diff --git a/.github/ISSUE_TEMPLATE/bug-report.md b/.github/ISSUE_TEMPLATE/bug-report.md
new file mode 100644
index 0000000000..a7371e02a6
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/bug-report.md
@@ -0,0 +1,43 @@
+---
+name: Bug report
+about: Create a report to help us fix issues.
+title: ''
+labels: 'Type: Bug'
+assignees: ''
+
+---
+
+
+
+**Application version**
+
+
+**Platform**
+
+
+**Printer**
+
+
+**Reproduction steps**
+
+
+**Actual results**
+
+
+**Expected results**
+
+
+**Additional information**
+
diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md
new file mode 100644
index 0000000000..2a0a3e4e7b
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/feature_request.md
@@ -0,0 +1,22 @@
+---
+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.**
+
+
+**Describe the solution you'd like**
+
+
+**Describe alternatives you've considered**
+
+
+**Affected users and/or printers**
+
+**Additional context**
+
diff --git a/.gitignore b/.gitignore
index 0a66b6eb33..2ec5af2b9b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -42,7 +42,6 @@ plugins/cura-siemensnx-plugin
plugins/CuraBlenderPlugin
plugins/CuraCloudPlugin
plugins/CuraDrivePlugin
-plugins/CuraDrive
plugins/CuraLiveScriptingPlugin
plugins/CuraOpenSCADPlugin
plugins/CuraPrintProfileCreator
@@ -72,3 +71,4 @@ run.sh
.scannerwork/
CuraEngine
+/.coverage
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 9e9bf4b538..b516de6b63 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")
@@ -17,15 +16,38 @@ if(CURA_DEBUGMODE)
set(_cura_debugmode "ON")
endif()
+set(CURA_APP_NAME "cura" CACHE STRING "Short name of Cura, used for configuration folder")
+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")
endif()
@@ -38,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)
+
if(NOT APPLE AND NOT WIN32)
install(FILES cura_app.py
DESTINATION ${CMAKE_INSTALL_BINDIR}
@@ -51,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)
@@ -76,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/Jenkinsfile b/Jenkinsfile
index 274e383ffa..a345ebbd05 100644
--- a/Jenkinsfile
+++ b/Jenkinsfile
@@ -1,8 +1,11 @@
-parallel_nodes(['linux && cura', 'windows && cura']) {
- timeout(time: 2, unit: "HOURS") {
+parallel_nodes(['linux && cura', 'windows && cura'])
+{
+ timeout(time: 2, unit: "HOURS")
+ {
// Prepare building
- stage('Prepare') {
+ stage('Prepare')
+ {
// Ensure we start with a clean build directory.
step([$class: 'WsCleanup'])
@@ -11,37 +14,17 @@ parallel_nodes(['linux && cura', 'windows && cura']) {
}
// If any error occurs during building, we want to catch it and continue with the "finale" stage.
- catchError {
- stage('Pre Checks') {
- if (isUnix()) {
- // Check shortcut keys
- try {
- sh """
- echo 'Check for duplicate shortcut keys in all translation files.'
- ${env.CURA_ENVIRONMENT_PATH}/master/bin/python3 scripts/check_shortcut_keys.py
- """
- } catch(e) {
- currentBuild.result = "UNSTABLE"
- }
-
- // Check setting visibilities
- try {
- sh """
- echo 'Check for duplicate shortcut keys in all translation files.'
- ${env.CURA_ENVIRONMENT_PATH}/master/bin/python3 scripts/check_setting_visibility.py
- """
- } catch(e) {
- currentBuild.result = "UNSTABLE"
- }
- }
- }
-
+ catchError
+ {
// Building and testing should happen in a subdirectory.
- dir('build') {
+ dir('build')
+ {
// Perform the "build". Since Uranium is Python code, this basically only ensures CMake is setup.
- stage('Build') {
+ stage('Build')
+ {
def branch = env.BRANCH_NAME
- if(!fileExists("${env.CURA_ENVIRONMENT_PATH}/${branch}")) {
+ if(!fileExists("${env.CURA_ENVIRONMENT_PATH}/${branch}"))
+ {
branch = "master"
}
@@ -51,52 +34,27 @@ parallel_nodes(['linux && cura', 'windows && cura']) {
}
// Try and run the unit tests. If this stage fails, we consider the build to be "unstable".
- stage('Unit Test') {
- if (isUnix()) {
- // For Linux to show everything
- def branch = env.BRANCH_NAME
- if(!fileExists("${env.CURA_ENVIRONMENT_PATH}/${branch}")) {
- branch = "master"
- }
- def uranium_dir = get_workspace_dir("Ultimaker/Uranium/${branch}")
-
+ stage('Unit Test')
+ {
+ if (isUnix())
+ {
+ // For Linux
try {
- sh """
- cd ..
- export PYTHONPATH=.:"${uranium_dir}"
- ${env.CURA_ENVIRONMENT_PATH}/${branch}/bin/pytest -x --verbose --full-trace --capture=no ./tests
- """
- } catch(e) {
+ sh 'make CTEST_OUTPUT_ON_FAILURE=TRUE test'
+ } catch(e)
+ {
currentBuild.result = "UNSTABLE"
}
}
- else {
+ else
+ {
// For Windows
- try {
+ try
+ {
// This also does code style checks.
bat 'ctest -V'
- } catch(e) {
- currentBuild.result = "UNSTABLE"
- }
- }
- }
-
- stage('Code Style') {
- if (isUnix()) {
- // For Linux to show everything
- def branch = env.BRANCH_NAME
- if(!fileExists("${env.CURA_ENVIRONMENT_PATH}/${branch}")) {
- branch = "master"
- }
- def uranium_dir = get_workspace_dir("Ultimaker/Uranium/${branch}")
-
- try {
- sh """
- cd ..
- export PYTHONPATH=.:"${uranium_dir}"
- ${env.CURA_ENVIRONMENT_PATH}/${branch}/bin/python3 run_mypy.py
- """
- } catch(e) {
+ } catch(e)
+ {
currentBuild.result = "UNSTABLE"
}
}
@@ -105,7 +63,8 @@ parallel_nodes(['linux && cura', 'windows && cura']) {
}
// Perform any post-build actions like notification and publishing of unit tests.
- stage('Finalize') {
+ stage('Finalize')
+ {
// Publish the test results to Jenkins.
junit allowEmptyResults: true, testResults: 'build/junit*.xml'
diff --git a/README.md b/README.md
index 70466e9c22..93abcc0c61 100644
--- a/README.md
+++ b/README.md
@@ -20,8 +20,9 @@ Dependencies
------------
* [Uranium](https://github.com/Ultimaker/Uranium) Cura is built on top of the Uranium framework.
* [CuraEngine](https://github.com/Ultimaker/CuraEngine) This will be needed at runtime to perform the actual slicing.
+* [fdm_materials](https://github.com/Ultimaker/fdm_materials) Required to load a printer that has swappable material profiles.
* [PySerial](https://github.com/pyserial/pyserial) Only required for USB printing support.
-* [python-zeroconf](https://github.com/jstasiak/python-zeroconf) Only required to detect mDNS-enabled printers
+* [python-zeroconf](https://github.com/jstasiak/python-zeroconf) Only required to detect mDNS-enabled printers.
Build scripts
-------------
diff --git a/cmake/CuraTests.cmake b/cmake/CuraTests.cmake
index 30794ed608..b1d3e0ddc4 100644
--- a/cmake/CuraTests.cmake
+++ b/cmake/CuraTests.cmake
@@ -1,10 +1,23 @@
# 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)
function(cura_add_test)
set(_single_args NAME DIRECTORY PYTHONPATH)
@@ -34,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}")
@@ -57,5 +70,13 @@ endforeach()
#Add code style test.
add_test(
NAME "code-style"
- COMMAND ${PYTHON_EXECUTABLE} run_mypy.py WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
-)
\ No newline at end of file
+ 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 ${Python3_EXECUTABLE} scripts/check_shortcut_keys.py
+ WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
+)
diff --git a/contributing.md b/contributing.md
new file mode 100644
index 0000000000..06f9dd472b
--- /dev/null
+++ b/contributing.md
@@ -0,0 +1,19 @@
+Submitting bug reports
+----------------------
+Please submit bug reports for all of Cura and CuraEngine to the [Cura repository](https://github.com/Ultimaker/Cura/issues). There will be a template there to fill in. Depending on the type of issue, we will usually ask for the [Cura log](Logging Issues) or a project file.
+
+If a bug report would contain private information, such as a proprietary 3D model, you may also e-mail us. Ask for contact information in the issue.
+
+Bugs related to supporting certain types of printers can usually not be solved by the Cura maintainers, since we don't have access to every 3D printer model in the world either. We have to rely on external contributors to fix this. If it's something simple and obvious, such as a mistake in the start g-code, then we can directly fix it for you, but e.g. issues with USB cable connectivity are impossible for us to debug.
+
+Requesting features
+-------------------
+The issue template in the Cura repository does not apply to feature requests. You can ignore it.
+
+When requesting a feature, please describe clearly what you need and why you think this is valuable to users or what problem it solves.
+
+Making pull requests
+--------------------
+If you want to propose a change to Cura's source code, please create a pull request in the appropriate repository (being [Cura](https://github.com/Ultimaker/Cura), [Uranium](https://github.com/Ultimaker/Uranium), [CuraEngine](https://github.com/Ultimaker/CuraEngine), [fdm_materials](https://github.com/Ultimaker/fdm_materials), [libArcus](https://github.com/Ultimaker/libArcus), [cura-build](https://github.com/Ultimaker/cura-build), [cura-build-environment](https://github.com/Ultimaker/cura-build-environment), [libSavitar](https://github.com/Ultimaker/libSavitar), [libCharon](https://github.com/Ultimaker/libCharon) or [cura-binary-data](https://github.com/Ultimaker/cura-binary-data)) and if your change requires changes on multiple of these repositories, please link them together so that we know to merge them together.
+
+Some of these repositories will have automated tests running when you create a pull request, indicated by green check marks or red crosses in the Github web page. If you see a red cross, that means that a test has failed. If the test doesn't fail on the Master branch but does fail on your branch, that indicates that you've probably made a mistake and you need to do that. Click on the cross for more details, or run the test locally by running `cmake . && ctest --verbose`.
\ No newline at end of file
diff --git a/cura.desktop.in b/cura.desktop.in
index fbe8b30fed..b0195015a5 100644
--- a/cura.desktop.in
+++ b/cura.desktop.in
@@ -13,6 +13,6 @@ 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;
+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;
Categories=Graphics;
Keywords=3D;Printing;Slicer;
diff --git a/cura.sharedmimeinfo b/cura.sharedmimeinfo
index 23d38795eb..ed9099d425 100644
--- a/cura.sharedmimeinfo
+++ b/cura.sharedmimeinfo
@@ -19,4 +19,12 @@
+
+
+ Gcode file
+
+
+
+
+
\ No newline at end of file
diff --git a/cura/API/Account.py b/cura/API/Account.py
index bc1ce8c2b9..0e3af0e6c1 100644
--- a/cura/API/Account.py
+++ b/cura/API/Account.py
@@ -6,6 +6,7 @@ from PyQt5.QtCore import QObject, pyqtSignal, pyqtSlot, pyqtProperty
from UM.i18n import i18nCatalog
from UM.Message import Message
+from cura import UltimakerCloudAuthentication
from cura.OAuth2.AuthorizationService import AuthorizationService
from cura.OAuth2.Models import OAuth2Settings
@@ -28,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)
@@ -37,15 +39,16 @@ class Account(QObject):
self._logged_in = False
self._callback_port = 32118
- self._oauth_root = "https://account.ultimaker.com"
- self._cloud_api_root = "https://api.ultimaker.com"
+ self._oauth_root = UltimakerCloudAuthentication.CuraCloudAccountAPIRoot
self._oauth_settings = OAuth2Settings(
OAUTH_SERVER_URL= self._oauth_root,
CALLBACK_PORT=self._callback_port,
CALLBACK_URL="http://localhost:{}/callback".format(self._callback_port),
- CLIENT_ID="um---------------ultimaker_cura_drive_plugin",
- CLIENT_SCOPES="user.read drive.backups.read drive.backups.write",
+ CLIENT_ID="um----------------------------ultimaker_cura",
+ CLIENT_SCOPES="account.user.read drive.backup.read drive.backup.write packages.download "
+ "packages.rating.read packages.rating.write connect.cluster.read connect.cluster.write "
+ "cura.printjob.read cura.printjob.write cura.mesh.read cura.mesh.write",
AUTH_DATA_PREFERENCE_KEY="general/ultimaker_auth_data",
AUTH_SUCCESS_REDIRECT="{}/app/auth-success".format(self._oauth_root),
AUTH_FAILED_REDIRECT="{}/app/auth-error".format(self._oauth_root)
@@ -55,11 +58,19 @@ class Account(QObject):
def initialize(self) -> None:
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:
+ return "staging" in self._oauth_root
+
@pyqtProperty(bool, notify=loginStateChanged)
def isLoggedIn(self) -> bool:
return self._logged_in
@@ -70,6 +81,9 @@ class Account(QObject):
self._error_message.hide()
self._error_message = Message(error_message, title = i18n_catalog.i18nc("@info:title", "Login failed"))
self._error_message.show()
+ self._logged_in = False
+ self.loginStateChanged.emit(False)
+ return
if self._logged_in != logged_in:
self._logged_in = logged_in
@@ -96,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/API/Backups.py b/cura/API/Backups.py
index 8e5cd7b83a..ef74e74be0 100644
--- a/cura/API/Backups.py
+++ b/cura/API/Backups.py
@@ -1,6 +1,6 @@
# Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
-from typing import Tuple, Optional, TYPE_CHECKING
+from typing import Tuple, Optional, TYPE_CHECKING, Dict, Any
from cura.Backups.BackupsManager import BackupsManager
@@ -24,12 +24,12 @@ class Backups:
## Create a new back-up using the BackupsManager.
# \return Tuple containing a ZIP file with the back-up data and a dict
# with metadata about the back-up.
- def createBackup(self) -> Tuple[Optional[bytes], Optional[dict]]:
+ def createBackup(self) -> Tuple[Optional[bytes], Optional[Dict[str, Any]]]:
return self.manager.createBackup()
## Restore a back-up using the BackupsManager.
# \param zip_file A ZIP file containing the actual back-up data.
# \param meta_data Some metadata needed for restoring a back-up, like the
# Cura version number.
- def restoreBackup(self, zip_file: bytes, meta_data: dict) -> None:
+ def restoreBackup(self, zip_file: bytes, meta_data: Dict[str, Any]) -> None:
return self.manager.restoreBackup(zip_file, meta_data)
diff --git a/cura/API/Interface/__init__.py b/cura/API/Interface/__init__.py
index 742254a1a4..cec174bf0a 100644
--- a/cura/API/Interface/__init__.py
+++ b/cura/API/Interface/__init__.py
@@ -3,7 +3,6 @@
from typing import TYPE_CHECKING
-from UM.PluginRegistry import PluginRegistry
from cura.API.Interface.Settings import Settings
if TYPE_CHECKING:
@@ -23,9 +22,6 @@ if TYPE_CHECKING:
class Interface:
- # For now we use the same API version to be consistent.
- VERSION = PluginRegistry.APIVersion
-
def __init__(self, application: "CuraApplication") -> None:
# API methods specific to the settings portion of the UI
self.settings = Settings(application)
diff --git a/cura/API/__init__.py b/cura/API/__init__.py
index ad07452c1a..b3e702263a 100644
--- a/cura/API/__init__.py
+++ b/cura/API/__init__.py
@@ -4,7 +4,6 @@ from typing import Optional, TYPE_CHECKING
from PyQt5.QtCore import QObject, pyqtProperty
-from UM.PluginRegistry import PluginRegistry
from cura.API.Backups import Backups
from cura.API.Interface import Interface
from cura.API.Account import Account
@@ -22,7 +21,6 @@ if TYPE_CHECKING:
class CuraAPI(QObject):
# For now we use the same API version to be consistent.
- VERSION = PluginRegistry.APIVersion
__instance = None # type: "CuraAPI"
_application = None # type: CuraApplication
@@ -62,4 +60,4 @@ class CuraAPI(QObject):
@property
def interface(self) -> "Interface":
- return self._interface
\ No newline at end of file
+ return self._interface
diff --git a/cura/ApplicationMetadata.py b/cura/ApplicationMetadata.py
new file mode 100644
index 0000000000..eeb283a72b
--- /dev/null
+++ b/cura/ApplicationMetadata.py
@@ -0,0 +1,48 @@
+# Copyright (c) 2018 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+
+# ---------
+# General constants used in Cura
+# ---------
+DEFAULT_CURA_APP_NAME = "cura"
+DEFAULT_CURA_DISPLAY_NAME = "Ultimaker Cura"
+DEFAULT_CURA_VERSION = "master"
+DEFAULT_CURA_BUILD_TYPE = ""
+DEFAULT_CURA_DEBUG_MODE = False
+DEFAULT_CURA_SDK_VERSION = "6.2.0"
+
+try:
+ from cura.CuraVersion import CuraAppName # type: ignore
+ if CuraAppName == "":
+ CuraAppName = DEFAULT_CURA_APP_NAME
+except ImportError:
+ CuraAppName = DEFAULT_CURA_APP_NAME
+
+try:
+ from cura.CuraVersion import CuraAppDisplayName # type: ignore
+ if CuraAppDisplayName == "":
+ CuraAppDisplayName = DEFAULT_CURA_DISPLAY_NAME
+except ImportError:
+ CuraAppDisplayName = DEFAULT_CURA_DISPLAY_NAME
+
+try:
+ from cura.CuraVersion import CuraVersion # type: ignore
+ if CuraVersion == "":
+ CuraVersion = DEFAULT_CURA_VERSION
+except ImportError:
+ CuraVersion = DEFAULT_CURA_VERSION # [CodeStyle: Reflecting imported value]
+
+try:
+ from cura.CuraVersion import CuraBuildType # type: ignore
+except ImportError:
+ CuraBuildType = DEFAULT_CURA_BUILD_TYPE
+
+try:
+ from cura.CuraVersion import CuraDebugMode # type: ignore
+except ImportError:
+ CuraDebugMode = DEFAULT_CURA_DEBUG_MODE
+
+# 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 = "6.2.0"
diff --git a/cura/Arranging/Arrange.py b/cura/Arranging/Arrange.py
index 5657ee991a..caa7aae910 100644
--- a/cura/Arranging/Arrange.py
+++ b/cura/Arranging/Arrange.py
@@ -66,6 +66,11 @@ class Arrange:
continue
vertices = vertices.getMinkowskiHull(Polygon.approximatedCircle(min_offset))
points = copy.deepcopy(vertices._points)
+
+ # After scaling (like up to 0.1 mm) the node might not have points
+ if len(points) == 0:
+ continue
+
shape_arr = ShapeArray.fromPolygon(points, scale = scale)
arranger.place(0, 0, shape_arr)
@@ -212,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/ArrangeObjectsJob.py b/cura/Arranging/ArrangeObjectsJob.py
index ce11556b5b..aef051c838 100644
--- a/cura/Arranging/ArrangeObjectsJob.py
+++ b/cura/Arranging/ArrangeObjectsJob.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.
from UM.Application import Application
@@ -39,10 +39,17 @@ class ArrangeObjectsJob(Job):
arranger = Arrange.create(x = machine_width, y = machine_depth, fixed_nodes = self._fixed_nodes, min_offset = self._min_offset)
+ # Build set to exclude children (those get arranged together with the parents).
+ included_as_child = set()
+ for node in self._nodes:
+ included_as_child.update(node.getAllChildren())
+
# Collect nodes to be placed
nodes_arr = [] # fill with (size, node, offset_shape_arr, hull_shape_arr)
for node in self._nodes:
- offset_shape_arr, hull_shape_arr = ShapeArray.fromNode(node, min_offset = self._min_offset)
+ if node in included_as_child:
+ continue
+ offset_shape_arr, hull_shape_arr = ShapeArray.fromNode(node, min_offset = self._min_offset, include_children = True)
if offset_shape_arr is None:
Logger.log("w", "Node [%s] could not be converted to an array for arranging...", str(node))
continue
diff --git a/cura/Arranging/ShapeArray.py b/cura/Arranging/ShapeArray.py
index ab785cc3e1..9227e446fb 100644
--- a/cura/Arranging/ShapeArray.py
+++ b/cura/Arranging/ShapeArray.py
@@ -1,12 +1,18 @@
+#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 +22,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 +48,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):
+ 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]
@@ -52,6 +58,21 @@ class ShapeArray:
return None, None
# For one_at_a_time printing you need the convex hull head.
hull_head_verts = node.callDecoration("getConvexHullHead") or hull_verts
+ if hull_head_verts is None:
+ hull_head_verts = Polygon()
+
+ # If the child-nodes are included, adjust convex hulls as well:
+ if include_children:
+ children = node.getAllChildren()
+ if not children is None:
+ for child in children:
+ # 'Inefficient' combination of convex hulls through known code rather than mess it up:
+ child_hull = child.callDecoration("getConvexHull")
+ if not child_hull is None:
+ hull_verts = hull_verts.unionConvexHulls(child_hull)
+ child_hull_head = child.callDecoration("getConvexHullHead") or child_hull
+ if not child_hull_head is None:
+ hull_head_verts = hull_head_verts.unionConvexHulls(child_hull_head)
offset_verts = hull_head_verts.getMinkowskiHull(Polygon.approximatedCircle(min_offset))
offset_points = copy.deepcopy(offset_verts._points) # x, y
@@ -73,7 +94,7 @@ 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
@@ -96,9 +117,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) -> bool:
if p1[0] == p2[0] and p1[1] == p2[1]:
- return
+ return False
idxs = numpy.indices(base_array.shape) # Create 3D array of indices
p1 = p1.astype(float)
@@ -116,5 +137,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 897d5fa979..9ccdcaf64d 100644
--- a/cura/Backups/Backup.py
+++ b/cura/Backups/Backup.py
@@ -46,12 +46,13 @@ class Backup:
# We copy the preferences file to the user data directory in Linux as it's in a different location there.
# When restoring a backup on Linux, we move it back.
- if Platform.isLinux():
+ if Platform.isLinux(): #TODO: This should check for the config directory not being the same as the data directory, rather than hard-coding that to Linux systems.
preferences_file_name = self._application.getApplicationName()
preferences_file = Resources.getPath(Resources.Preferences, "{}.cfg".format(preferences_file_name))
backup_preferences_file = os.path.join(version_data_dir, "{}.cfg".format(preferences_file_name))
- Logger.log("d", "Copying preferences file from %s to %s", preferences_file, backup_preferences_file)
- shutil.copyfile(preferences_file, backup_preferences_file)
+ if os.path.exists(preferences_file) and (not os.path.exists(backup_preferences_file) or not os.path.samefile(preferences_file, backup_preferences_file)):
+ Logger.log("d", "Copying preferences file from %s to %s", preferences_file, backup_preferences_file)
+ shutil.copyfile(preferences_file, backup_preferences_file)
# Create an empty buffer and write the archive to it.
buffer = io.BytesIO()
@@ -115,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()
@@ -146,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 547c3dae71..ed211ed7b4 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.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,20 @@ 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 +43,46 @@ 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._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,8 +90,15 @@ 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)
+ self._stack_change_timer.setSingleShot(True)
+ self._stack_change_timer.timeout.connect(self._onStackChangeTimerFinished)
+
self._application.globalContainerStackChanged.connect(self._onStackChanged)
+
self._onStackChanged()
self._engine_ready = False
@@ -93,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,12 +132,14 @@ class BuildVolume(SceneNode):
# 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:
- self._scene_change_timer.start()
+ # Ignore anything that is not something we can slice in the first place!
+ if source.callDecoration("isSliceable"):
+ self._scene_change_timer.start()
def _onSceneChangeTimerFinished(self):
root = self._application.getController().getScene().getRoot()
@@ -139,7 +156,7 @@ class BuildVolume(SceneNode):
if active_extruder_changed is not None:
node.callDecoration("getActiveExtruderChangedSignal").disconnect(self._updateDisallowedAreasAndRebuild)
node.decoratorsChanged.disconnect(self._updateNodeListeners)
- self._updateDisallowedAreasAndRebuild() # make sure we didn't miss anything before we updated the node listeners
+ self.rebuild()
self._scene_objects = new_scene_objects
self._onSettingPropertyChanged("print_sequence", "value") # Create fake event, so right settings are triggered.
@@ -156,16 +173,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:
@@ -213,13 +227,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
@@ -232,14 +251,21 @@ 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:
@@ -265,8 +291,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:
@@ -286,7 +312,7 @@ class BuildVolume(SceneNode):
node.setOutsideBuildArea(True)
return
- if node.collidesWithArea(self.getDisallowedAreas()):
+ if node.collidesWithAreas(self.getDisallowedAreas()):
node.setOutsideBuildArea(True)
return
@@ -298,32 +324,43 @@ class BuildVolume(SceneNode):
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()
@@ -342,25 +379,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
@@ -369,23 +391,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"):
@@ -393,77 +511,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),
@@ -475,28 +529,35 @@ 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 # 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
- self._adhesion_type = self._global_container_stack.getProperty("adhesion_type", "value")
+ if self._global_container_stack.extruders:
+ # 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
if self._adhesion_type == "raft":
self._raft_thickness = (
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"))
@@ -505,25 +566,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 _onStackChanged(self):
+ def _onStackChangeTimerFinished(self) -> None:
if self._global_container_stack:
self._global_container_stack.propertyChanged.disconnect(self._onSettingPropertyChanged)
extruders = ExtruderManager.getInstance().getActiveExtruderStacks()
@@ -554,7 +613,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()
@@ -563,20 +622,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:
@@ -589,33 +651,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:
@@ -625,7 +680,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()
@@ -633,7 +688,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
@@ -644,6 +699,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.
#
@@ -651,60 +714,30 @@ class BuildVolume(SceneNode):
# ``_updateDisallowedAreas`` method itself shouldn't call ``rebuild``,
# since there may be other changes before it needs to be rebuilt, which
# would hit performance.
+
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])
@@ -712,29 +745,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 prime_tower_area in 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 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
@@ -755,11 +787,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")
@@ -769,17 +804,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 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],
- ])
+ 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 = (
+ 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
+
+ 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.
@@ -797,9 +834,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:
@@ -807,13 +845,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)
@@ -836,9 +874,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))
@@ -849,7 +890,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")
@@ -858,13 +899,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
@@ -872,7 +913,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:
@@ -956,8 +998,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)))
@@ -969,14 +1011,86 @@ 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
+ def _calculateBedAdhesionSize(self, used_extruders):
+ if self._global_container_stack is None:
+ return
+
+ container_stack = self._global_container_stack
+ 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")
+ # 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
+
+ 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 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?")
+
+ max_length_available = 0.5 * min(
+ self._global_container_stack.getProperty("machine_width", "value"),
+ 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
+
+ def _calculateMoveFromWallRadius(self, used_extruders):
+ move_from_wall_radius = 0 # Moves that start from outer wall.
+ 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).
+ 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
@@ -993,59 +1107,10 @@ class BuildVolume(SceneNode):
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":
- 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
-
- 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 brim 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?")
-
- 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
-
- 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"))
-
- 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]
- 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).
- if avoid_other_parts_enabled:
- move_from_wall_radius = max(move_from_wall_radius, avoid_distance)
+ 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.
@@ -1061,8 +1126,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"]
+ _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/CameraImageProvider.py b/cura/CameraImageProvider.py
deleted file mode 100644
index 6a07f6b029..0000000000
--- a/cura/CameraImageProvider.py
+++ /dev/null
@@ -1,29 +0,0 @@
-from PyQt5.QtGui import QImage
-from PyQt5.QtQuick import QQuickImageProvider
-from PyQt5.QtCore import QSize
-
-from UM.Application import Application
-
-
-class CameraImageProvider(QQuickImageProvider):
- def __init__(self):
- super().__init__(QQuickImageProvider.Image)
-
- ## Request a new image.
- def requestImage(self, id, size):
- for output_device in Application.getInstance().getOutputDeviceManager().getOutputDevices():
- try:
- image = output_device.activePrinter.camera.getImage()
- if image.isNull():
- image = QImage()
-
- return image, QSize(15, 15)
- except AttributeError:
- try:
- image = output_device.activeCamera.getImage()
-
- return image, QSize(15, 15)
- except AttributeError:
- pass
-
- return QImage(), QSize(15, 15)
diff --git a/cura/CrashHandler.py b/cura/CrashHandler.py
index 46544ca0ef..6e6da99b0f 100644
--- a/cura/CrashHandler.py
+++ b/cura/CrashHandler.py
@@ -36,18 +36,14 @@ else:
except ImportError:
CuraDebugMode = False # [CodeStyle: Reflecting imported value]
-# List of exceptions that should be considered "fatal" and abort the program.
-# These are primarily some exception types that we simply cannot really recover from
-# (MemoryError and SystemError) and exceptions that indicate grave errors in the
-# code that cause the Python interpreter to fail (SyntaxError, ImportError).
-fatal_exception_types = [
- MemoryError,
- SyntaxError,
- ImportError,
- SystemError,
+# List of exceptions that should not be considered "fatal" and abort the program.
+# These are primarily some exception types that we simply skip
+skip_exception_types = [
+ SystemExit,
+ KeyboardInterrupt,
+ GeneratorExit
]
-
class CrashHandler:
crash_url = "https://stats.ultimaker.com/api/cura"
@@ -70,7 +66,7 @@ class CrashHandler:
# If Cura has fully started, we only show fatal errors.
# If Cura has not fully started yet, we always show the early crash dialog. Otherwise, Cura will just crash
# without any information.
- if has_started and exception_type not in fatal_exception_types:
+ if has_started and exception_type in skip_exception_types:
return
if not has_started:
@@ -323,7 +319,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
@@ -387,7 +384,7 @@ class CrashHandler:
Application.getInstance().callLater(self._show)
def _show(self):
- # When the exception is not in the fatal_exception_types list, the dialog is not created, so we don't need to show it
+ # When the exception is in the skip_exception_types list, the dialog is not created, so we don't need to show it
if self.dialog:
self.dialog.exec_()
os._exit(1)
diff --git a/cura/CuraActions.py b/cura/CuraActions.py
index 93a18318df..20c44c7916 100644
--- a/cura/CuraActions.py
+++ b/cura/CuraActions.py
@@ -3,7 +3,7 @@
from PyQt5.QtCore import QObject, QUrl
from PyQt5.QtGui import QDesktopServices
-from typing import List, TYPE_CHECKING
+from typing import List, cast
from UM.Event import CallFunctionEvent
from UM.FlameProfiler import pyqtSlot
@@ -23,9 +23,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:
@@ -36,12 +35,12 @@ class CuraActions(QObject):
# Starting a web browser from a signal handler connected to a menu will crash on windows.
# So instead, defer the call to the next run of the event loop, since that does work.
# Note that weirdly enough, only signal handlers that open a web browser fail like that.
- event = CallFunctionEvent(self._openUrl, [QUrl("http://ultimaker.com/en/support/software")], {})
+ event = CallFunctionEvent(self._openUrl, [QUrl("https://ultimaker.com/en/resources/manuals/software")], {})
cura.CuraApplication.CuraApplication.getInstance().functionEvent(event)
@pyqtSlot()
def openBugReportPage(self) -> None:
- event = CallFunctionEvent(self._openUrl, [QUrl("http://github.com/Ultimaker/Cura/issues")], {})
+ event = CallFunctionEvent(self._openUrl, [QUrl("https://github.com/Ultimaker/Cura/issues")], {})
cura.CuraApplication.CuraApplication.getInstance().functionEvent(event)
## Reset camera position and direction to default
@@ -61,8 +60,10 @@ class CuraActions(QObject):
operation = GroupedOperation()
for node in Selection.getAllSelectedObjects():
current_node = node
- while current_node.getParent() and current_node.getParent().callDecoration("isGroup"):
- current_node = current_node.getParent()
+ parent_node = current_node.getParent()
+ while parent_node and parent_node.callDecoration("isGroup"):
+ current_node = parent_node
+ parent_node = current_node.getParent()
# This was formerly done with SetTransformOperation but because of
# unpredictable matrix deconstruction it was possible that mirrors
@@ -150,13 +151,13 @@ class CuraActions(QObject):
root = cura.CuraApplication.CuraApplication.getInstance().getController().getScene().getRoot()
- nodes_to_change = []
+ nodes_to_change = [] # type: List[SceneNode]
for node in Selection.getAllSelectedObjects():
parent_node = node # Find the parent node to change instead
while parent_node.getParent() != root:
- parent_node = parent_node.getParent()
+ parent_node = cast(SceneNode, parent_node.getParent())
- for single_node in BreadthFirstIterator(parent_node): #type: ignore #Ignore type error because iter() should get called automatically by Python syntax.
+ for single_node in BreadthFirstIterator(parent_node): # type: ignore #Ignore type error because iter() should get called automatically by Python syntax.
nodes_to_change.append(single_node)
if not nodes_to_change:
diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py
index 0b2940044f..d477454e2b 100755
--- a/cura/CuraApplication.py
+++ b/cura/CuraApplication.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.
import os
import sys
import time
-from typing import cast, TYPE_CHECKING, Optional
+from typing import cast, TYPE_CHECKING, Optional, Callable, List
import numpy
@@ -13,131 +13,138 @@ 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
+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.Bindings import MainWindow
+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.Decorators import deprecated
from UM.Operations.AddSceneNodeOperation import AddSceneNodeOperation
-from UM.Operations.RemoveSceneNodeOperation import RemoveSceneNodeOperation
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.ContainerStack import ContainerStack
+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.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 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.Scene.CuraSceneNode import CuraSceneNode
+from cura.Scene.SliceableObjectDecorator import SliceableObjectDecorator
+from cura.Scene import ZOffsetDecorator
from cura.Machines.MachineErrorChecker import MachineErrorChecker
+from cura.Machines.VariantManager import VariantManager
+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.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.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.MachineManager import MachineManager
+from cura.Settings.MachineNameValidator import MachineNameValidator
+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 CameraImageProvider
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 UM.FlameProfiler import pyqtSlot
+from cura import ApplicationMetadata, UltimakerCloudAuthentication
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")
-try:
- from cura.CuraVersion import CuraVersion, CuraBuildType, CuraDebugMode, CuraSDKVersion
-except ImportError:
- CuraVersion = "master" # [CodeStyle: Reflecting imported value]
- CuraBuildType = ""
- CuraDebugMode = False
- CuraSDKVersion = ""
-
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 = 5
+ SettingVersion = 9
Created = False
@@ -157,15 +164,19 @@ class CuraApplication(QtApplication):
Q_ENUMS(ResourceTypes)
def __init__(self, *args, **kwargs):
- super().__init__(name = "cura",
- version = CuraVersion,
- buildtype = CuraBuildType,
- is_debug_mode = CuraDebugMode,
+ super().__init__(name = ApplicationMetadata.CuraAppName,
+ app_display_name = ApplicationMetadata.CuraAppDisplayName,
+ version = ApplicationMetadata.CuraVersion,
+ api_version = ApplicationMetadata.CuraSDKVersion,
+ buildtype = ApplicationMetadata.CuraBuildType,
+ is_debug_mode = ApplicationMetadata.CuraDebugMode,
tray_icon_name = "cura-icon-32.png",
**kwargs)
self.default_theme = "cura-light"
+ self.change_log_url = "https://ultimaker.com/ultimaker-cura-latest-features"
+
self._boot_loading_time = time.time()
self._on_exit_callback_manager = OnExitCallbackManager(self)
@@ -173,7 +184,6 @@ class CuraApplication(QtApplication):
# Variables set from CLI
self._files_to_open = []
self._use_single_instance = False
- self._trigger_early_crash = False # For debug only
self._single_instance = None
@@ -198,6 +208,8 @@ class CuraApplication(QtApplication):
self._container_manager = None
self._object_manager = None
+ self._extruders_model = None
+ self._extruders_model_with_optional = None
self._build_plate_model = None
self._multi_build_plate_model = None
self._setting_visibility_presets_model = None
@@ -206,6 +218,15 @@ class CuraApplication(QtApplication):
self._cura_scene_controller = None
self._machine_error_checker = None
+ self._machine_settings_manager = MachineSettingsManager(self, parent = self)
+
+ self._discovered_printer_model = DiscoveredPrintersModel(self, parent = self)
+ self._first_start_machine_actions_model = FirstStartMachineActionsModel(self, parent = self)
+ 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)
@@ -235,15 +256,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
@@ -252,6 +270,14 @@ class CuraApplication(QtApplication):
from cura.CuraPackageManager import CuraPackageManager
self._package_manager_class = CuraPackageManager
+ @pyqtProperty(str, constant=True)
+ def ultimakerCloudApiRootUrl(self) -> str:
+ return UltimakerCloudAuthentication.CuraCloudAPIRoot
+
+ @pyqtProperty(str, constant = True)
+ def ultimakerCloudAccountRootUrl(self) -> str:
+ return UltimakerCloudAuthentication.CuraCloudAccountAPIRoot
+
# Adds command line options to the command line parser. This should be called after the application is created and
# before the pre-start.
def addCommandLineOptions(self):
@@ -284,7 +310,10 @@ class CuraApplication(QtApplication):
sys.exit(0)
self._use_single_instance = self._cli_args.single_instance
- self._trigger_early_crash = self._cli_args.trigger_early_crash
+ # FOR TESTING ONLY
+ if self._cli_args.trigger_early_crash:
+ assert not "This crash is triggered by the trigger_early_crash command line argument."
+
for filename in self._cli_args.file:
self._files_to_open.append(os.path.abspath(filename))
@@ -294,7 +323,8 @@ class CuraApplication(QtApplication):
super().initialize()
self.__sendCommandToSingleInstance()
- self.__initializeSettingDefinitionsAndFunctions()
+ self._initializeSettingDefinitions()
+ self._initializeSettingFunctions()
self.__addAllResourcesAndContainerResources()
self.__addAllEmptyContainers()
self.__setLatestResouceVersionsForVersionUpgrade()
@@ -302,8 +332,6 @@ class CuraApplication(QtApplication):
self._machine_action_manager = MachineActionManager.MachineActionManager(self)
self._machine_action_manager.initialize()
- self.change_log_url = "https://ultimaker.com/ultimaker-cura-latest-features"
-
def __sendCommandToSingleInstance(self):
self._single_instance = SingleInstance(self, self._files_to_open)
@@ -325,31 +353,40 @@ class CuraApplication(QtApplication):
resource_path = os.path.join(os.path.abspath(os.path.dirname(__file__)), "..", "resources")
Resources.addSearchPath(resource_path)
- # Adds custom property types, settings types, and extra operators (functions) that need to be registered in
- # SettingDefinition and SettingFunction.
- def __initializeSettingDefinitionsAndFunctions(self):
- self._cura_formula_functions = CuraFormulaFunctions(self)
-
+ @classmethod
+ def _initializeSettingDefinitions(cls):
# Need to do this before ContainerRegistry tries to load the machines
- SettingDefinition.addSupportedProperty("settable_per_mesh", DefinitionPropertyType.Any, default = True, read_only = True)
- SettingDefinition.addSupportedProperty("settable_per_extruder", DefinitionPropertyType.Any, default = True, read_only = True)
+ SettingDefinition.addSupportedProperty("settable_per_mesh", DefinitionPropertyType.Any, default=True,
+ read_only=True)
+ SettingDefinition.addSupportedProperty("settable_per_extruder", DefinitionPropertyType.Any, default=True,
+ read_only=True)
# this setting can be changed for each group in one-at-a-time mode
- SettingDefinition.addSupportedProperty("settable_per_meshgroup", DefinitionPropertyType.Any, default = True, read_only = True)
- SettingDefinition.addSupportedProperty("settable_globally", DefinitionPropertyType.Any, default = True, read_only = True)
+ SettingDefinition.addSupportedProperty("settable_per_meshgroup", DefinitionPropertyType.Any, default=True,
+ read_only=True)
+ SettingDefinition.addSupportedProperty("settable_globally", DefinitionPropertyType.Any, default=True,
+ read_only=True)
# From which stack the setting would inherit if not defined per object (handled in the engine)
# AND for settings which are not settable_per_mesh:
# which extruder is the only extruder this setting is obtained from
- SettingDefinition.addSupportedProperty("limit_to_extruder", DefinitionPropertyType.Function, default = "-1", depends_on = "value")
+ SettingDefinition.addSupportedProperty("limit_to_extruder", DefinitionPropertyType.Function, default="-1",
+ depends_on="value")
# For settings which are not settable_per_mesh and not settable_per_extruder:
# A function which determines the glabel/meshgroup value by looking at the values of the setting in all (used) extruders
- SettingDefinition.addSupportedProperty("resolve", DefinitionPropertyType.Function, default = None, depends_on = "value")
+ SettingDefinition.addSupportedProperty("resolve", DefinitionPropertyType.Function, default=None,
+ depends_on="value")
SettingDefinition.addSettingType("extruder", None, str, Validator)
SettingDefinition.addSettingType("optional_extruder", None, str, None)
SettingDefinition.addSettingType("[int]", None, str, None)
+
+ # Adds custom property types, settings types, and extra operators (functions) that need to be registered in
+ # SettingDefinition and SettingFunction.
+ def _initializeSettingFunctions(self):
+ self._cura_formula_functions = CuraFormulaFunctions(self)
+
SettingFunction.registerOperator("extruderValue", self._cura_formula_functions.getValueInExtruder)
SettingFunction.registerOperator("extruderValues", self._cura_formula_functions.getValuesInAllExtruders)
SettingFunction.registerOperator("resolveOrValue", self._cura_formula_functions.getResolveOrValue)
@@ -384,7 +421,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)
@@ -419,41 +456,38 @@ class CuraApplication(QtApplication):
)
# Runs preparations that needs to be done before the starting process.
- def startSplashWindowPhase(self):
+ def startSplashWindowPhase(self) -> None:
super().startSplashWindowPhase()
- self.setWindowIcon(QIcon(Resources.getPath(Resources.Images, "cura-icon.png")))
+ if not self.getIsHeadLess():
+ self.setWindowIcon(QIcon(Resources.getPath(Resources.Images, "cura-icon.png")))
self.setRequiredPlugins([
# Misc.:
- "ConsoleLogger",
- "CuraEngineBackend",
- "UserAgreement",
- "FileLogger",
- "XmlMaterialProfile",
- "Toolbox",
- "PrepareStage",
- "MonitorStage",
- "LocalFileOutputDevice",
- "LocalContainerProvider",
+ "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.
+ "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.
+ "PrepareStage", #Cura is useless without this one since you can't load models.
+ "PreviewStage", #This shows the list of the plugin views that are installed in Cura.
+ "MonitorStage", #Major part of Cura's functionality.
+ "LocalFileOutputDevice", #Major part of Cura's functionality.
+ "LocalContainerProvider", #Cura is useless without any profiles or setting definitions.
# Views:
- "SimpleView",
- "SimulationView",
- "SolidView",
+ "SimpleView", #Dependency of SolidView.
+ "SolidView", #Displays models. Cura is useless without it.
# Readers & Writers:
- "GCodeWriter",
- "STLReader",
- "3MFWriter",
+ "GCodeWriter", #Cura is useless if it can't write its output.
+ "STLReader", #Most common model format, so disabling this makes Cura 90% useless.
+ "3MFWriter", #Required for writing project files.
# Tools:
- "CameraTool",
- "MirrorTool",
- "RotateTool",
- "ScaleTool",
- "SelectionTool",
- "TranslateTool",
+ "CameraTool", #Needed to see the scene. Cura is useless without it.
+ "SelectionTool", #Dependency of the rest of the tools.
+ "TranslateTool", #You'll need this for almost every print.
])
self._i18n_catalog = i18nCatalog("cura")
@@ -490,7 +524,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", "{}")
@@ -502,7 +542,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
@@ -521,19 +561,25 @@ class CuraApplication(QtApplication):
CuraApplication.Created = True
def _onEngineCreated(self):
- self._qml_engine.addImageProvider("camera", CameraImageProvider.CameraImageProvider())
self._qml_engine.addImageProvider("print_job_preview", PrintJobPreviewImageProvider.PrintJobPreviewImageProvider())
@pyqtProperty(bool)
- def needToShowUserAgreement(self):
- return self._need_to_show_user_agreement
+ def needToShowUserAgreement(self) -> bool:
+ return not UM.Util.parseBool(self.getPreferences().getValue("general/accepted_user_agreement"))
- def setNeedToShowUserAgreement(self, set_value = True):
- 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.
- def closeApplication(self):
+ # 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()
if main_window is not None:
@@ -560,11 +606,11 @@ class CuraApplication(QtApplication):
showConfirmExitDialog = pyqtSignal(str, arguments = ["message"])
- def setConfirmExitDialogCallback(self, callback):
+ def setConfirmExitDialogCallback(self, callback: Callable) -> None:
self._confirm_exit_dialog_callback = callback
@pyqtSlot(bool)
- def callConfirmExitDialogCallback(self, yes_or_no: bool):
+ def callConfirmExitDialogCallback(self, yes_or_no: bool) -> None:
self._confirm_exit_dialog_callback(yes_or_no)
## Signal to connect preferences action in QML
@@ -572,9 +618,17 @@ class CuraApplication(QtApplication):
## Show the preferences window
@pyqtSlot()
- def showPreferences(self):
+ def showPreferences(self) -> None:
self.showPreferencesWindow.emit()
+ @override(Application)
+ def getGlobalContainerStack(self) -> Optional["GlobalStack"]:
+ return self._global_container_stack
+
+ @override(Application)
+ def setGlobalContainerStack(self, stack: "GlobalStack") -> None:
+ super().setGlobalContainerStack(stack)
+
## A reusable dialogbox
#
showMessageBox = pyqtSignal(str, str, str, str, int, int, arguments = ["title", "text", "informativeText", "detailedText", "buttons", "icon"])
@@ -586,7 +640,7 @@ class CuraApplication(QtApplication):
showDiscardOrKeepProfileChanges = pyqtSignal()
- def discardOrKeepProfileChanges(self):
+ def discardOrKeepProfileChanges(self) -> bool:
has_user_interaction = False
choice = self.getPreferences().getValue("cura/choice_on_profile_override")
if choice == "always_discard":
@@ -602,7 +656,7 @@ class CuraApplication(QtApplication):
return has_user_interaction
@pyqtSlot(str)
- def discardOrKeepProfileChangesClosed(self, option):
+ def discardOrKeepProfileChangesClosed(self, option: str) -> None:
global_stack = self.getGlobalContainerStack()
if option == "discard":
for extruder in global_stack.extruders.values():
@@ -623,14 +677,9 @@ class CuraApplication(QtApplication):
self._message_box_callback = None
self._message_box_callback_arguments = []
- showPrintMonitor = pyqtSignal(bool, arguments = ["show"])
-
- 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()
@@ -650,12 +699,12 @@ class CuraApplication(QtApplication):
## Handle loading of all plugin types (and the backend explicitly)
# \sa PluginRegistry
- def _loadPlugins(self):
+ def _loadPlugins(self) -> None:
self._plugin_registry.addType("profile_reader", self._addProfileReader)
self._plugin_registry.addType("profile_writer", self._addProfileWriter)
if Platform.isLinux():
- lib_suffixes = {"", "64", "32", "x32"} #A few common ones on different distributions.
+ lib_suffixes = {"", "64", "32", "x32"} # A few common ones on different distributions.
else:
lib_suffixes = {""}
for suffix in lib_suffixes:
@@ -691,7 +740,7 @@ class CuraApplication(QtApplication):
self._quality_manager.initialize()
Logger.log("i", "Initializing machine manager")
- self._machine_manager = MachineManager(self)
+ self._machine_manager = MachineManager(self, parent = self)
Logger.log("i", "Initializing container manager")
self._container_manager = ContainerManager(self)
@@ -714,14 +763,17 @@ class CuraApplication(QtApplication):
self._print_information = PrintInformation.PrintInformation(self)
self._cura_actions = CuraActions.CuraActions(self)
- # Initialize setting visibility presets model
- self._setting_visibility_presets_model = SettingVisibilityPresetsModel(self)
- default_visibility_profile = self._setting_visibility_presets_model.getItem(0)
- self.getPreferences().setDefault("general/visible_settings", ";".join(default_visibility_profile["settings"]))
+ # Initialize setting visibility presets model.
+ self._setting_visibility_presets_model = SettingVisibilityPresetsModel(self.getPreferences(), parent = self)
# 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()
@@ -787,7 +839,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")
@@ -816,10 +867,38 @@ 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":
+ 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)
@@ -851,9 +930,22 @@ class CuraApplication(QtApplication):
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)
+ def getExtrudersModel(self, *args) -> "ExtrudersModel":
+ if self._extruders_model is None:
+ self._extruders_model = ExtrudersModel(self)
+ return self._extruders_model
+
+ @pyqtSlot(result = QObject)
+ def getExtrudersModelWithOptional(self, *args) -> "ExtrudersModel":
+ if self._extruders_model_with_optional is None:
+ self._extruders_model_with_optional = ExtrudersModel(self)
+ self._extruders_model_with_optional.setAddOptionalExtruder(True)
+ return self._extruders_model_with_optional
+
@pyqtSlot(result = QObject)
def getMultiBuildPlateModel(self, *args) -> MultiBuildPlateModel:
if self._multi_build_plate_model is None:
@@ -897,7 +989,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)
@@ -928,7 +1020,7 @@ class CuraApplication(QtApplication):
engine.rootContext().setContextProperty("CuraApplication", self)
engine.rootContext().setContextProperty("PrintInformation", self._print_information)
engine.rootContext().setContextProperty("CuraActions", self._cura_actions)
- engine.rootContext().setContextProperty("CuraSDKVersion", CuraSDKVersion)
+ engine.rootContext().setContextProperty("CuraSDKVersion", ApplicationMetadata.CuraSDKVersion)
qmlRegisterUncreatableType(CuraApplication, "Cura", 1, 0, "ResourceTypes", "Just an Enum type")
@@ -939,17 +1031,29 @@ class CuraApplication(QtApplication):
qmlRegisterSingletonType(SimpleModeSettingsManager, "Cura", 1, 0, "SimpleModeSettingsManager", self.getSimpleModeSettingsManager)
qmlRegisterSingletonType(MachineActionManager.MachineActionManager, "Cura", 1, 0, "MachineActionManager", self.getMachineActionManager)
- qmlRegisterSingletonType(ObjectsModel, "Cura", 1, 0, "ObjectsModel", self.getObjectsModel)
+ 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")
+
+ qmlRegisterType(ObjectsModel, "Cura", 1, 0, "ObjectsModel")
qmlRegisterType(BuildPlateModel, "Cura", 1, 0, "BuildPlateModel")
qmlRegisterType(MultiBuildPlateModel, "Cura", 1, 0, "MultiBuildPlateModel")
qmlRegisterType(InstanceContainer, "Cura", 1, 0, "InstanceContainer")
qmlRegisterType(ExtrudersModel, "Cura", 1, 0, "ExtrudersModel")
+ qmlRegisterType(GlobalStacksModel, "Cura", 1, 0, "GlobalStacksModel")
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")
+
+ qmlRegisterType(DiscoveredPrintersModel, "Cura", 1, 0, "DiscoveredPrintersModel")
qmlRegisterSingletonType(QualityProfilesDropDownMenuModel, "Cura", 1, 0,
"QualityProfilesDropDownMenuModel", self.getQualityProfilesDropDownMenuModel)
@@ -960,11 +1064,14 @@ class CuraApplication(QtApplication):
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)
qmlRegisterType(SidebarCustomMenuItemsModel, "Cura", 1, 0, "SidebarCustomMenuItemsModel")
+ qmlRegisterType(PrinterOutputDevice, "Cura", 1, 0, "PrinterOutputDevice")
+
from cura.API import CuraAPI
qmlRegisterSingletonType(CuraAPI, "Cura", 1, 1, "API", self.getCuraAPI)
@@ -1014,7 +1121,6 @@ class CuraApplication(QtApplication):
self._camera_animation.setTarget(Selection.getSelectedObject(0).getWorldPosition())
self._camera_animation.start()
- requestAddPrinter = pyqtSignal()
activityChanged = pyqtSignal()
sceneBoundingBoxChanged = pyqtSignal()
@@ -1075,88 +1181,6 @@ class CuraApplication(QtApplication):
self._platform_activity = True if count > 0 else False
self.activityChanged.emit()
- # Remove all selected objects from the scene.
- @pyqtSlot()
- @deprecated("Moved to CuraActions", "2.6")
- def deleteSelection(self):
- if not self.getController().getToolsEnabled():
- return
- removed_group_nodes = []
- op = GroupedOperation()
- nodes = Selection.getAllSelectedObjects()
- for node in nodes:
- op.addOperation(RemoveSceneNodeOperation(node))
- group_node = node.getParent()
- if group_node and group_node.callDecoration("isGroup") and group_node not in removed_group_nodes:
- remaining_nodes_in_group = list(set(group_node.getChildren()) - set(nodes))
- if len(remaining_nodes_in_group) == 1:
- removed_group_nodes.append(group_node)
- op.addOperation(SetParentOperation(remaining_nodes_in_group[0], group_node.getParent()))
- op.addOperation(RemoveSceneNodeOperation(group_node))
- op.push()
-
- ## Remove an object from the scene.
- # Note that this only removes an object if it is selected.
- @pyqtSlot("quint64")
- @deprecated("Use deleteSelection instead", "2.6")
- def deleteObject(self, object_id):
- if not self.getController().getToolsEnabled():
- return
-
- node = self.getController().getScene().findObject(object_id)
-
- if not node and object_id != 0: # Workaround for tool handles overlapping the selected object
- node = Selection.getSelectedObject(0)
-
- if node:
- op = GroupedOperation()
- op.addOperation(RemoveSceneNodeOperation(node))
-
- group_node = node.getParent()
- if group_node:
- # Note that at this point the node has not yet been deleted
- if len(group_node.getChildren()) <= 2 and group_node.callDecoration("isGroup"):
- op.addOperation(SetParentOperation(group_node.getChildren()[0], group_node.getParent()))
- op.addOperation(RemoveSceneNodeOperation(group_node))
-
- op.push()
-
- ## Create a number of copies of existing object.
- # \param object_id
- # \param count number of copies
- # \param min_offset minimum offset to other objects.
- @pyqtSlot("quint64", int)
- @deprecated("Use CuraActions::multiplySelection", "2.6")
- def multiplyObject(self, object_id, count, min_offset = 8):
- node = self.getController().getScene().findObject(object_id)
- if not node:
- node = Selection.getSelectedObject(0)
-
- while node.getParent() and node.getParent().callDecoration("isGroup"):
- node = node.getParent()
-
- job = MultiplyObjectsJob([node], count, min_offset)
- job.start()
- return
-
- ## Center object on platform.
- @pyqtSlot("quint64")
- @deprecated("Use CuraActions::centerSelection", "2.6")
- def centerObject(self, object_id):
- node = self.getController().getScene().findObject(object_id)
- if not node and object_id != 0: # Workaround for tool handles overlapping the selected object
- node = Selection.getSelectedObject(0)
-
- if not node:
- return
-
- if node.getParent() and node.getParent().callDecoration("isGroup"):
- node = node.getParent()
-
- if node:
- op = SetTransformOperation(node, Vector())
- op.push()
-
## Select all nodes containing mesh data in the scene.
@pyqtSlot()
def selectAll(self):
@@ -1236,62 +1260,75 @@ class CuraApplication(QtApplication):
## Arrange all objects.
@pyqtSlot()
- def arrangeObjectsToAllBuildPlates(self):
- nodes = []
+ def arrangeObjectsToAllBuildPlates(self) -> None:
+ nodes_to_arrange = []
for node in DepthFirstIterator(self.getController().getScene().getRoot()):
if not isinstance(node, SceneNode):
continue
+
if not node.getMeshData() and not node.callDecoration("isGroup"):
continue # Node that doesnt have a mesh and is not a group.
- if node.getParent() and node.getParent().callDecoration("isGroup"):
- continue # Grouped nodes don't need resetting as their parent (the group) is resetted)
+
+ parent_node = node.getParent()
+ if parent_node and parent_node.callDecoration("isGroup"):
+ continue # Grouped nodes don't need resetting as their parent (the group) is reset)
+
if not node.callDecoration("isSliceable") and not node.callDecoration("isGroup"):
continue # i.e. node with layer data
+
+ bounding_box = node.getBoundingBox()
# Skip nodes that are too big
- if node.getBoundingBox().width < self._volume.getBoundingBox().width or node.getBoundingBox().depth < self._volume.getBoundingBox().depth:
- nodes.append(node)
- job = ArrangeObjectsAllBuildPlatesJob(nodes)
+ if bounding_box is None or bounding_box.width < self._volume.getBoundingBox().width or bounding_box.depth < self._volume.getBoundingBox().depth:
+ nodes_to_arrange.append(node)
+ job = ArrangeObjectsAllBuildPlatesJob(nodes_to_arrange)
job.start()
self.getCuraSceneController().setActiveBuildPlate(0) # Select first build plate
# Single build plate
@pyqtSlot()
- def arrangeAll(self):
- nodes = []
+ def arrangeAll(self) -> None:
+ nodes_to_arrange = []
active_build_plate = self.getMultiBuildPlateModel().activeBuildPlate
for node in DepthFirstIterator(self.getController().getScene().getRoot()):
if not isinstance(node, SceneNode):
continue
+
if not node.getMeshData() and not node.callDecoration("isGroup"):
continue # Node that doesnt have a mesh and is not a group.
- if node.getParent() and node.getParent().callDecoration("isGroup"):
+
+ parent_node = node.getParent()
+ if parent_node and parent_node.callDecoration("isGroup"):
continue # Grouped nodes don't need resetting as their parent (the group) is resetted)
+
if not node.isSelectable():
continue # i.e. node with layer data
+
if not node.callDecoration("isSliceable") and not node.callDecoration("isGroup"):
continue # i.e. node with layer data
+
if node.callDecoration("getBuildPlateNumber") == active_build_plate:
# Skip nodes that are too big
- if node.getBoundingBox().width < self._volume.getBoundingBox().width or node.getBoundingBox().depth < self._volume.getBoundingBox().depth:
- nodes.append(node)
- self.arrange(nodes, fixed_nodes = [])
+ bounding_box = node.getBoundingBox()
+ if bounding_box is None or bounding_box.width < self._volume.getBoundingBox().width or bounding_box.depth < self._volume.getBoundingBox().depth:
+ nodes_to_arrange.append(node)
+ self.arrange(nodes_to_arrange, fixed_nodes = [])
## Arrange a set of nodes given a set of fixed nodes
# \param nodes nodes that we have to place
# \param fixed_nodes nodes that are placed in the arranger before finding spots for nodes
- def arrange(self, nodes, fixed_nodes):
+ def arrange(self, nodes: List[SceneNode], fixed_nodes: List[SceneNode]) -> None:
min_offset = self.getBuildVolume().getEdgeDisallowedSize() + 2 # Allow for some rounding errors
job = ArrangeObjectsJob(nodes, fixed_nodes, min_offset = max(min_offset, 8))
job.start()
## Reload all mesh data on the screen from file.
@pyqtSlot()
- def reloadAll(self):
+ def reloadAll(self) -> None:
Logger.log("i", "Reloading all loaded mesh data.")
nodes = []
has_merged_nodes = False
for node in DepthFirstIterator(self.getController().getScene().getRoot()):
- if not isinstance(node, CuraSceneNode) or not node.getMeshData() :
+ if not isinstance(node, CuraSceneNode) or not node.getMeshData():
if node.getName() == "MergedMesh":
has_merged_nodes = True
continue
@@ -1302,10 +1339,10 @@ class CuraApplication(QtApplication):
return
for node in nodes:
- file_name = node.getMeshData().getFileName()
- if file_name:
- job = ReadMeshJob(file_name)
- job._node = node
+ mesh_data = node.getMeshData()
+ if mesh_data and mesh_data.getFileName():
+ job = ReadMeshJob(mesh_data.getFileName())
+ job._node = node # type: ignore
job.finished.connect(self._reloadMeshFinished)
if has_merged_nodes:
job.finished.connect(self.updateOriginOfMergedMeshes)
@@ -1314,20 +1351,8 @@ class CuraApplication(QtApplication):
else:
Logger.log("w", "Unable to reload data because we don't have a filename.")
-
- ## Get logging data of the backend engine
- # \returns \type{string} Logging data
- @pyqtSlot(result = str)
- def getEngineLog(self):
- log = ""
-
- for entry in self.getBackend().getLog():
- log += entry.decode()
-
- return log
-
@pyqtSlot("QStringList")
- def setExpandedCategories(self, categories):
+ def setExpandedCategories(self, categories: List[str]) -> None:
categories = list(set(categories))
categories.sort()
joined = ";".join(categories)
@@ -1338,7 +1363,7 @@ class CuraApplication(QtApplication):
expandedCategoriesChanged = pyqtSignal()
@pyqtProperty("QStringList", notify = expandedCategoriesChanged)
- def expandedCategories(self):
+ def expandedCategories(self) -> List[str]:
return self.getPreferences().getValue("cura/categories_expanded").split(";")
@pyqtSlot()
@@ -1388,13 +1413,12 @@ class CuraApplication(QtApplication):
## Updates origin position of all merged meshes
- # \param jobNode \type{Job} empty object which passed which is required by JobQueue
- def updateOriginOfMergedMeshes(self, jobNode):
+ def updateOriginOfMergedMeshes(self, _):
group_nodes = []
for node in DepthFirstIterator(self.getController().getScene().getRoot()):
if isinstance(node, CuraSceneNode) and node.getName() == "MergedMesh":
- #checking by name might be not enough, the merged mesh should has "GroupDecorator" decorator
+ # Checking by name might be not enough, the merged mesh should has "GroupDecorator" decorator
for decorator in node.getDecorators():
if isinstance(decorator, GroupDecorator):
group_nodes.append(node)
@@ -1438,7 +1462,7 @@ class CuraApplication(QtApplication):
@pyqtSlot()
- def groupSelected(self):
+ def groupSelected(self) -> None:
# Create a group-node
group_node = CuraSceneNode()
group_decorator = GroupDecorator()
@@ -1454,7 +1478,8 @@ class CuraApplication(QtApplication):
# Remove nodes that are directly parented to another selected node from the selection so they remain parented
selected_nodes = Selection.getAllSelectedObjects().copy()
for node in selected_nodes:
- if node.getParent() in selected_nodes and not node.getParent().callDecoration("isGroup"):
+ parent = node.getParent()
+ if parent is not None and parent in selected_nodes and not parent.callDecoration("isGroup"):
Selection.remove(node)
# Move selected nodes into the group-node
@@ -1466,7 +1491,7 @@ class CuraApplication(QtApplication):
Selection.add(group_node)
@pyqtSlot()
- def ungroupSelected(self):
+ def ungroupSelected(self) -> None:
selected_objects = Selection.getAllSelectedObjects().copy()
for node in selected_objects:
if node.callDecoration("isGroup"):
@@ -1489,7 +1514,7 @@ class CuraApplication(QtApplication):
# Note: The group removes itself from the scene once all its children have left it,
# see GroupDecorator._onChildrenChanged
- def _createSplashScreen(self):
+ def _createSplashScreen(self) -> Optional[CuraSplashScreen.CuraSplashScreen]:
if self._is_headless:
return None
return CuraSplashScreen.CuraSplashScreen()
@@ -1655,7 +1680,9 @@ class CuraApplication(QtApplication):
is_non_sliceable = "." + file_extension in self._non_sliceable_extensions
if is_non_sliceable:
- self.callLater(lambda: self.getController().setActiveView("SimulationView"))
+ # Need to switch first to the preview stage and then to layer view
+ self.callLater(lambda: (self.getController().setActiveStage("PreviewStage"),
+ self.getController().setActiveView("SimulationView")))
block_slicing_decorator = BlockSlicingDecorator()
node.addDecorator(block_slicing_decorator)
@@ -1753,3 +1780,32 @@ 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
diff --git a/cura/CuraVersion.py.in b/cura/CuraVersion.py.in
index 226b2183f2..4583e76f67 100644
--- a/cura/CuraVersion.py.in
+++ b/cura/CuraVersion.py.in
@@ -1,9 +1,11 @@
-# Copyright (c) 2015 Ultimaker B.V.
+# Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
+CuraAppName = "@CURA_APP_NAME@"
+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
new file mode 100644
index 0000000000..b358558dff
--- /dev/null
+++ b/cura/CuraView.py
@@ -0,0 +1,34 @@
+# 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.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.
+# MainComponent works in the same way the MainComponent of a stage.
+# 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, 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:
+ 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/LayerDataBuilder.py b/cura/LayerDataBuilder.py
index d6cc81a4e9..e8d1b8c59f 100755
--- a/cura/LayerDataBuilder.py
+++ b/cura/LayerDataBuilder.py
@@ -7,43 +7,36 @@ from UM.Mesh.MeshBuilder import MeshBuilder
from .LayerData import LayerData
import numpy
+from typing import Dict, Optional
## Builder class for constructing a LayerData object
class LayerDataBuilder(MeshBuilder):
- def __init__(self):
+ def __init__(self) -> None:
super().__init__()
- self._layers = {}
- self._element_counts = {}
+ self._layers = {} # type: Dict[int, Layer]
+ self._element_counts = {} # type: Dict[int, int]
- def addLayer(self, layer):
+ def addLayer(self, layer: int) -> None:
if layer not in self._layers:
self._layers[layer] = Layer(layer)
- def addPolygon(self, layer, polygon_type, data, line_width, line_thickness, line_feedrate):
- if layer not in self._layers:
- self.addLayer(layer)
+ def getLayer(self, layer: int) -> Optional[Layer]:
+ return self._layers.get(layer)
- p = LayerPolygon(self, polygon_type, data, line_width, line_thickness, line_feedrate)
- self._layers[layer].polygons.append(p)
-
- def getLayer(self, layer):
- if layer in self._layers:
- return self._layers[layer]
-
- def getLayers(self):
+ def getLayers(self) -> Dict[int, Layer]:
return self._layers
- def getElementCounts(self):
+ def getElementCounts(self) -> Dict[int, int]:
return self._element_counts
- def setLayerHeight(self, layer, height):
+ def setLayerHeight(self, layer: int, height: float) -> None:
if layer not in self._layers:
self.addLayer(layer)
self._layers[layer].setHeight(height)
- def setLayerThickness(self, layer, thickness):
+ def setLayerThickness(self, layer: int, thickness: float) -> None:
if layer not in self._layers:
self.addLayer(layer)
@@ -71,7 +64,7 @@ class LayerDataBuilder(MeshBuilder):
vertex_offset = 0
index_offset = 0
for layer, data in sorted(self._layers.items()):
- ( vertex_offset, index_offset ) = data.build( vertex_offset, index_offset, vertices, colors, line_dimensions, feedrates, extruders, line_types, indices)
+ vertex_offset, index_offset = data.build(vertex_offset, index_offset, vertices, colors, line_dimensions, feedrates, extruders, line_types, indices)
self._element_counts[layer] = data.elementCount
self.addVertices(vertices)
diff --git a/cura/LayerDataDecorator.py b/cura/LayerDataDecorator.py
index c04479972a..ef82d8f5cc 100644
--- a/cura/LayerDataDecorator.py
+++ b/cura/LayerDataDecorator.py
@@ -1,13 +1,25 @@
+# Copyright (c) 2019 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+
+from typing import Optional
from UM.Scene.SceneNodeDecorator import SceneNodeDecorator
+from cura.LayerData import LayerData
+
+
## Simple decorator to indicate a scene node holds layer data.
class LayerDataDecorator(SceneNodeDecorator):
def __init__(self):
super().__init__()
- self._layer_data = None
-
- def getLayerData(self):
+ self._layer_data = None # type: Optional[LayerData]
+
+ def getLayerData(self) -> Optional["LayerData"]:
return self._layer_data
-
- def setLayerData(self, layer_data):
- self._layer_data = layer_data
\ No newline at end of file
+
+ def setLayerData(self, layer_data: LayerData) -> None:
+ self._layer_data = layer_data
+
+ def __deepcopy__(self, memo) -> "LayerDataDecorator":
+ copied_decorator = LayerDataDecorator()
+ copied_decorator._layer_data = self._layer_data
+ return copied_decorator
diff --git a/cura/LayerPolygon.py b/cura/LayerPolygon.py
index f33934de0c..824635e501 100644
--- a/cura/LayerPolygon.py
+++ b/cura/LayerPolygon.py
@@ -1,10 +1,12 @@
-# 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 typing import Any
+from typing import Any, Optional
import numpy
+from UM.Logger import Logger
+
class LayerPolygon:
NoneType = 0
@@ -18,22 +20,24 @@ class LayerPolygon:
MoveCombingType = 8
MoveRetractionType = 9
SupportInterfaceType = 10
- __number_of_types = 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)
## LayerPolygon, used in ProcessSlicedLayersJob
- # \param extruder
+ # \param extruder The position of the extruder
# \param line_types array with line_types
# \param data new_points
# \param line_widths array with line widths
# \param line_thicknesses: array with type as index and thickness as value
# \param line_feedrates array with line feedrates
- def __init__(self, extruder, line_types, data, line_widths, line_thicknesses, line_feedrates):
+ def __init__(self, extruder: int, line_types: numpy.ndarray, data: numpy.ndarray, line_widths: numpy.ndarray, line_thicknesses: numpy.ndarray, line_feedrates: numpy.ndarray) -> None:
self._extruder = extruder
self._types = line_types
for i in range(len(self._types)):
- if self._types[i] >= self.__number_of_types: #Got faulty line data from the engine.
+ if self._types[i] >= self.__number_of_types: # Got faulty line data from the engine.
+ Logger.log("w", "Found an unknown line type: %s", i)
self._types[i] = self.NoneType
self._data = data
self._line_widths = line_widths
@@ -53,23 +57,23 @@ class LayerPolygon:
# Buffering the colors shouldn't be necessary as it is not
# re-used and can save alot of memory usage.
self._color_map = LayerPolygon.getColorMap()
- self._colors = self._color_map[self._types]
+ self._colors = self._color_map[self._types] # type: numpy.ndarray
# 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], dtype = numpy.bool)
- self._build_cache_line_mesh_mask = None
- self._build_cache_needed_points = None
+ self._build_cache_line_mesh_mask = None # type: Optional[numpy.ndarray]
+ self._build_cache_needed_points = None # type: Optional[numpy.ndarray]
- def buildCache(self):
+ 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
@@ -90,10 +94,14 @@ class LayerPolygon:
# \param extruders : vertex numpy array to be filled
# \param line_types : vertex numpy array to be filled
# \param indices : index numpy array to be filled
- def build(self, vertex_offset, index_offset, vertices, colors, line_dimensions, feedrates, extruders, line_types, indices):
+ def build(self, vertex_offset: int, index_offset: int, vertices: numpy.ndarray, colors: numpy.ndarray, line_dimensions: numpy.ndarray, feedrates: numpy.ndarray, extruders: numpy.ndarray, line_types: numpy.ndarray, indices: numpy.ndarray) -> None:
if self._build_cache_line_mesh_mask is None or self._build_cache_needed_points is None:
self.buildCache()
-
+
+ if self._build_cache_line_mesh_mask is None or self._build_cache_needed_points is None:
+ Logger.log("w", "Failed to build cache for layer polygon")
+ return
+
line_mesh_mask = self._build_cache_line_mesh_mask
needed_points_list = self._build_cache_needed_points
@@ -128,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])
@@ -236,7 +244,8 @@ class LayerPolygon:
theme.getColor("layerview_support_infill").getRgbF(), # SupportInfillType
theme.getColor("layerview_move_combing").getRgbF(), # MoveCombingType
theme.getColor("layerview_move_retraction").getRgbF(), # MoveRetractionType
- theme.getColor("layerview_support_interface").getRgbF() # SupportInterfaceType
+ theme.getColor("layerview_support_interface").getRgbF(), # SupportInterfaceType
+ theme.getColor("layerview_prime_tower").getRgbF() # PrimeTowerType
])
return cls.__color_map
diff --git a/cura/MachineAction.py b/cura/MachineAction.py
index 969fef0edf..0f05401c89 100644
--- a/cura/MachineAction.py
+++ b/cura/MachineAction.py
@@ -1,13 +1,14 @@
# Copyright (c) 2016 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
-from PyQt5.QtCore import QObject, pyqtSlot, pyqtProperty, pyqtSignal
+import os
+from typing import Optional
+from PyQt5.QtCore import QObject, QUrl, pyqtSlot, pyqtProperty, pyqtSignal
+
+from UM.Logger import Logger
from UM.PluginObject import PluginObject
from UM.PluginRegistry import PluginRegistry
-from UM.Application import Application
-
-import os
## Machine actions are actions that are added to a specific machine type. Examples of such actions are
@@ -19,7 +20,7 @@ class MachineAction(QObject, PluginObject):
## Create a new Machine action.
# \param key unique key of the machine action
# \param label Human readable label used to identify the machine action.
- def __init__(self, key, label = ""):
+ def __init__(self, key: str, label: str = "") -> None:
super().__init__()
self._key = key
self._label = label
@@ -30,14 +31,20 @@ class MachineAction(QObject, PluginObject):
labelChanged = pyqtSignal()
onFinished = pyqtSignal()
- def getKey(self):
+ 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):
+ def label(self) -> str:
return self._label
- def setLabel(self, label):
+ def setLabel(self, label: str) -> None:
if self._label != label:
self._label = label
self.labelChanged.emit()
@@ -46,32 +53,46 @@ class MachineAction(QObject, PluginObject):
# This should not be re-implemented by child classes, instead re-implement _reset.
# /sa _reset
@pyqtSlot()
- def reset(self):
+ def reset(self) -> None:
self._finished = False
self._reset()
## Protected implementation of reset.
# /sa reset()
- def _reset(self):
+ def _reset(self) -> None:
pass
@pyqtSlot()
- def setFinished(self):
+ def setFinished(self) -> None:
self._finished = True
self._reset()
self.onFinished.emit()
@pyqtProperty(bool, notify = onFinished)
- def finished(self):
+ def finished(self) -> bool:
return self._finished
## Protected helper to create a view object based on provided QML.
- def _createViewFromQML(self):
- path = os.path.join(PluginRegistry.getInstance().getPluginPath(self.getPluginId()), self._qml_url)
- self._view = Application.getInstance().createQmlComponent(path, {"manager": self})
+ 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 None
+ path = os.path.join(plugin_path, self._qml_url)
- @pyqtProperty(QObject, constant = True)
- def displayItem(self):
- if not self._view:
- self._createViewFromQML()
- return self._view
+ from cura.CuraApplication import CuraApplication
+ view = CuraApplication.getInstance().createQmlComponent(path, {"manager": self})
+ return 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/MachineErrorChecker.py b/cura/Machines/MachineErrorChecker.py
index 06f064315b..964331909c 100644
--- a/cura/Machines/MachineErrorChecker.py
+++ b/cura/Machines/MachineErrorChecker.py
@@ -64,21 +64,21 @@ class MachineErrorChecker(QObject):
def _onMachineChanged(self) -> None:
if self._global_stack:
- self._global_stack.propertyChanged.disconnect(self.startErrorCheck)
+ self._global_stack.propertyChanged.disconnect(self.startErrorCheckPropertyChanged)
self._global_stack.containersChanged.disconnect(self.startErrorCheck)
for extruder in self._global_stack.extruders.values():
- extruder.propertyChanged.disconnect(self.startErrorCheck)
+ extruder.propertyChanged.disconnect(self.startErrorCheckPropertyChanged)
extruder.containersChanged.disconnect(self.startErrorCheck)
self._global_stack = self._machine_manager.activeMachine
if self._global_stack:
- self._global_stack.propertyChanged.connect(self.startErrorCheck)
+ self._global_stack.propertyChanged.connect(self.startErrorCheckPropertyChanged)
self._global_stack.containersChanged.connect(self.startErrorCheck)
for extruder in self._global_stack.extruders.values():
- extruder.propertyChanged.connect(self.startErrorCheck)
+ extruder.propertyChanged.connect(self.startErrorCheckPropertyChanged)
extruder.containersChanged.connect(self.startErrorCheck)
hasErrorUpdated = pyqtSignal()
@@ -93,6 +93,13 @@ class MachineErrorChecker(QObject):
def needToWaitForResult(self) -> bool:
return self._need_to_check or self._check_in_progress
+ # Start the error check for property changed
+ # this is seperate from the startErrorCheck because it ignores a number property types
+ def startErrorCheckPropertyChanged(self, key, property_name):
+ if property_name != "value":
+ return
+ self.startErrorCheck()
+
# Starts the error check timer to schedule a new error check.
def startErrorCheck(self, *args) -> None:
if not self._check_in_progress:
@@ -120,7 +127,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.extruders.values():
for key in stack.getAllKeys():
self._stacks_and_keys_to_check.append((stack, key))
@@ -161,7 +168,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/MaterialManager.py b/cura/Machines/MaterialManager.py
index be97fbc161..90012325c8 100644
--- a/cura/Machines/MaterialManager.py
+++ b/cura/Machines/MaterialManager.py
@@ -21,6 +21,7 @@ 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
@@ -92,7 +93,7 @@ class MaterialManager(QObject):
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]
+ self._material_group_map = dict()
# Map #1
# root_material_id -> MaterialGroup
@@ -102,6 +103,8 @@ class MaterialManager(QObject):
continue
root_material_id = material_metadata.get("base_file", "")
+ if root_material_id not in material_metadatas: #Not a registered material profile. Don't store this in the look-up tables.
+ continue
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)
@@ -117,7 +120,7 @@ class MaterialManager(QObject):
# Map #1.5
# GUID -> material group list
- self._guid_material_groups_map = defaultdict(list) # type: Dict[str, List[MaterialGroup]]
+ self._guid_material_groups_map = defaultdict(list)
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)
@@ -199,7 +202,7 @@ class MaterialManager(QObject):
# 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]]
+ self._diameter_machine_nozzle_buildplate_material_map = dict()
for material_metadata in material_metadatas.values():
self.__addMaterialMetadataIntoLookupTree(material_metadata)
@@ -218,7 +221,7 @@ class MaterialManager(QObject):
root_material_id = material_metadata["base_file"]
definition = material_metadata["definition"]
- approximate_diameter = material_metadata["approximate_diameter"]
+ approximate_diameter = str(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] = {}
@@ -298,9 +301,13 @@ class MaterialManager(QObject):
def getRootMaterialIDWithoutDiameter(self, root_material_id: str) -> str:
return self._diameter_material_map.get(root_material_id, "")
- def getMaterialGroupListByGUID(self, guid: str) -> Optional[list]:
+ 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.
#
@@ -327,7 +334,6 @@ class MaterialManager(QObject):
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
@@ -365,7 +371,7 @@ class MaterialManager(QObject):
nozzle_name = None
if extruder_stack.variant.getId() != "empty_variant":
nozzle_name = extruder_stack.variant.getName()
- diameter = extruder_stack.approximateMaterialDiameter
+ 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)
@@ -446,6 +452,28 @@ class MaterialManager(QObject):
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
@@ -478,12 +506,22 @@ class MaterialManager(QObject):
buildplate_name = global_stack.getBuildplateName()
machine_definition = global_stack.definition
- if extruder_definition is None:
- extruder_definition = global_stack.extruders[position].definition
- if extruder_definition and parseBool(global_stack.getMetaDataEntry("has_materials", False)):
- # At this point the extruder_definition is not None
- material_diameter = extruder_definition.getProperty("material_diameter", "value")
+ # 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))
@@ -500,16 +538,40 @@ class MaterialManager(QObject):
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
#
+ @pyqtSlot("QVariant", result=bool)
+ def canMaterialBeRemoved(self, material_node: "MaterialNode"):
+ # Check if the material is active in any extruder train. In that case, the material shouldn't be removed!
+ # In the future we might enable this again, but right now, it's causing a ton of issues if we do (since it
+ # corrupts the configuration)
+ root_material_id = material_node.getMetaDataEntry("base_file")
+ material_group = self.getMaterialGroup(root_material_id)
+ if not material_group:
+ return False
+
+ nodes_to_remove = [material_group.root_material_node] + material_group.derived_material_node_list
+ ids_to_remove = [node.getMetaDataEntry("id", "") for node in nodes_to_remove]
+
+ for extruder_stack in self._container_registry.findContainerStacks(type="extruder_train"):
+ if extruder_stack.material.getId() in ids_to_remove:
+ return False
+ return True
- #
- # 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")
@@ -592,7 +654,6 @@ class MaterialManager(QObject):
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)
@@ -612,8 +673,10 @@ class MaterialManager(QObject):
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 = "generic_pla"
root_material_id = self.getRootMaterialIDForDiameter(root_material_id, approximate_diameter)
material_group = self.getMaterialGroup(root_material_id)
@@ -644,7 +707,11 @@ class MaterialManager(QObject):
@pyqtSlot(str)
def removeFavorite(self, root_material_id: str) -> None:
- self._favorites.remove(root_material_id)
+ 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.
@@ -653,4 +720,4 @@ class MaterialManager(QObject):
@pyqtSlot()
def getFavorites(self):
- return self._favorites
\ No newline at end of file
+ return self._favorites
diff --git a/cura/Machines/Models/BaseMaterialsModel.py b/cura/Machines/Models/BaseMaterialsModel.py
index be9f8be1ed..e936877923 100644
--- a/cura/Machines/Models/BaseMaterialsModel.py
+++ b/cura/Machines/Models/BaseMaterialsModel.py
@@ -1,5 +1,6 @@
# Copyright (c) 2018 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 UM.Qt.ListModel import ListModel
@@ -9,13 +10,16 @@ from UM.Qt.ListModel import ListModel
# 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()
+ enabledChanged = pyqtSignal()
def __init__(self, parent = None):
super().__init__(parent)
-
from cura.CuraApplication import CuraApplication
self._application = CuraApplication.getInstance()
@@ -54,8 +58,9 @@ class BaseMaterialsModel(ListModel):
self._extruder_position = 0
self._extruder_stack = None
- self._available_materials = None
- self._favorite_ids = None
+ self._available_materials = None # type: Optional[Dict[str, MaterialNode]]
+ self._favorite_ids = set() # type: Set[str]
+ self._enabled = True
def _updateExtruderStack(self):
global_stack = self._machine_manager.activeMachine
@@ -64,9 +69,11 @@ class BaseMaterialsModel(ListModel):
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))
if self._extruder_stack is not None:
self._extruder_stack.pyqtContainersChanged.connect(self._update)
+ self._extruder_stack.approximateMaterialDiameterChanged.connect(self._update)
# Force update the model when the extruder stack changes
self._update()
@@ -80,6 +87,18 @@ class BaseMaterialsModel(ListModel):
def extruderPosition(self) -> int:
return self._extruder_position
+ def setEnabled(self, enabled):
+ if self._enabled != enabled:
+ self._enabled = enabled
+ if self._enabled:
+ # ensure the data is there again.
+ self._update()
+ self.enabledChanged.emit()
+
+ @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.
def _update(self):
@@ -91,7 +110,7 @@ class BaseMaterialsModel(ListModel):
def _canUpdate(self):
global_stack = self._machine_manager.activeMachine
- if global_stack is None:
+ if global_stack is None or not self._enabled:
return False
extruder_position = str(self._extruder_position)
@@ -100,7 +119,6 @@ class BaseMaterialsModel(ListModel):
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
diff --git a/cura/Machines/Models/DiscoveredPrintersModel.py b/cura/Machines/Models/DiscoveredPrintersModel.py
new file mode 100644
index 0000000000..803e1d21ba
--- /dev/null
+++ b/cura/Machines/Models/DiscoveredPrintersModel.py
@@ -0,0 +1,264 @@
+# 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 PyQt5.QtCore import QObject
+ 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 ClusterUM3OutputDevice, 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 82%
rename from cura/Settings/ExtrudersModel.py
rename to cura/Machines/Models/ExtrudersModel.py
index 52fc502bfc..9eee7f5f9e 100644
--- a/cura/Settings/ExtrudersModel.py
+++ b/cura/Machines/Models/ExtrudersModel.py
@@ -1,31 +1,31 @@
-# Copyright (c) 2017 Ultimaker B.V.
+# Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
-from PyQt5.QtCore import Qt, pyqtSignal, pyqtSlot, pyqtProperty, QTimer
-from typing import Iterable
+from PyQt5.QtCore import Qt, pyqtSignal, pyqtProperty, QTimer
+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
## Human-readable name of the extruder.
NameRole = Qt.UserRole + 2
- ## Is the extruder enabled?
- EnabledRole = Qt.UserRole + 9
## Colour of the material loaded in the extruder.
ColorRole = Qt.UserRole + 3
@@ -47,6 +47,12 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel):
VariantRole = Qt.UserRole + 7
StackRole = Qt.UserRole + 8
+ MaterialBrandRole = Qt.UserRole + 9
+ ColorNameRole = Qt.UserRole + 10
+
+ ## Is the extruder enabled?
+ EnabledRole = Qt.UserRole + 11
+
## List of colours to display if there is no material or the material has no known
# colour.
defaultColors = ["#ffc924", "#86ec21", "#22eeee", "#245bff", "#9124ff", "#ff24c8"]
@@ -67,14 +73,13 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel):
self.addRoleName(self.MaterialRole, "material")
self.addRoleName(self.VariantRole, "variant")
self.addRoleName(self.StackRole, "stack")
-
+ self.addRoleName(self.MaterialBrandRole, "material_brand")
+ self.addRoleName(self.ColorNameRole, "color_name")
self._update_extruder_timer = QTimer()
self._update_extruder_timer.setInterval(100)
self._update_extruder_timer.setSingleShot(True)
self._update_extruder_timer.timeout.connect(self.__updateExtruders)
- self._simple_names = False
-
self._active_machine_extruders = [] # type: Iterable[ExtruderStack]
self._add_optional_extruder = False
@@ -96,21 +101,6 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel):
def addOptionalExtruder(self):
return self._add_optional_extruder
- ## Set the simpleNames property.
- def setSimpleNames(self, simple_names):
- if simple_names != self._simple_names:
- self._simple_names = simple_names
- self.simpleNamesChanged.emit()
- self._updateExtruders()
-
- ## Emitted when the simpleNames property changes.
- simpleNamesChanged = pyqtSignal()
-
- ## Whether or not the model should show all definitions regardless of visibility.
- @pyqtProperty(bool, fset = setSimpleNames, notify = simpleNamesChanged)
- def simpleNames(self):
- return self._simple_names
-
## Links to the stack-changed signal of the new extruders when an extruder
# is swapped out or added in the current machine.
#
@@ -119,17 +109,19 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel):
# that signal. Application.globalContainerStackChanged doesn't fill this
# signal; it's assumed to be the current printer in that case.
def _extrudersChanged(self, machine_id = None):
+ machine_manager = Application.getInstance().getMachineManager()
if machine_id is not None:
- if Application.getInstance().getGlobalContainerStack() is None:
+ if machine_manager.activeMachine is None:
# No machine, don't need to update the current machine's extruders
return
- if machine_id != Application.getInstance().getGlobalContainerStack().getId():
+ if machine_id != machine_manager.activeMachine.getId():
# Not the current machine
return
# Unlink from old extruders
for extruder in self._active_machine_extruders:
extruder.containersChanged.disconnect(self._onExtruderStackContainersChanged)
+ extruder.enabledChanged.disconnect(self._updateExtruders)
# Link to new extruders
self._active_machine_extruders = []
@@ -138,13 +130,14 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel):
if extruder is None: #This extruder wasn't loaded yet. This happens asynchronously while this model is constructed from QML.
continue
extruder.containersChanged.connect(self._onExtruderStackContainersChanged)
+ extruder.enabledChanged.connect(self._updateExtruders)
self._active_machine_extruders.append(extruder)
self._updateExtruders() # Since the new extruders may have different properties, update our own model.
def _onExtruderStackContainersChanged(self, container):
- # Update when there is an empty container or material change
- if container.getMetaDataEntry("type") == "material" or container.getMetaDataEntry("type") is None:
+ # Update when there is an empty container or material or variant change
+ if container.getMetaDataEntry("type") in ["material", "variant", None]:
# The ExtrudersModel needs to be updated when the material-name or -color changes, because the user identifies extruders by material-name
self._updateExtruders()
@@ -160,7 +153,7 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel):
def __updateExtruders(self):
extruders_changed = False
- if self.rowCount() != 0:
+ if self.count != 0:
extruders_changed = True
items = []
@@ -172,7 +165,7 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel):
machine_extruder_count = global_container_stack.getProperty("machine_extruder_count", "value")
for extruder in Application.getInstance().getExtruderManager().getActiveExtruderStacks():
- position = extruder.getMetaDataEntry("position", default = "0") # Get the position
+ position = extruder.getMetaDataEntry("position", default = "0")
try:
position = int(position)
except ValueError:
@@ -183,7 +176,8 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel):
default_color = self.defaultColors[position] if 0 <= position < len(self.defaultColors) else self.defaultColors[0]
color = extruder.material.getMetaDataEntry("color_code", default = default_color) if extruder.material else default_color
-
+ material_brand = extruder.material.getMetaDataEntry("brand", default = "generic")
+ color_name = extruder.material.getMetaDataEntry("color_name")
# construct an item with only the relevant information
item = {
"id": extruder.getId(),
@@ -195,6 +189,8 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel):
"material": extruder.material.getName() if extruder.material else "",
"variant": extruder.variant.getName() if extruder.variant else "", # e.g. print core
"stack": extruder,
+ "material_brand": material_brand,
+ "color_name": color_name
}
items.append(item)
@@ -213,9 +209,14 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel):
"enabled": True,
"color": "#ffffff",
"index": -1,
- "definition": ""
+ "definition": "",
+ "material": "",
+ "variant": "",
+ "stack": None,
+ "material_brand": "",
+ "color_name": "",
}
items.append(item)
-
- self.setItems(items)
- self.modelChanged.emit()
+ if self._items != items:
+ self.setItems(items)
+ self.modelChanged.emit()
diff --git a/cura/Machines/Models/FavoriteMaterialsModel.py b/cura/Machines/Models/FavoriteMaterialsModel.py
index 18fe310c44..98a2a01597 100644
--- a/cura/Machines/Models/FavoriteMaterialsModel.py
+++ b/cura/Machines/Models/FavoriteMaterialsModel.py
@@ -1,20 +1,16 @@
# Copyright (c) 2018 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
+## Model that shows the list of favorite materials.
class FavoriteMaterialsModel(BaseMaterialsModel):
-
def __init__(self, parent = None):
super().__init__(parent)
self._update()
def _update(self):
-
- # Perform standard check and reset if the check fails
if not self._canUpdate():
- self.setItems([])
return
# Get updated list of favorites
diff --git a/cura/Machines/Models/FirstStartMachineActionsModel.py b/cura/Machines/Models/FirstStartMachineActionsModel.py
new file mode 100644
index 0000000000..ce0e9bf856
--- /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 c276b865bf..e81a73de24 100644
--- a/cura/Machines/Models/GenericMaterialsModel.py
+++ b/cura/Machines/Models/GenericMaterialsModel.py
@@ -1,7 +1,6 @@
# Copyright (c) 2018 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):
@@ -11,10 +10,7 @@ class GenericMaterialsModel(BaseMaterialsModel):
self._update()
def _update(self):
-
- # Perform standard check and reset if the check fails
if not self._canUpdate():
- self.setItems([])
return
# Get updated list of favorites
diff --git a/cura/Machines/Models/GlobalStacksModel.py b/cura/Machines/Models/GlobalStacksModel.py
new file mode 100644
index 0000000000..9db4ffe6db
--- /dev/null
+++ b/cura/Machines/Models/GlobalStacksModel.py
@@ -0,0 +1,77 @@
+# 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 cura.PrinterOutput.PrinterOutputDevice import ConnectionType
+from cura.Settings.CuraContainerRegistry import CuraContainerRegistry
+from cura.Settings.GlobalStack import GlobalStack
+
+
+class GlobalStacksModel(ListModel):
+ NameRole = Qt.UserRole + 1
+ IdRole = Qt.UserRole + 2
+ 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) -> 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.addRoleName(self.DiscoverySourceRole, "discoverySource")
+
+ self._change_timer = QTimer()
+ self._change_timer.setInterval(200)
+ self._change_timer.setSingleShot(True)
+ self._change_timer.timeout.connect(self._update)
+
+ # Listen to changes
+ CuraContainerRegistry.getInstance().containerAdded.connect(self._onContainerChanged)
+ CuraContainerRegistry.getInstance().containerMetaDataChanged.connect(self._onContainerChanged)
+ CuraContainerRegistry.getInstance().containerRemoved.connect(self._onContainerChanged)
+ self._updateDelayed()
+
+ ## Handler for container added/removed events from registry
+ 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) -> 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]
+
+ 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(),
+ "discoverySource": section_name})
+ items.sort(key = lambda i: (not i["hasRemoteConnection"], i["name"]))
+ self.setItems(items)
diff --git a/cura/Machines/Models/MachineManagementModel.py b/cura/Machines/Models/MachineManagementModel.py
deleted file mode 100644
index 7dc51f07f7..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("connect_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["connect_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/MaterialBrandsModel.py b/cura/Machines/Models/MaterialBrandsModel.py
index 458e4d9b47..c4721db5f7 100644
--- a/cura/Machines/Models/MaterialBrandsModel.py
+++ b/cura/Machines/Models/MaterialBrandsModel.py
@@ -1,9 +1,8 @@
# Copyright (c) 2018 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):
@@ -28,12 +27,8 @@ class MaterialBrandsModel(BaseMaterialsModel):
self._update()
def _update(self):
-
- # Perform standard check and reset if the check fails
if not self._canUpdate():
- self.setItems([])
return
-
# Get updated list of favorites
self._favorite_ids = self._material_manager.getFavorites()
diff --git a/cura/Machines/Models/MultiBuildPlateModel.py b/cura/Machines/Models/MultiBuildPlateModel.py
index 958e93837a..add960a545 100644
--- a/cura/Machines/Models/MultiBuildPlateModel.py
+++ b/cura/Machines/Models/MultiBuildPlateModel.py
@@ -4,6 +4,7 @@
from PyQt5.QtCore import QTimer, pyqtSignal, pyqtProperty
from UM.Application import Application
+from UM.Scene.Camera import Camera
from UM.Scene.Selection import Selection
from UM.Qt.ListModel import ListModel
@@ -34,8 +35,9 @@ class MultiBuildPlateModel(ListModel):
self._active_build_plate = -1
def setMaxBuildPlate(self, max_build_plate):
- self._max_build_plate = max_build_plate
- self.maxBuildPlateChanged.emit()
+ if self._max_build_plate != max_build_plate:
+ self._max_build_plate = max_build_plate
+ self.maxBuildPlateChanged.emit()
## Return the highest build plate number
@pyqtProperty(int, notify = maxBuildPlateChanged)
@@ -43,15 +45,17 @@ class MultiBuildPlateModel(ListModel):
return self._max_build_plate
def setActiveBuildPlate(self, nr):
- self._active_build_plate = nr
- self.activeBuildPlateChanged.emit()
+ if self._active_build_plate != nr:
+ self._active_build_plate = nr
+ self.activeBuildPlateChanged.emit()
@pyqtProperty(int, notify = activeBuildPlateChanged)
def activeBuildPlate(self):
return self._active_build_plate
def _updateSelectedObjectBuildPlateNumbersDelayed(self, *args):
- self._update_timer.start()
+ if not isinstance(args[0], Camera):
+ self._update_timer.start()
def _updateSelectedObjectBuildPlateNumbers(self, *args):
result = set()
diff --git a/cura/Machines/Models/NozzleModel.py b/cura/Machines/Models/NozzleModel.py
index 9d97106d6b..785ff5b9b9 100644
--- a/cura/Machines/Models/NozzleModel.py
+++ b/cura/Machines/Models/NozzleModel.py
@@ -33,8 +33,6 @@ class NozzleModel(ListModel):
def _update(self):
Logger.log("d", "Updating {model_class_name}.".format(model_class_name = self.__class__.__name__))
- self.items.clear()
-
global_stack = self._machine_manager.activeMachine
if global_stack is None:
self.setItems([])
diff --git a/cura/Machines/Models/QualityProfilesDropDownMenuModel.py b/cura/Machines/Models/QualityProfilesDropDownMenuModel.py
index a01cc1194f..deabb6e9ba 100644
--- a/cura/Machines/Models/QualityProfilesDropDownMenuModel.py
+++ b/cura/Machines/Models/QualityProfilesDropDownMenuModel.py
@@ -1,7 +1,7 @@
# Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
-from PyQt5.QtCore import Qt
+from PyQt5.QtCore import Qt, QTimer
from UM.Application import Application
from UM.Logger import Logger
@@ -10,6 +10,7 @@ from UM.Settings.SettingFunction import SettingFunction
from cura.Machines.QualityManager import QualityGroup
+
#
# QML Model for all built-in quality profiles. This model is used for the drop-down quality menu.
#
@@ -21,6 +22,7 @@ class QualityProfilesDropDownMenuModel(ListModel):
AvailableRole = Qt.UserRole + 5
QualityGroupRole = Qt.UserRole + 6
QualityChangesGroupRole = Qt.UserRole + 7
+ IsExperimentalRole = Qt.UserRole + 8
def __init__(self, parent = None):
super().__init__(parent)
@@ -32,19 +34,28 @@ class QualityProfilesDropDownMenuModel(ListModel):
self.addRoleName(self.AvailableRole, "available") #Whether the quality profile is available in our current nozzle + material.
self.addRoleName(self.QualityGroupRole, "quality_group")
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()
- self._application.globalContainerStackChanged.connect(self._update)
- self._machine_manager.activeQualityGroupChanged.connect(self._update)
- self._machine_manager.extruderChanged.connect(self._update)
- self._quality_manager.qualitiesUpdated.connect(self._update)
+ 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)
self._layer_height_unit = "" # This is cached
- self._update()
+ self._update_timer = QTimer() # type: 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()
def _update(self):
Logger.log("d", "Updating {model_class_name}.".format(model_class_name = self.__class__.__name__))
@@ -74,7 +85,8 @@ class QualityProfilesDropDownMenuModel(ListModel):
"layer_height": layer_height,
"layer_height_unit": self._layer_height_unit,
"available": quality_group.is_available,
- "quality_group": quality_group}
+ "quality_group": quality_group,
+ "is_experimental": quality_group.is_experimental}
item_list.append(item)
diff --git a/cura/Machines/Models/SettingVisibilityPresetsModel.py b/cura/Machines/Models/SettingVisibilityPresetsModel.py
index 7e098197a9..baa8e3ed29 100644
--- a/cura/Machines/Models/SettingVisibilityPresetsModel.py
+++ b/cura/Machines/Models/SettingVisibilityPresetsModel.py
@@ -1,135 +1,115 @@
# Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
-from typing import Optional, List, Dict, Union
-import os
-import urllib.parse
-from configparser import ConfigParser
+from typing import Optional, List
-from PyQt5.QtCore import pyqtProperty, Qt, pyqtSignal, pyqtSlot
+from PyQt5.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject
-from UM.Application import Application
from UM.Logger import Logger
-from UM.Qt.ListModel import ListModel
+from UM.Preferences import Preferences
from UM.Resources import Resources
-from UM.MimeTypeDatabase import MimeTypeDatabase, MimeTypeNotFoundError
from UM.i18n import i18nCatalog
+from cura.Settings.SettingVisibilityPreset import SettingVisibilityPreset
+
catalog = i18nCatalog("cura")
-class SettingVisibilityPresetsModel(ListModel):
- IdRole = Qt.UserRole + 1
- NameRole = Qt.UserRole + 2
- SettingsRole = Qt.UserRole + 3
+class SettingVisibilityPresetsModel(QObject):
+ onItemsChanged = pyqtSignal()
+ activePresetChanged = pyqtSignal()
- def __init__(self, parent = None):
+ def __init__(self, preferences: Preferences, parent = None) -> None:
super().__init__(parent)
- self.addRoleName(self.IdRole, "id")
- self.addRoleName(self.NameRole, "name")
- self.addRoleName(self.SettingsRole, "settings")
+
+ self._items = [] # type: List[SettingVisibilityPreset]
+ self._custom_preset = SettingVisibilityPreset(preset_id = "custom", name = "Custom selection", weight = -100)
self._populate()
- basic_item = self.items[1]
- basic_visibile_settings = ";".join(basic_item["settings"])
- self._preferences = Application.getInstance().getPreferences()
+ basic_item = self.getVisibilityPresetById("basic")
+ if basic_item is not None:
+ basic_visibile_settings = ";".join(basic_item.settings)
+ else:
+ Logger.log("w", "Unable to find the basic visiblity preset.")
+ basic_visibile_settings = ""
+
+ self._preferences = preferences
+
# Preference to store which preset is currently selected
self._preferences.addPreference("cura/active_setting_visibility_preset", "basic")
+
# Preference that stores the "custom" set so it can always be restored (even after a restart)
self._preferences.addPreference("cura/custom_visible_settings", basic_visibile_settings)
self._preferences.preferenceChanged.connect(self._onPreferencesChanged)
- self._active_preset_item = self._getItem(self._preferences.getValue("cura/active_setting_visibility_preset"))
+ self._active_preset_item = self.getVisibilityPresetById(self._preferences.getValue("cura/active_setting_visibility_preset"))
+
# Initialize visible settings if it is not done yet
visible_settings = self._preferences.getValue("general/visible_settings")
+
if not visible_settings:
- self._preferences.setValue("general/visible_settings", ";".join(self._active_preset_item["settings"]))
+ new_visible_settings = self._active_preset_item.settings if self._active_preset_item is not None else []
+ self._preferences.setValue("general/visible_settings", ";".join(new_visible_settings))
else:
self._onPreferencesChanged("general/visible_settings")
self.activePresetChanged.emit()
- def _getItem(self, item_id: str) -> Optional[dict]:
+ def getVisibilityPresetById(self, item_id: str) -> Optional[SettingVisibilityPreset]:
result = None
- for item in self.items:
- if item["id"] == item_id:
+ for item in self._items:
+ if item.presetId == item_id:
result = item
break
return result
def _populate(self) -> None:
from cura.CuraApplication import CuraApplication
- items = [] # type: List[Dict[str, Union[str, int, List[str]]]]
+ items = [] # type: List[SettingVisibilityPreset]
+ items.append(self._custom_preset)
for file_path in Resources.getAllResourcesOfType(CuraApplication.ResourceTypes.SettingVisibilityPreset):
+ setting_visibility_preset = SettingVisibilityPreset()
try:
- mime_type = MimeTypeDatabase.getMimeTypeForFile(file_path)
- except MimeTypeNotFoundError:
- Logger.log("e", "Could not determine mime type of file %s", file_path)
- continue
-
- item_id = urllib.parse.unquote_plus(mime_type.stripExtension(os.path.basename(file_path)))
- if not os.path.isfile(file_path):
- Logger.log("e", "[%s] is not a file", file_path)
- continue
-
- parser = ConfigParser(allow_no_value = True) # accept options without any value,
- try:
- parser.read([file_path])
- if not parser.has_option("general", "name") or not parser.has_option("general", "weight"):
- continue
-
- settings = [] # type: List[str]
- for section in parser.sections():
- if section == 'general':
- continue
-
- settings.append(section)
- for option in parser[section].keys():
- settings.append(option)
-
- items.append({
- "id": item_id,
- "name": catalog.i18nc("@action:inmenu", parser["general"]["name"]),
- "weight": parser["general"]["weight"],
- "settings": settings,
- })
-
+ setting_visibility_preset.loadFromFile(file_path)
except Exception:
Logger.logException("e", "Failed to load setting preset %s", file_path)
- items.sort(key = lambda k: (int(k["weight"]), k["id"])) # type: ignore
- # Put "custom" at the top
- items.insert(0, {"id": "custom",
- "name": "Custom selection",
- "weight": -100,
- "settings": []})
+ items.append(setting_visibility_preset)
+
+ # Sort them on weight (and if that fails, use ID)
+ items.sort(key = lambda k: (int(k.weight), k.presetId))
self.setItems(items)
+ @pyqtProperty("QVariantList", notify = onItemsChanged)
+ def items(self) -> List[SettingVisibilityPreset]:
+ return self._items
+
+ def setItems(self, items: List[SettingVisibilityPreset]) -> None:
+ if self._items != items:
+ self._items = items
+ self.onItemsChanged.emit()
+
@pyqtSlot(str)
- def setActivePreset(self, preset_id: str):
- if preset_id == self._active_preset_item["id"]:
+ def setActivePreset(self, preset_id: str) -> None:
+ if self._active_preset_item is not None and preset_id == self._active_preset_item.presetId:
Logger.log("d", "Same setting visibility preset [%s] selected, do nothing.", preset_id)
return
- preset_item = None
- for item in self.items:
- if item["id"] == preset_id:
- preset_item = item
- break
+ preset_item = self.getVisibilityPresetById(preset_id)
if preset_item is None:
Logger.log("w", "Tried to set active preset to unknown id [%s]", preset_id)
return
- need_to_save_to_custom = self._active_preset_item["id"] == "custom" and preset_id != "custom"
+ need_to_save_to_custom = self._active_preset_item is None or (self._active_preset_item.presetId == "custom" and preset_id != "custom")
if need_to_save_to_custom:
# Save the current visibility settings to custom
current_visibility_string = self._preferences.getValue("general/visible_settings")
if current_visibility_string:
self._preferences.setValue("cura/custom_visible_settings", current_visibility_string)
- new_visibility_string = ";".join(preset_item["settings"])
+ new_visibility_string = ";".join(preset_item.settings)
if preset_id == "custom":
# Get settings from the stored custom data
new_visibility_string = self._preferences.getValue("cura/custom_visible_settings")
@@ -141,11 +121,11 @@ class SettingVisibilityPresetsModel(ListModel):
self._active_preset_item = preset_item
self.activePresetChanged.emit()
- activePresetChanged = pyqtSignal()
-
@pyqtProperty(str, notify = activePresetChanged)
def activePreset(self) -> str:
- return self._active_preset_item["id"]
+ if self._active_preset_item is not None:
+ return self._active_preset_item.presetId
+ return ""
def _onPreferencesChanged(self, name: str) -> None:
if name != "general/visible_settings":
@@ -158,25 +138,31 @@ class SettingVisibilityPresetsModel(ListModel):
visibility_set = set(visibility_string.split(";"))
matching_preset_item = None
- for item in self.items:
- if item["id"] == "custom":
+ for item in self._items:
+ if item.presetId == "custom":
continue
- if set(item["settings"]) == visibility_set:
+ if set(item.settings) == visibility_set:
matching_preset_item = item
break
item_to_set = self._active_preset_item
if matching_preset_item is None:
# The new visibility setup is "custom" should be custom
- if self._active_preset_item["id"] == "custom":
+ if self._active_preset_item is None or self._active_preset_item.presetId == "custom":
# We are already in custom, just save the settings
self._preferences.setValue("cura/custom_visible_settings", visibility_string)
else:
- item_to_set = self.items[0] # 0 is custom
+ # We need to move to custom preset.
+ item_to_set = self.getVisibilityPresetById("custom")
else:
item_to_set = matching_preset_item
- if self._active_preset_item is None or self._active_preset_item["id"] != item_to_set["id"]:
+ # If we didn't find a matching preset, fallback to custom.
+ if item_to_set is None:
+ item_to_set = self._custom_preset
+
+ if self._active_preset_item is None or self._active_preset_item.presetId != item_to_set.presetId:
self._active_preset_item = item_to_set
- self._preferences.setValue("cura/active_setting_visibility_preset", self._active_preset_item["id"])
+ if self._active_preset_item is not None:
+ self._preferences.setValue("cura/active_setting_visibility_preset", self._active_preset_item.presetId)
self.activePresetChanged.emit()
diff --git a/cura/Settings/UserChangesModel.py b/cura/Machines/Models/UserChangesModel.py
similarity index 99%
rename from cura/Settings/UserChangesModel.py
rename to cura/Machines/Models/UserChangesModel.py
index 9a26e5607e..e629295397 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
diff --git a/cura/Machines/QualityGroup.py b/cura/Machines/QualityGroup.py
index 535ba453f8..f5bcbb0de8 100644
--- a/cura/Machines/QualityGroup.py
+++ b/cura/Machines/QualityGroup.py
@@ -4,6 +4,9 @@
from typing import Dict, Optional, List, Set
from PyQt5.QtCore import QObject, pyqtSlot
+
+from UM.Util import parseBool
+
from cura.Machines.ContainerNode import ContainerNode
@@ -29,6 +32,7 @@ class QualityGroup(QObject):
self.nodes_for_extruders = {} # type: Dict[int, ContainerNode]
self.quality_type = quality_type
self.is_available = False
+ self.is_experimental = False
@pyqtSlot(result = str)
def getName(self) -> str:
@@ -51,3 +55,17 @@ class QualityGroup(QObject):
for extruder_node in self.nodes_for_extruders.values():
result.append(extruder_node)
return result
+
+ def setGlobalNode(self, node: "ContainerNode") -> None:
+ self.node_for_global = node
+
+ # Update is_experimental flag
+ is_experimental = parseBool(node.getMetaDataEntry("is_experimental", False))
+ self.is_experimental |= is_experimental
+
+ def setExtruderNode(self, position: int, node: "ContainerNode") -> None:
+ self.nodes_for_extruders[position] = node
+
+ # Update is_experimental flag
+ 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
index ce19624c21..7da4f4f0d6 100644
--- a/cura/Machines/QualityManager.py
+++ b/cura/Machines/QualityManager.py
@@ -1,7 +1,7 @@
# 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
+from typing import TYPE_CHECKING, Optional, cast, Dict, List, Set
from PyQt5.QtCore import QObject, QTimer, pyqtSignal, pyqtSlot
@@ -16,7 +16,7 @@ from .QualityGroup import QualityGroup
from .QualityNode import QualityNode
if TYPE_CHECKING:
- from UM.Settings.DefinitionContainer import DefinitionContainer
+ from UM.Settings.Interfaces import DefinitionContainerInterface
from cura.Settings.GlobalStack import GlobalStack
from .QualityChangesGroup import QualityChangesGroup
from cura.CuraApplication import CuraApplication
@@ -202,13 +202,11 @@ class QualityManager(QObject):
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
@@ -235,7 +233,7 @@ class QualityManager(QObject):
for quality_type, quality_node in node.quality_type_map.items():
quality_group = QualityGroup(quality_node.getMetaDataEntry("name", ""), quality_type)
- quality_group.node_for_global = quality_node
+ quality_group.setGlobalNode(quality_node)
quality_group_dict[quality_type] = quality_group
break
@@ -259,11 +257,15 @@ class QualityManager(QObject):
root_material_id = self._material_manager.getRootMaterialIDWithoutDiameter(root_material_id)
root_material_id_list.append(root_material_id)
- # Also try to get the fallback material
- material_type = extruder.material.getMetaDataEntry("material")
- fallback_root_material_id = self._material_manager.getFallbackMaterialIdByMaterialType(material_type)
- if fallback_root_material_id:
- root_material_id_list.append(fallback_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
@@ -333,7 +335,7 @@ class QualityManager(QObject):
quality_group = quality_group_dict[quality_type]
if position not in quality_group.nodes_for_extruders:
- quality_group.nodes_for_extruders[position] = quality_node
+ 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.
@@ -363,7 +365,7 @@ class QualityManager(QObject):
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.node_for_global = quality_node
+ quality_group.setGlobalNode(quality_node)
quality_group_dict[quality_type] = quality_group
break
@@ -437,7 +439,8 @@ class QualityManager(QObject):
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,
+ new_name = self._container_registry.uniqueName(quality_changes_name)
+ new_quality_changes = self._createQualityChanges(quality_group.quality_type, new_name,
global_stack, None)
self._container_registry.addContainer(new_quality_changes)
else:
@@ -534,7 +537,7 @@ class QualityManager(QObject):
# 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: "DefinitionContainer",
+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)):
diff --git a/cura/Machines/VariantManager.py b/cura/Machines/VariantManager.py
index f6feb70e09..eaaa9fc5f0 100644
--- a/cura/Machines/VariantManager.py
+++ b/cura/Machines/VariantManager.py
@@ -107,7 +107,7 @@ class VariantManager:
break
return variant_node
- return self._machine_to_variant_dict_map[machine_definition_id].get(variant_type, {}).get(variant_name)
+ 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()
diff --git a/cura/MultiplyObjectsJob.py b/cura/MultiplyObjectsJob.py
index 3cbf795952..e71bbf6668 100644
--- a/cura/MultiplyObjectsJob.py
+++ b/cura/MultiplyObjectsJob.py
@@ -25,7 +25,7 @@ class MultiplyObjectsJob(Job):
def run(self):
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 Object"))
+ dismissable=False, progress=0, title = i18n_catalog.i18nc("@info:title", "Placing Objects"))
status_message.show()
scene = Application.getInstance().getController().getScene()
diff --git a/cura/OAuth2/AuthorizationHelpers.py b/cura/OAuth2/AuthorizationHelpers.py
index f75ad9c9f9..08309fa30e 100644
--- a/cura/OAuth2/AuthorizationHelpers.py
+++ b/cura/OAuth2/AuthorizationHelpers.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 datetime import datetime
import json
import random
from hashlib import sha512
from base64 import b64encode
-from typing import Dict, Optional
+from typing import Optional
import requests
+from UM.i18n import i18nCatalog
from UM.Logger import Logger
from cura.OAuth2.Models import AuthenticationResponse, UserProfile, OAuth2Settings
+catalog = i18nCatalog("cura")
+TOKEN_TIMESTAMP_FORMAT = "%Y-%m-%d %H:%M:%S"
-
-# Class containing several helpers to deal with the authorization flow.
+## Class containing several helpers to deal with the authorization flow.
class AuthorizationHelpers:
def __init__(self, settings: "OAuth2Settings") -> None:
self._settings = settings
self._token_url = "{}/token".format(self._settings.OAUTH_SERVER_URL)
@property
- # The OAuth2 settings object.
+ ## The OAuth2 settings object.
def settings(self) -> "OAuth2Settings":
return self._settings
- # Request the access token from the authorization server.
+ ## Request the access token from the authorization server.
# \param authorization_code: The authorization code from the 1st step.
- # \param verification_code: The verification code needed for the PKCE extension.
- # \return: An AuthenticationResponse object.
+ # \param verification_code: The verification code needed for the PKCE
+ # extension.
+ # \return An AuthenticationResponse object.
def getAccessTokenUsingAuthorizationCode(self, authorization_code: str, verification_code: str) -> "AuthenticationResponse":
data = {
"client_id": self._settings.CLIENT_ID if self._settings.CLIENT_ID is not None else "",
@@ -37,12 +41,16 @@ class AuthorizationHelpers:
"code_verifier": verification_code,
"scope": self._settings.CLIENT_SCOPES if self._settings.CLIENT_SCOPES is not None else "",
}
- return self.parseTokenResponse(requests.post(self._token_url, data = data)) # type: ignore
+ try:
+ return self.parseTokenResponse(requests.post(self._token_url, data = data)) # type: ignore
+ except requests.exceptions.ConnectionError:
+ return AuthenticationResponse(success=False, err_message="Unable to connect to remote server")
- # Request the access token from the authorization server using a refresh token.
+ ## Request the access token from the authorization server using a refresh token.
# \param refresh_token:
- # \return: An AuthenticationResponse object.
+ # \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 "",
@@ -50,12 +58,15 @@ class AuthorizationHelpers:
"refresh_token": refresh_token,
"scope": self._settings.CLIENT_SCOPES if self._settings.CLIENT_SCOPES is not None else "",
}
- return self.parseTokenResponse(requests.post(self._token_url, data = data)) # type: ignore
+ try:
+ return self.parseTokenResponse(requests.post(self._token_url, data = data)) # type: ignore
+ except requests.exceptions.ConnectionError:
+ return AuthenticationResponse(success=False, err_message="Unable to connect to remote server")
@staticmethod
- # Parse the token response from the authorization server into an AuthenticationResponse object.
+ ## Parse the token response from the authorization server into an AuthenticationResponse object.
# \param token_response: The JSON string data response from the authorization server.
- # \return: An AuthenticationResponse object.
+ # \return An AuthenticationResponse object.
def parseTokenResponse(token_response: requests.models.Response) -> "AuthenticationResponse":
token_data = None
@@ -65,25 +76,31 @@ class AuthorizationHelpers:
Logger.log("w", "Could not parse token response data: %s", token_response.text)
if not token_data:
- return AuthenticationResponse(success=False, err_message="Could not read response.")
+ return AuthenticationResponse(success = False, err_message = catalog.i18nc("@message", "Could not read response."))
if token_response.status_code not in (200, 201):
- return AuthenticationResponse(success=False, err_message=token_data["error_description"])
+ return AuthenticationResponse(success = False, err_message = token_data["error_description"])
return AuthenticationResponse(success=True,
token_type=token_data["token_type"],
access_token=token_data["access_token"],
refresh_token=token_data["refresh_token"],
expires_in=token_data["expires_in"],
- scope=token_data["scope"])
+ scope=token_data["scope"],
+ received_at=datetime.now().strftime(TOKEN_TIMESTAMP_FORMAT))
- # Calls the authentication API endpoint to get the token data.
+ ## Calls the authentication API endpoint to get the token data.
# \param access_token: The encoded JWT token.
- # \return: Dict containing some profile data.
+ # \return Dict containing some profile data.
def parseJWT(self, access_token: str) -> Optional["UserProfile"]:
- token_request = requests.get("{}/check-token".format(self._settings.OAUTH_SERVER_URL), headers = {
- "Authorization": "Bearer {}".format(access_token)
- })
+ try:
+ token_request = requests.get("{}/check-token".format(self._settings.OAUTH_SERVER_URL), headers = {
+ "Authorization": "Bearer {}".format(access_token)
+ })
+ 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")
+ 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)
return None
@@ -98,15 +115,15 @@ class AuthorizationHelpers:
)
@staticmethod
- # Generate a 16-character verification code.
+ ## Generate a 16-character verification code.
# \param code_length: How long should the code be?
def generateVerificationCode(code_length: int = 16) -> str:
return "".join(random.choice("0123456789ABCDEF") for i in range(code_length))
@staticmethod
- # Generates a base64 encoded sha512 encrypted version of a given string.
+ ## Generates a base64 encoded sha512 encrypted version of a given string.
# \param verification_code:
- # \return: The encrypted code in base64 format.
+ # \return The encrypted code in base64 format.
def generateVerificationCodeChallenge(verification_code: str) -> str:
encoded = sha512(verification_code.encode()).digest()
return b64encode(encoded, altchars = b"_-").decode()
diff --git a/cura/OAuth2/AuthorizationRequestHandler.py b/cura/OAuth2/AuthorizationRequestHandler.py
index 7e0a659a56..66ecfc2787 100644
--- a/cura/OAuth2/AuthorizationRequestHandler.py
+++ b/cura/OAuth2/AuthorizationRequestHandler.py
@@ -1,25 +1,27 @@
-# 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, Callable, Tuple, Dict, Any, List, TYPE_CHECKING
from http.server import BaseHTTPRequestHandler
+from typing import Optional, Callable, Tuple, Dict, Any, List, TYPE_CHECKING
from urllib.parse import parse_qs, urlparse
from cura.OAuth2.Models import AuthenticationResponse, ResponseData, HTTP_STATUS
+from UM.i18n import i18nCatalog
if TYPE_CHECKING:
from cura.OAuth2.Models import ResponseStatus
from cura.OAuth2.AuthorizationHelpers import AuthorizationHelpers
+catalog = i18nCatalog("cura")
-# This handler handles all HTTP requests on the local web server.
-# It also requests the access token for the 2nd stage of the OAuth flow.
+## This handler handles all HTTP requests on the local web server.
+# It also requests the access token for the 2nd stage of the OAuth flow.
class AuthorizationRequestHandler(BaseHTTPRequestHandler):
def __init__(self, request, client_address, server) -> None:
super().__init__(request, client_address, server)
# These values will be injected by the HTTPServer that this handler belongs to.
- self.authorization_helpers = None # type: Optional["AuthorizationHelpers"]
+ self.authorization_helpers = None # type: Optional[AuthorizationHelpers]
self.authorization_callback = None # type: Optional[Callable[[AuthenticationResponse], None]]
self.verification_code = None # type: Optional[str]
@@ -47,9 +49,9 @@ class AuthorizationRequestHandler(BaseHTTPRequestHandler):
# This will cause the server to shut down, so we do it at the very end of the request handling.
self.authorization_callback(token_response)
- # Handler for the callback URL redirect.
- # \param query: Dict containing the HTTP query parameters.
- # \return: HTTP ResponseData containing a success page to show to the user.
+ ## Handler for the callback URL redirect.
+ # \param query Dict containing the HTTP query parameters.
+ # \return HTTP ResponseData containing a success page to show to the user.
def _handleCallback(self, query: Dict[Any, List]) -> Tuple[ResponseData, Optional[AuthenticationResponse]]:
code = self._queryGet(query, "code")
if code and self.authorization_helpers is not None and self.verification_code is not None:
@@ -60,30 +62,30 @@ class AuthorizationRequestHandler(BaseHTTPRequestHandler):
elif self._queryGet(query, "error_code") == "user_denied":
# Otherwise we show an error message (probably the user clicked "Deny" in the auth dialog).
token_response = AuthenticationResponse(
- success=False,
- err_message="Please give the required permissions when authorizing this application."
+ success = False,
+ err_message = catalog.i18nc("@message", "Please give the required permissions when authorizing this application.")
)
else:
# We don't know what went wrong here, so instruct the user to check the logs.
token_response = AuthenticationResponse(
- success=False,
- error_message="Something unexpected happened when trying to log in, please try again."
+ success = False,
+ error_message = catalog.i18nc("@message", "Something unexpected happened when trying to log in, please try again.")
)
if self.authorization_helpers is None:
return ResponseData(), token_response
return ResponseData(
- status=HTTP_STATUS["REDIRECT"],
- data_stream=b"Redirecting...",
- redirect_uri=self.authorization_helpers.settings.AUTH_SUCCESS_REDIRECT if token_response.success else
+ status = HTTP_STATUS["REDIRECT"],
+ data_stream = b"Redirecting...",
+ redirect_uri = self.authorization_helpers.settings.AUTH_SUCCESS_REDIRECT if token_response.success else
self.authorization_helpers.settings.AUTH_FAILED_REDIRECT
), token_response
+ ## Handle all other non-existing server calls.
@staticmethod
- # Handle all other non-existing server calls.
def _handleNotFound() -> ResponseData:
- return ResponseData(status=HTTP_STATUS["NOT_FOUND"], content_type="text/html", data_stream=b"Not found.")
+ return ResponseData(status = HTTP_STATUS["NOT_FOUND"], content_type = "text/html", data_stream = b"Not found.")
def _sendHeaders(self, status: "ResponseStatus", content_type: str, redirect_uri: str = None) -> None:
self.send_response(status.code, status.message)
@@ -95,7 +97,7 @@ class AuthorizationRequestHandler(BaseHTTPRequestHandler):
def _sendData(self, data: bytes) -> None:
self.wfile.write(data)
+ ## Convenience helper for getting values from a pre-parsed query string
@staticmethod
- # Convenience Helper for getting values from a pre-parsed query string
- def _queryGet(query_data: Dict[Any, List], key: str, default: Optional[str]=None) -> Optional[str]:
+ def _queryGet(query_data: Dict[Any, List], key: str, default: Optional[str] = None) -> Optional[str]:
return query_data.get(key, [default])[0]
diff --git a/cura/OAuth2/AuthorizationRequestServer.py b/cura/OAuth2/AuthorizationRequestServer.py
index 288e348ea9..51a8ceba77 100644
--- a/cura/OAuth2/AuthorizationRequestServer.py
+++ b/cura/OAuth2/AuthorizationRequestServer.py
@@ -1,5 +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 http.server import HTTPServer
from typing import Callable, Any, TYPE_CHECKING
@@ -8,19 +9,19 @@ if TYPE_CHECKING:
from cura.OAuth2.AuthorizationHelpers import AuthorizationHelpers
-# The authorization request callback handler server.
-# This subclass is needed to be able to pass some data to the request handler.
-# This cannot be done on the request handler directly as the HTTPServer creates an instance of the handler after
-# init.
+## The authorization request callback handler server.
+# This subclass is needed to be able to pass some data to the request handler.
+# This cannot be done on the request handler directly as the HTTPServer
+# creates an instance of the handler after init.
class AuthorizationRequestServer(HTTPServer):
- # Set the authorization helpers instance on the request handler.
+ ## Set the authorization helpers instance on the request handler.
def setAuthorizationHelpers(self, authorization_helpers: "AuthorizationHelpers") -> None:
self.RequestHandlerClass.authorization_helpers = authorization_helpers # type: ignore
- # Set the authorization callback on the request handler.
+ ## Set the authorization callback on the request handler.
def setAuthorizationCallback(self, authorization_callback: Callable[["AuthenticationResponse"], Any]) -> None:
self.RequestHandlerClass.authorization_callback = authorization_callback # type: ignore
- # Set the verification code on the request handler.
+ ## Set the verification code on the request handler.
def setVerificationCode(self, verification_code: str) -> None:
self.RequestHandlerClass.verification_code = verification_code # type: ignore
diff --git a/cura/OAuth2/AuthorizationService.py b/cura/OAuth2/AuthorizationService.py
index 65b31f1ed7..27041b1f80 100644
--- a/cura/OAuth2/AuthorizationService.py
+++ b/cura/OAuth2/AuthorizationService.py
@@ -1,34 +1,41 @@
-# 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
import webbrowser
+from datetime import datetime, timedelta
from typing import Optional, TYPE_CHECKING
from urllib.parse import urlencode
+import requests.exceptions
+
from UM.Logger import Logger
+from UM.Message import Message
from UM.Signal import Signal
from cura.OAuth2.LocalAuthorizationServer import LocalAuthorizationServer
-from cura.OAuth2.AuthorizationHelpers import AuthorizationHelpers
+from cura.OAuth2.AuthorizationHelpers import AuthorizationHelpers, TOKEN_TIMESTAMP_FORMAT
from cura.OAuth2.Models import AuthenticationResponse
+from UM.i18n import i18nCatalog
+i18n_catalog = i18nCatalog("cura")
+
if TYPE_CHECKING:
from cura.OAuth2.Models import UserProfile, OAuth2Settings
from UM.Preferences import Preferences
+## The authorization service is responsible for handling the login flow,
+# storing user credentials and providing account information.
class AuthorizationService:
- """
- The authorization service is responsible for handling the login flow,
- storing user credentials and providing account information.
- """
-
# Emit signal when authentication is completed.
onAuthStateChanged = Signal()
# 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)
@@ -38,31 +45,48 @@ class AuthorizationService:
self._preferences = preferences
self._server = LocalAuthorizationServer(self._auth_helpers, self._onAuthStateChanged, daemon=True)
+ self._unable_to_get_data_message = None # type: Optional[Message]
+
+ self.onAuthStateChanged.connect(self._authChanged)
+
+ def _authChanged(self, logged_in):
+ if logged_in and self._unable_to_get_data_message is not None:
+ self._unable_to_get_data_message.hide()
+
def initialize(self, preferences: Optional["Preferences"] = None) -> None:
if preferences is not None:
self._preferences = preferences
if self._preferences:
self._preferences.addPreference(self._settings.AUTH_DATA_PREFERENCE_KEY, "{}")
- # Get the user profile as obtained from the JWT (JSON Web Token).
+ ## Get the user profile as obtained from the JWT (JSON Web Token).
# If the JWT is not yet parsed, calling this will take care of that.
# \return UserProfile if a user is logged in, None otherwise.
# \sa _parseJWT
def getUserProfile(self) -> Optional["UserProfile"]:
if not self._user_profile:
# If no user profile was stored locally, we try to get it from JWT.
- self._user_profile = self._parseJWT()
- if not self._user_profile:
+ try:
+ 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:
# If there is still no user profile from the JWT, we have to log in again.
+ Logger.log("w", "The user profile could not be loaded. The user must log in again!")
+ self.deleteAuthData()
return None
return self._user_profile
- # Tries to parse the JWT (JSON Web Token) data, which it does if all the needed data is there.
+ ## Tries to parse the JWT (JSON Web Token) data, which it does if all the needed data is there.
# \return UserProfile if it was able to parse, None otherwise.
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:
@@ -70,41 +94,54 @@ 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.
+ ## Get the access token as provided by the repsonse data.
def getAccessToken(self) -> Optional[str]:
- if not self.getUserProfile():
- # We check if we can get the user profile.
- # If we can't get it, that means the access token (JWT) was invalid or expired.
- return None
-
if self._auth_data is None:
+ Logger.log("d", "No auth data to retrieve the access_token from")
return None
- return self._auth_data.access_token
+ # Check if the current access token is expired and refresh it if that is the case.
+ # We have a fallback on a date far in the past for currently stored auth data in cura.cfg.
+ received_at = datetime.strptime(self._auth_data.received_at, TOKEN_TIMESTAMP_FORMAT) \
+ if self._auth_data.received_at else datetime(2000, 1, 1)
+ expiry_date = received_at + timedelta(seconds = float(self._auth_data.expires_in or 0) - 60)
+ if datetime.now() > expiry_date:
+ self.refreshAccessToken()
- # Try to refresh the access token. This should be used when it has expired.
+ return self._auth_data.access_token if self._auth_data else None
+
+ ## Try to refresh the access token. This should be used when it has expired.
def refreshAccessToken(self) -> None:
if self._auth_data is None or self._auth_data.refresh_token is None:
Logger.log("w", "Unable to refresh access token, since there is no refresh token.")
return
- self._storeAuthData(self._auth_helpers.getAccessTokenUsingRefreshToken(self._auth_data.refresh_token))
- self.onAuthStateChanged.emit(logged_in=True)
+ response = self._auth_helpers.getAccessTokenUsingRefreshToken(self._auth_data.refresh_token)
+ if response.success:
+ self._storeAuthData(response)
+ self.onAuthStateChanged.emit(logged_in = True)
+ else:
+ 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)
+ ## Delete the authentication data that we have stored locally (eg; logout)
def deleteAuthData(self) -> None:
if self._auth_data is not None:
self._storeAuthData()
- self.onAuthStateChanged.emit(logged_in=False)
+ self.onAuthStateChanged.emit(logged_in = False)
- # Start the flow to become authenticated. This will start a new webbrowser tap, prompting the user to login.
+ ## Start the flow to become authenticated. This will start a new webbrowser tap, prompting the user to login.
def startAuthorizationFlow(self) -> None:
Logger.log("d", "Starting new OAuth2 flow...")
@@ -120,7 +157,7 @@ class AuthorizationService:
"redirect_uri": self._settings.CALLBACK_URL,
"scope": self._settings.CLIENT_SCOPES,
"response_type": "code",
- "state": "CuraDriveIsAwesome",
+ "state": "(.Y.)",
"code_challenge": challenge_code,
"code_challenge_method": "S512"
})
@@ -131,16 +168,16 @@ class AuthorizationService:
# Start a local web server to receive the callback URL on.
self._server.start(verification_code)
- # Callback method for the authentication flow.
+ ## Callback method for the authentication flow.
def _onAuthStateChanged(self, auth_response: AuthenticationResponse) -> None:
if auth_response.success:
self._storeAuthData(auth_response)
- self.onAuthStateChanged.emit(logged_in=True)
+ self.onAuthStateChanged.emit(logged_in = True)
else:
- self.onAuthenticationError.emit(logged_in=False, error_message=auth_response.err_message)
+ self.onAuthenticationError.emit(logged_in = False, error_message = auth_response.err_message)
self._server.stop() # Stop the web server at all times.
- # Load authentication data from preferences.
+ ## Load authentication data from preferences.
def loadAuthDataFromPreferences(self) -> None:
if self._preferences is None:
Logger.log("e", "Unable to load authentication data, since no preference has been set!")
@@ -149,12 +186,24 @@ class AuthorizationService:
preferences_data = json.loads(self._preferences.getValue(self._settings.AUTH_DATA_PREFERENCE_KEY))
if preferences_data:
self._auth_data = AuthenticationResponse(**preferences_data)
- self.onAuthStateChanged.emit(logged_in=True)
+ # Also check if we can actually get the user profile information.
+ user_profile = self.getUserProfile()
+ if user_profile is not None:
+ self.onAuthStateChanged.emit(logged_in = True)
+ else:
+ if self._unable_to_get_data_message is not None:
+ 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.
+ ## 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
@@ -166,3 +215,9 @@ class AuthorizationService:
else:
self._user_profile = None
self._preferences.resetPreference(self._settings.AUTH_DATA_PREFERENCE_KEY)
+
+ self.accessTokenChanged.emit()
+
+ def _onMessageActionTriggered(self, _, action):
+ if action == "retry":
+ self.loadAuthDataFromPreferences()
diff --git a/cura/OAuth2/LocalAuthorizationServer.py b/cura/OAuth2/LocalAuthorizationServer.py
index 5a282d8135..25b2435012 100644
--- a/cura/OAuth2/LocalAuthorizationServer.py
+++ b/cura/OAuth2/LocalAuthorizationServer.py
@@ -1,5 +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.
+
import threading
from typing import Optional, Callable, Any, TYPE_CHECKING
@@ -14,12 +15,15 @@ if TYPE_CHECKING:
class LocalAuthorizationServer:
- # The local LocalAuthorizationServer takes care of the oauth2 callbacks.
- # Once the flow is completed, this server should be closed down again by calling stop()
- # \param auth_helpers: An instance of the authorization helpers class.
- # \param auth_state_changed_callback: A callback function to be called when the authorization state changes.
- # \param daemon: Whether the server thread should be run in daemon mode. Note: Daemon threads are abruptly stopped
- # at shutdown. Their resources (e.g. open files) may never be released.
+ ## The local LocalAuthorizationServer takes care of the oauth2 callbacks.
+ # Once the flow is completed, this server should be closed down again by
+ # calling stop()
+ # \param auth_helpers An instance of the authorization helpers class.
+ # \param auth_state_changed_callback A callback function to be called when
+ # the authorization state changes.
+ # \param daemon Whether the server thread should be run in daemon mode.
+ # Note: Daemon threads are abruptly stopped at shutdown. Their resources
+ # (e.g. open files) may never be released.
def __init__(self, auth_helpers: "AuthorizationHelpers",
auth_state_changed_callback: Callable[["AuthenticationResponse"], Any],
daemon: bool) -> None:
@@ -30,8 +34,8 @@ class LocalAuthorizationServer:
self._auth_state_changed_callback = auth_state_changed_callback
self._daemon = daemon
- # Starts the local web server to handle the authorization callback.
- # \param verification_code: The verification code part of the OAuth2 client identification.
+ ## Starts the local web server to handle the authorization callback.
+ # \param verification_code The verification code part of the OAuth2 client identification.
def start(self, verification_code: str) -> None:
if self._web_server:
# If the server is already running (because of a previously aborted auth flow), we don't have to start it.
@@ -54,7 +58,7 @@ class LocalAuthorizationServer:
self._web_server_thread = threading.Thread(None, self._web_server.serve_forever, daemon = self._daemon)
self._web_server_thread.start()
- # Stops the web server if it was running. It also does some cleanup.
+ ## Stops the web server if it was running. It also does some cleanup.
def stop(self) -> None:
Logger.log("d", "Stopping local oauth2 web server...")
diff --git a/cura/OAuth2/Models.py b/cura/OAuth2/Models.py
index 83fc22554f..468351c62b 100644
--- a/cura/OAuth2/Models.py
+++ b/cura/OAuth2/Models.py
@@ -1,4 +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.
from typing import Optional
@@ -7,7 +8,7 @@ class BaseModel:
self.__dict__.update(kwargs)
-# OAuth OAuth2Settings data template.
+## OAuth OAuth2Settings data template.
class OAuth2Settings(BaseModel):
CALLBACK_PORT = None # type: Optional[int]
OAUTH_SERVER_URL = None # type: Optional[str]
@@ -19,14 +20,14 @@ class OAuth2Settings(BaseModel):
AUTH_FAILED_REDIRECT = "https://ultimaker.com" # type: str
-# User profile data template.
+## User profile data template.
class UserProfile(BaseModel):
user_id = None # type: Optional[str]
username = None # type: Optional[str]
profile_image_url = None # type: Optional[str]
-# Authentication data template.
+## Authentication data template.
class AuthenticationResponse(BaseModel):
"""Data comes from the token response with success flag and error message added."""
success = True # type: bool
@@ -36,25 +37,25 @@ class AuthenticationResponse(BaseModel):
expires_in = None # type: Optional[str]
scope = None # type: Optional[str]
err_message = None # type: Optional[str]
+ received_at = None # type: Optional[str]
-# Response status template.
+## Response status template.
class ResponseStatus(BaseModel):
code = 200 # type: int
- message = "" # type str
+ message = "" # type: str
-# Response data template.
+## Response data template.
class ResponseData(BaseModel):
status = None # type: ResponseStatus
data_stream = None # type: Optional[bytes]
redirect_uri = None # type: Optional[str]
content_type = "text/html" # type: str
-
-# Possible HTTP responses.
+## Possible HTTP responses.
HTTP_STATUS = {
- "OK": ResponseStatus(code=200, message="OK"),
- "NOT_FOUND": ResponseStatus(code=404, message="NOT FOUND"),
- "REDIRECT": ResponseStatus(code=302, message="REDIRECT")
+ "OK": ResponseStatus(code = 200, message = "OK"),
+ "NOT_FOUND": ResponseStatus(code = 404, message = "NOT FOUND"),
+ "REDIRECT": ResponseStatus(code = 302, message = "REDIRECT")
}
diff --git a/cura/OAuth2/__init__.py b/cura/OAuth2/__init__.py
index f3f6970c54..d5641e902f 100644
--- a/cura/OAuth2/__init__.py
+++ b/cura/OAuth2/__init__.py
@@ -1,2 +1,2 @@
-# Copyright (c) 2018 Ultimaker B.V.
+# Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
diff --git a/cura/ObjectsModel.py b/cura/ObjectsModel.py
deleted file mode 100644
index 8354540783..0000000000
--- a/cura/ObjectsModel.py
+++ /dev/null
@@ -1,94 +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.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._updateDelayed)
- Application.getInstance().getPreferences().preferenceChanged.connect(self._updateDelayed)
-
- self._update_timer = QTimer()
- self._update_timer.setInterval(100)
- self._update_timer.setSingleShot(True)
- self._update_timer.timeout.connect(self._update)
-
- self._build_plate_number = -1
-
- def setActiveBuildPlate(self, nr):
- self._build_plate_number = nr
- self._update()
-
- 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/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 8ddcdbfb2f..d9876b3b36 100755
--- a/cura/PlatformPhysics.py
+++ b/cura/PlatformPhysics.py
@@ -17,7 +17,6 @@ from cura.Scene import ZOffsetDecorator
import random # used for list shuffling
-
class PlatformPhysics:
def __init__(self, controller, volume):
super().__init__()
@@ -40,8 +39,9 @@ class PlatformPhysics:
Application.getInstance().getPreferences().addPreference("physics/automatic_drop_down", True)
def _onSceneChanged(self, source):
- if not source.getMeshData():
+ if not source.callDecoration("isSliceable"):
return
+
self._change_timer.start()
def _onChangeTimerFinished(self):
@@ -76,7 +76,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
diff --git a/cura/PreviewPass.py b/cura/PreviewPass.py
index befb52ee5e..8465af4b83 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
@@ -83,30 +85,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
new file mode 100644
index 0000000000..3f20e0f3c4
--- /dev/null
+++ b/cura/PrinterOutput/FirmwareUpdater.py
@@ -0,0 +1,78 @@
+# Copyright (c) 2018 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+
+from PyQt5.QtCore import QObject, QUrl, pyqtSignal, pyqtProperty
+
+from enum import IntEnum
+from threading import Thread
+from typing import Union
+
+MYPY = False
+if MYPY:
+ from cura.PrinterOutput.PrinterOutputDevice import PrinterOutputDevice
+
+class FirmwareUpdater(QObject):
+ firmwareProgressChanged = pyqtSignal()
+ firmwareUpdateStateChanged = pyqtSignal()
+
+ def __init__(self, output_device: "PrinterOutputDevice") -> None:
+ super().__init__()
+
+ self._output_device = output_device
+
+ self._update_firmware_thread = Thread(target=self._updateFirmware, daemon=True)
+
+ self._firmware_file = ""
+ self._firmware_progress = 0
+ self._firmware_update_state = FirmwareUpdateState.idle
+
+ def updateFirmware(self, firmware_file: Union[str, QUrl]) -> None:
+ # the file path could be url-encoded.
+ if firmware_file.startswith("file://"):
+ self._firmware_file = QUrl(firmware_file).toLocalFile()
+ else:
+ self._firmware_file = firmware_file
+
+ self._setFirmwareUpdateState(FirmwareUpdateState.updating)
+
+ self._update_firmware_thread.start()
+
+ def _updateFirmware(self) -> None:
+ raise NotImplementedError("_updateFirmware needs to be implemented")
+
+ ## 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._firmware_file = ""
+ self._onFirmwareProgress(100)
+ self._setFirmwareUpdateState(FirmwareUpdateState.completed)
+
+ @pyqtProperty(int, notify = firmwareProgressChanged)
+ def firmwareProgress(self) -> int:
+ return self._firmware_progress
+
+ @pyqtProperty(int, notify=firmwareUpdateStateChanged)
+ def firmwareUpdateState(self) -> "FirmwareUpdateState":
+ return self._firmware_update_state
+
+ def _setFirmwareUpdateState(self, state: "FirmwareUpdateState") -> None:
+ if self._firmware_update_state != state:
+ self._firmware_update_state = state
+ self.firmwareUpdateStateChanged.emit()
+
+ # Callback function for firmware update progress.
+ def _onFirmwareProgress(self, progress: int, max_progress: int = 100) -> None:
+ self._firmware_progress = int(progress * 100 / max_progress) # Convert to scale of 0-100
+ self.firmwareProgressChanged.emit()
+
+
+class FirmwareUpdateState(IntEnum):
+ idle = 0
+ updating = 1
+ completed = 2
+ unknown_error = 3
+ communication_error = 4
+ io_error = 5
+ firmware_not_found_error = 6
+
diff --git a/cura/PrinterOutput/GenericOutputController.py b/cura/PrinterOutput/GenericOutputController.py
index 95e65b2f0b..c160459776 100644
--- a/cura/PrinterOutput/GenericOutputController.py
+++ b/cura/PrinterOutput/GenericOutputController.py
@@ -1,35 +1,37 @@
# Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
-from typing import TYPE_CHECKING
+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.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):
- def __init__(self, output_device):
+ def __init__(self, output_device: "PrinterOutputDevice") -> None:
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._preheat_printer = None # type: Optional[PrinterOutputModel]
self._preheat_hotends_timer = QTimer()
self._preheat_hotends_timer.setSingleShot(True)
self._preheat_hotends_timer.timeout.connect(self._onPreheatHotendsTimerFinished)
- self._preheat_hotends = set()
+ self._preheat_hotends = set() # type: Set[ExtruderOutputModel]
self._output_device.printersChanged.connect(self._onPrintersChanged)
- self._active_printer = None
+ self._active_printer = None # type: Optional[PrinterOutputModel]
- def _onPrintersChanged(self):
+ def _onPrintersChanged(self) -> None:
if self._active_printer:
self._active_printer.stateChanged.disconnect(self._onPrinterStateChanged)
self._active_printer.targetBedTemperatureChanged.disconnect(self._onTargetBedTemperatureChanged)
@@ -43,32 +45,33 @@ class GenericOutputController(PrinterOutputController):
for extruder in self._active_printer.extruders:
extruder.targetHotendTemperatureChanged.connect(self._onTargetHotendTemperatureChanged)
- def _onPrinterStateChanged(self):
- if self._active_printer.state != "idle":
+ def _onPrinterStateChanged(self) -> None:
+ if self._active_printer and self._active_printer.state != "idle":
if self._preheat_bed_timer.isActive():
self._preheat_bed_timer.stop()
- self._preheat_printer.updateIsPreheating(False)
+ if self._preheat_printer:
+ self._preheat_printer.updateIsPreheating(False)
if self._preheat_hotends_timer.isActive():
self._preheat_hotends_timer.stop()
for extruder in self._preheat_hotends:
extruder.updateIsPreheating(False)
self._preheat_hotends = set()
- def moveHead(self, printer: "PrinterOutputModel", x, y, z, speed):
+ def moveHead(self, printer: "PrinterOutputModel", x, y, z, speed) -> None:
self._output_device.sendCommand("G91")
self._output_device.sendCommand("G0 X%s Y%s Z%s F%s" % (x, y, z, speed))
self._output_device.sendCommand("G90")
- def homeHead(self, printer):
+ def homeHead(self, printer: "PrinterOutputModel") -> None:
self._output_device.sendCommand("G28 X Y")
- def homeBed(self, printer):
+ def homeBed(self, printer: "PrinterOutputModel") -> None:
self._output_device.sendCommand("G28 Z")
- def sendRawCommand(self, printer: "PrinterOutputModel", command: str):
+ def sendRawCommand(self, printer: "PrinterOutputModel", command: str) -> None:
self._output_device.sendCommand(command.upper()) #Most printers only understand uppercase g-code commands.
- def setJobState(self, job: "PrintJobOutputModel", state: str):
+ def setJobState(self, job: "PrintJobOutputModel", state: str) -> None:
if state == "pause":
self._output_device.pausePrint()
job.updateState("paused")
@@ -79,42 +82,46 @@ class GenericOutputController(PrinterOutputController):
self._output_device.cancelPrint()
pass
- def setTargetBedTemperature(self, printer: "PrinterOutputModel", temperature: int):
- self._output_device.sendCommand("M140 S%s" % temperature)
+ def setTargetBedTemperature(self, printer: "PrinterOutputModel", temperature: float) -> None:
+ self._output_device.sendCommand("M140 S%s" % round(temperature)) # The API doesn't allow floating point.
- def _onTargetBedTemperatureChanged(self):
- if self._preheat_bed_timer.isActive() and self._preheat_printer.targetBedTemperature == 0:
+ def _onTargetBedTemperatureChanged(self) -> None:
+ if self._preheat_bed_timer.isActive() and self._preheat_printer and self._preheat_printer.targetBedTemperature == 0:
self._preheat_bed_timer.stop()
self._preheat_printer.updateIsPreheating(False)
- def preheatBed(self, printer: "PrinterOutputModel", temperature, duration):
+ def preheatBed(self, printer: "PrinterOutputModel", temperature, duration) -> None:
try:
temperature = round(temperature) # The API doesn't allow floating point.
duration = round(duration)
except ValueError:
return # Got invalid values, can't pre-heat.
- self.setTargetBedTemperature(printer, temperature=temperature)
+ self.setTargetBedTemperature(printer, temperature = temperature)
self._preheat_bed_timer.setInterval(duration * 1000)
self._preheat_bed_timer.start()
self._preheat_printer = printer
printer.updateIsPreheating(True)
- def cancelPreheatBed(self, printer: "PrinterOutputModel"):
- self.setTargetBedTemperature(printer, temperature=0)
+ def cancelPreheatBed(self, printer: "PrinterOutputModel") -> None:
+ self.setTargetBedTemperature(printer, temperature = 0)
self._preheat_bed_timer.stop()
printer.updateIsPreheating(False)
- def _onPreheatBedTimerFinished(self):
+ def _onPreheatBedTimerFinished(self) -> None:
+ if not self._preheat_printer:
+ return
self.setTargetBedTemperature(self._preheat_printer, 0)
self._preheat_printer.updateIsPreheating(False)
- def setTargetHotendTemperature(self, printer: "PrinterOutputModel", position: int, temperature: int):
+ def setTargetHotendTemperature(self, printer: "PrinterOutputModel", position: int, temperature: Union[int, float]) -> None:
self._output_device.sendCommand("M104 S%s T%s" % (temperature, position))
- def _onTargetHotendTemperatureChanged(self):
+ def _onTargetHotendTemperatureChanged(self) -> None:
if not self._preheat_hotends_timer.isActive():
return
+ if not self._active_printer:
+ return
for extruder in self._active_printer.extruders:
if extruder in self._preheat_hotends and extruder.targetHotendTemperature == 0:
@@ -123,7 +130,7 @@ class GenericOutputController(PrinterOutputController):
if not self._preheat_hotends:
self._preheat_hotends_timer.stop()
- def preheatHotend(self, extruder: "ExtruderOutputModel", temperature, duration):
+ def preheatHotend(self, extruder: "ExtruderOutputModel", temperature, duration) -> None:
position = extruder.getPosition()
number_of_extruders = len(extruder.getPrinter().extruders)
if position >= number_of_extruders:
@@ -141,7 +148,7 @@ class GenericOutputController(PrinterOutputController):
self._preheat_hotends.add(extruder)
extruder.updateIsPreheating(True)
- def cancelPreheatHotend(self, extruder: "ExtruderOutputModel"):
+ def cancelPreheatHotend(self, extruder: "ExtruderOutputModel") -> None:
self.setTargetHotendTemperature(extruder.getPrinter(), extruder.getPosition(), temperature=0)
if extruder in self._preheat_hotends:
extruder.updateIsPreheating(False)
@@ -149,14 +156,14 @@ class GenericOutputController(PrinterOutputController):
if not self._preheat_hotends and self._preheat_hotends_timer.isActive():
self._preheat_hotends_timer.stop()
- def _onPreheatHotendsTimerFinished(self):
+ def _onPreheatHotendsTimerFinished(self) -> None:
for extruder in self._preheat_hotends:
self.setTargetHotendTemperature(extruder.getPrinter(), extruder.getPosition(), 0)
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
- def stopPreheatTimers(self):
+ def stopPreheatTimers(self) -> None:
if self._preheat_hotends_timer.isActive():
for extruder in self._preheat_hotends:
extruder.updateIsPreheating(False)
@@ -165,5 +172,6 @@ class GenericOutputController(PrinterOutputController):
self._preheat_hotends_timer.stop()
if self._preheat_bed_timer.isActive():
- self._preheat_printer.updateIsPreheating(False)
+ if self._preheat_printer:
+ self._preheat_printer.updateIsPreheating(False)
self._preheat_bed_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 77%
rename from cura/PrinterOutput/ExtruderConfigurationModel.py
rename to cura/PrinterOutput/Models/ExtruderConfigurationModel.py
index da0ad6b0b2..5b4cb5d6f5 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):
@@ -62,9 +62,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..7a17ef3cce
--- /dev/null
+++ b/cura/PrinterOutput/Models/MaterialOutputModel.py
@@ -0,0 +1,36 @@
+# 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
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 73%
rename from cura/PrinterOutput/ConfigurationModel.py
rename to cura/PrinterOutput/Models/PrinterConfigurationModel.py
index 89e609c913..47b9532080 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,9 @@ class ConfigurationModel(QObject):
return self._extruder_configurations
def setBuildplateConfiguration(self, buildplate_configuration: str) -> None:
- self._buildplate_configuration = buildplate_configuration
+ if self._buildplate_configuration != buildplate_configuration:
+ self._buildplate_configuration = buildplate_configuration
+ self.configurationChanged.emit()
@pyqtProperty(str, fset = setBuildplateConfiguration, notify = configurationChanged)
def buildplateConfiguration(self) -> str:
@@ -54,7 +56,7 @@ class ConfigurationModel(QObject):
for configuration in self._extruder_configurations:
if configuration is None:
return False
- return self._printer_type is not None
+ return self._printer_type != ""
def __str__(self):
message_chunks = []
@@ -69,7 +71,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.
@@ -84,4 +102,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..13fe85e674
--- /dev/null
+++ b/cura/PrinterOutput/Models/PrinterOutputModel.py
@@ -0,0 +1,312 @@
+# 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
+
+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._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 = 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._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[PrinterConfigurationModel]:
+ if self._printer_configuration.isValid():
+ return self._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()
\ No newline at end of file
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/NetworkCamera.py b/cura/PrinterOutput/NetworkCamera.py
deleted file mode 100644
index 5b28ffd30d..0000000000
--- a/cura/PrinterOutput/NetworkCamera.py
+++ /dev/null
@@ -1,119 +0,0 @@
-from UM.Logger import Logger
-
-from PyQt5.QtCore import QUrl, pyqtProperty, pyqtSignal, QObject, pyqtSlot
-from PyQt5.QtGui import QImage
-from PyQt5.QtNetwork import QNetworkRequest, QNetworkReply, QNetworkAccessManager
-
-
-class NetworkCamera(QObject):
- newImage = pyqtSignal()
-
- def __init__(self, target = None, parent = None):
- super().__init__(parent)
- self._stream_buffer = b""
- self._stream_buffer_start_index = -1
- self._manager = None
- self._image_request = None
- self._image_reply = None
- self._image = QImage()
- self._image_id = 0
-
- self._target = target
- self._started = False
-
- @pyqtSlot(str)
- def setTarget(self, target):
- restart_required = False
- if self._started:
- self.stop()
- restart_required = True
-
- self._target = target
-
- if restart_required:
- self.start()
-
- @pyqtProperty(QUrl, notify=newImage)
- def latestImage(self):
- self._image_id += 1
- # There is an image provider that is called "camera". 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://camera/" + str(self._image_id)
-
- return QUrl(temp, QUrl.TolerantMode)
-
- @pyqtSlot()
- def start(self):
- # Ensure that previous requests (if any) are stopped.
- self.stop()
- if self._target is None:
- Logger.log("w", "Unable to start camera stream without target!")
- return
- self._started = True
- url = QUrl(self._target)
- self._image_request = QNetworkRequest(url)
- if self._manager is None:
- self._manager = QNetworkAccessManager()
-
- self._image_reply = self._manager.get(self._image_request)
- self._image_reply.downloadProgress.connect(self._onStreamDownloadProgress)
-
- @pyqtSlot()
- def stop(self):
- self._stream_buffer = b""
- self._stream_buffer_start_index = -1
-
- if self._image_reply:
- try:
- # disconnect the signal
- try:
- self._image_reply.downloadProgress.disconnect(self._onStreamDownloadProgress)
- except Exception:
- pass
- # abort the request if it's not finished
- if not self._image_reply.isFinished():
- self._image_reply.close()
- except Exception as e: # RuntimeError
- pass # It can happen that the wrapped c++ object is already deleted.
-
- self._image_reply = None
- self._image_request = None
-
- self._manager = None
-
- self._started = False
-
- def getImage(self):
- return self._image
-
- ## Ensure that close gets called when object is destroyed
- def __del__(self):
- self.stop()
-
- def _onStreamDownloadProgress(self, bytes_received, bytes_total):
- # An MJPG stream is (for our purpose) a stream of concatenated JPG images.
- # JPG images start with the marker 0xFFD8, and end with 0xFFD9
- if self._image_reply is None:
- return
- self._stream_buffer += self._image_reply.readAll()
-
- if len(self._stream_buffer) > 2000000: # No single camera frame should be 2 Mb or larger
- Logger.log("w", "MJPEG buffer exceeds reasonable size. Restarting stream...")
- self.stop() # resets stream buffer and start index
- self.start()
- return
-
- if self._stream_buffer_start_index == -1:
- self._stream_buffer_start_index = self._stream_buffer.indexOf(b'\xff\xd8')
- stream_buffer_end_index = self._stream_buffer.lastIndexOf(b'\xff\xd9')
- # If this happens to be more than a single frame, then so be it; the JPG decoder will
- # ignore the extra data. We do it like this in order not to get a buildup of frames
-
- if self._stream_buffer_start_index != -1 and stream_buffer_end_index != -1:
- jpg_data = self._stream_buffer[self._stream_buffer_start_index:stream_buffer_end_index + 2]
- self._stream_buffer = self._stream_buffer[stream_buffer_end_index + 2:]
- self._stream_buffer_start_index = -1
- self._image.loadFromData(jpg_data)
-
- self.newImage.emit()
diff --git a/cura/PrinterOutput/NetworkMJPGImage.py b/cura/PrinterOutput/NetworkMJPGImage.py
new file mode 100644
index 0000000000..522d684085
--- /dev/null
+++ b/cura/PrinterOutput/NetworkMJPGImage.py
@@ -0,0 +1,153 @@
+# Copyright (c) 2018 Aldo Hoeben / fieldOfView
+# NetworkMJPGImage is released under the terms of the LGPLv3 or higher.
+
+from PyQt5.QtCore import QUrl, pyqtProperty, pyqtSignal, pyqtSlot, QRect, QByteArray
+from PyQt5.QtGui import QImage, QPainter
+from PyQt5.QtQuick import QQuickPaintedItem
+from PyQt5.QtNetwork import QNetworkRequest, QNetworkReply, QNetworkAccessManager
+
+from UM.Logger import Logger
+
+#
+# A QQuickPaintedItem that progressively downloads a network mjpeg stream,
+# picks it apart in individual jpeg frames, and paints it.
+#
+class NetworkMJPGImage(QQuickPaintedItem):
+
+ def __init__(self, *args, **kwargs) -> None:
+ super().__init__(*args, **kwargs)
+
+ self._stream_buffer = QByteArray()
+ self._stream_buffer_start_index = -1
+ self._network_manager = None # type: QNetworkAccessManager
+ self._image_request = None # type: QNetworkRequest
+ self._image_reply = None # type: QNetworkReply
+ self._image = QImage()
+ self._image_rect = QRect()
+
+ self._source_url = QUrl()
+ self._started = False
+
+ self._mirror = False
+
+ self.setAntialiasing(True)
+
+ ## Ensure that close gets called when object is destroyed
+ def __del__(self) -> None:
+ self.stop()
+
+
+ def paint(self, painter: "QPainter") -> None:
+ if self._mirror:
+ painter.drawImage(self.contentsBoundingRect(), self._image.mirrored())
+ return
+
+ painter.drawImage(self.contentsBoundingRect(), self._image)
+
+
+ def setSourceURL(self, source_url: "QUrl") -> None:
+ self._source_url = source_url
+ self.sourceURLChanged.emit()
+ if self._started:
+ self.start()
+
+ def getSourceURL(self) -> "QUrl":
+ return self._source_url
+
+ sourceURLChanged = pyqtSignal()
+ source = pyqtProperty(QUrl, fget = getSourceURL, fset = setSourceURL, notify = sourceURLChanged)
+
+ def setMirror(self, mirror: bool) -> None:
+ if mirror == self._mirror:
+ return
+ self._mirror = mirror
+ self.mirrorChanged.emit()
+ self.update()
+
+ def getMirror(self) -> bool:
+ return self._mirror
+
+ mirrorChanged = pyqtSignal()
+ mirror = pyqtProperty(bool, fget = getMirror, fset = setMirror, notify = mirrorChanged)
+
+ imageSizeChanged = pyqtSignal()
+
+ @pyqtProperty(int, notify = imageSizeChanged)
+ def imageWidth(self) -> int:
+ return self._image.width()
+
+ @pyqtProperty(int, notify = imageSizeChanged)
+ def imageHeight(self) -> int:
+ return self._image.height()
+
+
+ @pyqtSlot()
+ def start(self) -> None:
+ self.stop() # Ensure that previous requests (if any) are stopped.
+
+ if not self._source_url:
+ Logger.log("w", "Unable to start camera stream without target!")
+ return
+ self._started = True
+
+ self._image_request = QNetworkRequest(self._source_url)
+ if self._network_manager is None:
+ self._network_manager = QNetworkAccessManager()
+
+ self._image_reply = self._network_manager.get(self._image_request)
+ self._image_reply.downloadProgress.connect(self._onStreamDownloadProgress)
+
+ @pyqtSlot()
+ def stop(self) -> None:
+ self._stream_buffer = QByteArray()
+ self._stream_buffer_start_index = -1
+
+ if self._image_reply:
+ try:
+ try:
+ self._image_reply.downloadProgress.disconnect(self._onStreamDownloadProgress)
+ except Exception:
+ pass
+
+ if not self._image_reply.isFinished():
+ self._image_reply.close()
+ except Exception as e: # RuntimeError
+ pass # It can happen that the wrapped c++ object is already deleted.
+
+ self._image_reply = None
+ self._image_request = None
+
+ self._network_manager = None
+
+ self._started = False
+
+
+ def _onStreamDownloadProgress(self, bytes_received: int, bytes_total: int) -> None:
+ # An MJPG stream is (for our purpose) a stream of concatenated JPG images.
+ # JPG images start with the marker 0xFFD8, and end with 0xFFD9
+ if self._image_reply is None:
+ return
+ self._stream_buffer += self._image_reply.readAll()
+
+ if len(self._stream_buffer) > 2000000: # No single camera frame should be 2 Mb or larger
+ Logger.log("w", "MJPEG buffer exceeds reasonable size. Restarting stream...")
+ self.stop() # resets stream buffer and start index
+ self.start()
+ return
+
+ if self._stream_buffer_start_index == -1:
+ self._stream_buffer_start_index = self._stream_buffer.indexOf(b'\xff\xd8')
+ stream_buffer_end_index = self._stream_buffer.lastIndexOf(b'\xff\xd9')
+ # If this happens to be more than a single frame, then so be it; the JPG decoder will
+ # ignore the extra data. We do it like this in order not to get a buildup of frames
+
+ if self._stream_buffer_start_index != -1 and stream_buffer_end_index != -1:
+ jpg_data = self._stream_buffer[self._stream_buffer_start_index:stream_buffer_end_index + 2]
+ self._stream_buffer = self._stream_buffer[stream_buffer_end_index + 2:]
+ self._stream_buffer_start_index = -1
+ self._image.loadFromData(jpg_data)
+
+ if self._image.rect() != self._image_rect:
+ self.imageSizeChanged.emit()
+
+ self.update()
diff --git a/cura/PrinterOutput/NetworkedPrinterOutputDevice.py b/cura/PrinterOutput/NetworkedPrinterOutputDevice.py
index d9c5707a03..e23341ba8a 100644
--- a/cura/PrinterOutput/NetworkedPrinterOutputDevice.py
+++ b/cura/PrinterOutput/NetworkedPrinterOutputDevice.py
@@ -4,19 +4,23 @@
from UM.FileHandler.FileHandler import FileHandler #For typing.
from UM.Logger import Logger
from UM.Scene.SceneNode import SceneNode #For typing.
+from cura.API import Account
from cura.CuraApplication import CuraApplication
-from cura.PrinterOutputDevice import PrinterOutputDevice, ConnectionState
+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
from time import time
-from typing import Any, Callable, Dict, List, Optional
+from typing import Callable, Dict, List, Optional, Union
from enum import IntEnum
import os # To get the username
import gzip
+from cura.Settings.CuraContainerRegistry import CuraContainerRegistry
+
+
class AuthState(IntEnum):
NotAuthenticated = 1
AuthenticationRequested = 2
@@ -28,8 +32,8 @@ class AuthState(IntEnum):
class NetworkedPrinterOutputDevice(PrinterOutputDevice):
authenticationStateChanged = pyqtSignal()
- def __init__(self, device_id, address: str, properties: Dict[bytes, bytes], parent: QObject = None) -> None:
- super().__init__(device_id = device_id, parent = parent)
+ 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
@@ -41,7 +45,8 @@ class NetworkedPrinterOutputDevice(PrinterOutputDevice):
self._api_prefix = ""
self._address = address
self._properties = properties
- self._user_agent = "%s/%s " % (CuraApplication.getInstance().getApplicationName(), CuraApplication.getInstance().getVersion())
+ self._user_agent = "%s/%s " % (CuraApplication.getInstance().getApplicationName(),
+ CuraApplication.getInstance().getVersion())
self._onFinishedCallbacks = {} # type: Dict[str, Callable[[QNetworkReply], None]]
self._authentication_state = AuthState.NotAuthenticated
@@ -55,7 +60,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:
@@ -125,17 +131,15 @@ class NetworkedPrinterOutputDevice(PrinterOutputDevice):
if self._connection_state_before_timeout is None:
self._connection_state_before_timeout = self._connection_state
- self.setConnectionState(ConnectionState.closed)
+ 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:
- self._createNetworkManager()
- elif time() - self._last_manager_create_time > 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:
+ 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
self.setConnectionState(self._connection_state_before_timeout)
@@ -145,10 +149,15 @@ class NetworkedPrinterOutputDevice(PrinterOutputDevice):
url = QUrl("http://" + self._address + self._api_prefix + target)
request = QNetworkRequest(url)
if content_type is not None:
- request.setHeader(QNetworkRequest.ContentTypeHeader, "application/json")
+ request.setHeader(QNetworkRequest.ContentTypeHeader, content_type)
request.setHeader(QNetworkRequest.UserAgentHeader, self._user_agent)
return request
+ ## This method was only available privately before, but it was actually called from SendMaterialJob.py.
+ # We now have a public equivalent as well. We did not remove the private one as plugins might be using that.
+ def createFormPart(self, content_header: str, data: bytes, content_type: Optional[str] = None) -> QHttpPart:
+ return self._createFormPart(content_header, data, content_type)
+
def _createFormPart(self, content_header: str, data: bytes, content_type: Optional[str] = None) -> QHttpPart:
part = QHttpPart()
@@ -162,9 +171,15 @@ class NetworkedPrinterOutputDevice(PrinterOutputDevice):
part.setBody(data)
return part
- ## Convenience function to get the username from the OS.
- # The code was copied from the getpass module, as we try to use as little dependencies as possible.
+ ## Convenience function to get the username, either from the cloud or from the OS.
def _getUserName(self) -> str:
+ # check first if we are logged in with the Ultimaker Account
+ account = CuraApplication.getInstance().getCuraAPI().account # type: Account
+ if account and account.isLoggedIn:
+ return account.userName
+
+ # Otherwise get the username from the US
+ # The code below was copied from the getpass module, as we try to use as little dependencies as possible.
for name in ("LOGNAME", "USER", "LNAME", "USERNAME"):
user = os.environ.get(name)
if user:
@@ -180,49 +195,89 @@ class NetworkedPrinterOutputDevice(PrinterOutputDevice):
self._createNetworkManager()
assert (self._manager is not None)
- def put(self, target: str, data: str, on_finished: Optional[Callable[[QNetworkReply], None]]) -> None:
+ ## Sends a put request to the given path.
+ # \param url: The path after the API prefix.
+ # \param data: The data to be sent in the body
+ # \param content_type: The content type of the body data.
+ # \param on_finished: The function to call when the response is received.
+ # \param on_progress: The function to call when the progress changes. Parameters are bytes_sent / bytes_total.
+ def put(self, url: str, data: Union[str, bytes], content_type: Optional[str] = "application/json",
+ on_finished: Optional[Callable[[QNetworkReply], None]] = None,
+ on_progress: Optional[Callable[[int, int], None]] = None) -> None:
self._validateManager()
- request = self._createEmptyRequest(target)
- self._last_request_time = time()
- if self._manager is not None:
- reply = self._manager.put(request, data.encode())
- self._registerOnFinishedCallback(reply, on_finished)
- else:
- Logger.log("e", "Could not find manager.")
- def delete(self, target: str, on_finished: Optional[Callable[[QNetworkReply], None]]) -> None:
+ request = self._createEmptyRequest(url, content_type = content_type)
+ self._last_request_time = time()
+
+ if not self._manager:
+ Logger.log("e", "No network manager was created to execute the PUT call with.")
+ return
+
+ body = data if isinstance(data, bytes) else data.encode() # type: bytes
+ reply = self._manager.put(request, body)
+ self._registerOnFinishedCallback(reply, on_finished)
+
+ if on_progress is not None:
+ reply.uploadProgress.connect(on_progress)
+
+ ## Sends a delete request to the given path.
+ # \param url: The path after the API prefix.
+ # \param on_finished: The function to be call when the response is received.
+ def delete(self, url: str, on_finished: Optional[Callable[[QNetworkReply], None]]) -> None:
self._validateManager()
- request = self._createEmptyRequest(target)
- self._last_request_time = time()
- if self._manager is not None:
- reply = self._manager.deleteResource(request)
- self._registerOnFinishedCallback(reply, on_finished)
- else:
- Logger.log("e", "Could not find manager.")
- def get(self, target: str, on_finished: Optional[Callable[[QNetworkReply], None]]) -> None:
+ request = self._createEmptyRequest(url)
+ self._last_request_time = time()
+
+ if not self._manager:
+ Logger.log("e", "No network manager was created to execute the DELETE call with.")
+ return
+
+ reply = self._manager.deleteResource(request)
+ self._registerOnFinishedCallback(reply, on_finished)
+
+ ## Sends a get request to the given path.
+ # \param url: The path after the API prefix.
+ # \param on_finished: The function to be call when the response is received.
+ def get(self, url: str, on_finished: Optional[Callable[[QNetworkReply], None]]) -> None:
self._validateManager()
- request = self._createEmptyRequest(target)
- self._last_request_time = time()
- if self._manager is not None:
- reply = self._manager.get(request)
- self._registerOnFinishedCallback(reply, on_finished)
- else:
- Logger.log("e", "Could not find manager.")
- def post(self, target: str, data: str, on_finished: Optional[Callable[[QNetworkReply], None]], on_progress: Callable = None) -> None:
+ request = self._createEmptyRequest(url)
+ self._last_request_time = time()
+
+ if not self._manager:
+ Logger.log("e", "No network manager was created to execute the GET call with.")
+ return
+
+ reply = self._manager.get(request)
+ self._registerOnFinishedCallback(reply, on_finished)
+
+ ## Sends a post request to the given path.
+ # \param url: The path after the API prefix.
+ # \param data: The data to be sent in the body
+ # \param on_finished: The function to call when the response is received.
+ # \param on_progress: The function to call when the progress changes. Parameters are bytes_sent / bytes_total.
+ def post(self, url: str, data: Union[str, bytes],
+ on_finished: Optional[Callable[[QNetworkReply], None]],
+ on_progress: Optional[Callable[[int, int], None]] = None) -> None:
self._validateManager()
- request = self._createEmptyRequest(target)
- self._last_request_time = time()
- if self._manager is not None:
- reply = self._manager.post(request, data)
- if on_progress is not None:
- reply.uploadProgress.connect(on_progress)
- self._registerOnFinishedCallback(reply, on_finished)
- else:
- Logger.log("e", "Could not find manager.")
- def postFormWithParts(self, target: str, parts: List[QHttpPart], on_finished: Optional[Callable[[QNetworkReply], None]], on_progress: Callable = None) -> QNetworkReply:
+ request = self._createEmptyRequest(url)
+ self._last_request_time = time()
+
+ if not self._manager:
+ Logger.log("e", "Could not find manager.")
+ return
+
+ body = data if isinstance(data, bytes) else data.encode() # type: bytes
+ reply = self._manager.post(request, body)
+ if on_progress is not None:
+ reply.uploadProgress.connect(on_progress)
+ self._registerOnFinishedCallback(reply, on_finished)
+
+ def postFormWithParts(self, target: str, parts: List[QHttpPart],
+ on_finished: Optional[Callable[[QNetworkReply], None]],
+ on_progress: Optional[Callable[[int, int], None]] = None) -> QNetworkReply:
self._validateManager()
request = self._createEmptyRequest(target, content_type=None)
multi_post_part = QHttpMultiPart(QHttpMultiPart.FormDataType)
@@ -257,22 +312,37 @@ class NetworkedPrinterOutputDevice(PrinterOutputDevice):
def _createNetworkManager(self) -> None:
Logger.log("d", "Creating network manager")
if self._manager:
- self._manager.finished.disconnect(self.__handleOnFinished)
+ self._manager.finished.disconnect(self._handleOnFinished)
self._manager.authenticationRequired.disconnect(self._onAuthenticationRequired)
self._manager = QNetworkAccessManager()
- self._manager.finished.connect(self.__handleOnFinished)
+ 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
- def __handleOnFinished(self, reply: QNetworkReply) -> None:
+ ## 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.
if reply.operation() == QNetworkAccessManager.PostOperation:
@@ -284,8 +354,8 @@ class NetworkedPrinterOutputDevice(PrinterOutputDevice):
self._last_response_time = time()
- if self._connection_state == ConnectionState.connecting:
- self.setConnectionState(ConnectionState.connected)
+ if self._connection_state == ConnectionState.Connecting:
+ self.setConnectionState(ConnectionState.Connected)
callback_key = reply.url().toString() + str(reply.operation())
try:
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 7366b95f86..df66412df3 100644
--- a/cura/PrinterOutput/PrintJobOutputModel.py
+++ b/cura/PrinterOutput/PrintJobOutputModel.py
@@ -1,150 +1,4 @@
-# Copyright (c) 2017 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 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 "camera". 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: "PrinterOutputModel"):
- 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):
- return self._time_total
-
- @pyqtProperty(int, notify = timeElapsedChanged)
- def timeElapsed(self):
- return self._time_elapsed
-
- @pyqtProperty(str, notify=stateChanged)
- def state(self):
- return self._state
-
- 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)
\ No newline at end of file
+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 58c6ef05a7..3d710582ca 100644
--- a/cura/PrinterOutput/PrinterOutputController.py
+++ b/cura/PrinterOutput/PrinterOutputController.py
@@ -1,57 +1,66 @@
-# 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.Logger import Logger
+from UM.Signal import Signal
MYPY = False
if MYPY:
- from cura.PrinterOutput.PrintJobOutputModel import PrintJobOutputModel
- from cura.PrinterOutput.ExtruderOutputModel import ExtruderOutputModel
- from cura.PrinterOutput.PrinterOutputModel import PrinterOutputModel
+ from .Models.PrintJobOutputModel import PrintJobOutputModel
+ from .Models.ExtruderOutputModel import ExtruderOutputModel
+ from .Models.PrinterOutputModel import PrinterOutputModel
+ from .PrinterOutputDevice import PrinterOutputDevice
class PrinterOutputController:
- def __init__(self, output_device):
+ def __init__(self, output_device: "PrinterOutputDevice") -> None:
self.can_pause = True
self.can_abort = True
self.can_pre_heat_bed = True
self.can_pre_heat_hotends = True
self.can_send_raw_gcode = True
self.can_control_manually = True
+ self.can_update_firmware = False
self._output_device = output_device
- def setTargetHotendTemperature(self, printer: "PrinterOutputModel", extruder: "ExtruderOutputModel", temperature: int):
+ def setTargetHotendTemperature(self, printer: "PrinterOutputModel", position: int, temperature: float) -> None:
Logger.log("w", "Set target hotend temperature not implemented in controller")
- def setTargetBedTemperature(self, printer: "PrinterOutputModel", temperature: int):
+ def setTargetBedTemperature(self, printer: "PrinterOutputModel", temperature: float) -> None:
Logger.log("w", "Set target bed temperature not implemented in controller")
- def setJobState(self, job: "PrintJobOutputModel", state: str):
+ def setJobState(self, job: "PrintJobOutputModel", state: str) -> None:
Logger.log("w", "Set job state not implemented in controller")
- def cancelPreheatBed(self, printer: "PrinterOutputModel"):
+ def cancelPreheatBed(self, printer: "PrinterOutputModel") -> None:
Logger.log("w", "Cancel preheat bed not implemented in controller")
- def preheatBed(self, printer: "PrinterOutputModel", temperature, duration):
+ def preheatBed(self, printer: "PrinterOutputModel", temperature, duration) -> None:
Logger.log("w", "Preheat bed not implemented in controller")
- def cancelPreheatHotend(self, extruder: "ExtruderOutputModel"):
+ def cancelPreheatHotend(self, extruder: "ExtruderOutputModel") -> None:
Logger.log("w", "Cancel preheat hotend not implemented in controller")
- def preheatHotend(self, extruder: "ExtruderOutputModel", temperature, duration):
+ def preheatHotend(self, extruder: "ExtruderOutputModel", temperature, duration) -> None:
Logger.log("w", "Preheat hotend not implemented in controller")
- def setHeadPosition(self, printer: "PrinterOutputModel", x, y, z, speed):
+ def setHeadPosition(self, printer: "PrinterOutputModel", x, y, z, speed) -> None:
Logger.log("w", "Set head position not implemented in controller")
- def moveHead(self, printer: "PrinterOutputModel", x, y, z, speed):
+ def moveHead(self, printer: "PrinterOutputModel", x, y, z, speed) -> None:
Logger.log("w", "Move head not implemented in controller")
- def homeBed(self, printer: "PrinterOutputModel"):
+ def homeBed(self, printer: "PrinterOutputModel") -> None:
Logger.log("w", "Home bed not implemented in controller")
- def homeHead(self, printer: "PrinterOutputModel"):
+ def homeHead(self, printer: "PrinterOutputModel") -> None:
Logger.log("w", "Home head not implemented in controller")
- def sendRawCommand(self, printer: "PrinterOutputModel", command: str):
+ def sendRawCommand(self, printer: "PrinterOutputModel", command: str) -> None:
Logger.log("w", "Custom command not implemented in controller")
+
+ canUpdateFirmwareChanged = Signal()
+ def setCanUpdateFirmware(self, can_update_firmware: bool) -> None:
+ if can_update_firmware != self.can_update_firmware:
+ self.can_update_firmware = can_update_firmware
+ self.canUpdateFirmwareChanged.emit()
\ No newline at end of file
diff --git a/cura/PrinterOutput/PrinterOutputDevice.py b/cura/PrinterOutput/PrinterOutputDevice.py
new file mode 100644
index 0000000000..d4a37b3d68
--- /dev/null
+++ b/cura/PrinterOutput/PrinterOutputDevice.py
@@ -0,0 +1,261 @@
+# 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.Decorators import deprecated
+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
+
+ @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["PrinterConfigurationModel"]:
+ 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)
diff --git a/cura/PrinterOutput/PrinterOutputModel.py b/cura/PrinterOutput/PrinterOutputModel.py
index f009a33178..87020ce2d0 100644
--- a/cura/PrinterOutput/PrinterOutputModel.py
+++ b/cura/PrinterOutput/PrinterOutputModel.py
@@ -1,285 +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, QVariant, pyqtSlot
-from typing import 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()
- printerTypeChanged = pyqtSignal()
- buildplateChanged = pyqtSignal()
- cameraChanged = pyqtSignal()
- configurationChanged = pyqtSignal()
-
- def __init__(self, output_controller: "PrinterOutputController", number_of_extruders: int = 1, parent=None, firmware_version = "") -> None:
- super().__init__(parent)
- self._bed_temperature = -1 # Use -1 for no heated bed.
- self._target_bed_temperature = 0
- self._name = ""
- self._key = "" # Unique identifier
- self._controller = output_controller
- 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_name = None
-
- self._printer_configuration.extruderConfigurations = [extruder.extruderConfiguration for extruder in
- self._extruders]
-
- self._camera = None
-
- @pyqtProperty(str, constant = True)
- def firmwareVersion(self):
- return self._firmware_version
-
- def setCamera(self, camera):
- if self._camera is not camera:
- self._camera = camera
- self.cameraChanged.emit()
-
- def updateIsPreheating(self, pre_heating):
- if self._is_preheating != pre_heating:
- self._is_preheating = pre_heating
- self.isPreheatingChanged.emit()
-
- @pyqtProperty(bool, notify=isPreheatingChanged)
- def isPreheating(self):
- return self._is_preheating
-
- @pyqtProperty(QObject, notify=cameraChanged)
- def camera(self):
- return self._camera
-
- @pyqtProperty(str, notify = printerTypeChanged)
- def type(self):
- return self._printer_type
-
- def updateType(self, printer_type):
- if self._printer_type != printer_type:
- self._printer_type = printer_type
- self._printer_configuration.printerType = self._printer_type
- self.printerTypeChanged.emit()
- self.configurationChanged.emit()
-
- @pyqtProperty(str, notify = buildplateChanged)
- def buildplate(self):
- return self._buildplate_name
-
- def updateBuildplateName(self, buildplate_name):
- if self._buildplate_name != buildplate_name:
- self._buildplate_name = buildplate_name
- self._printer_configuration.buildplateConfiguration = self._buildplate_name
- self.buildplateChanged.emit()
- self.configurationChanged.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()
-
- @pyqtSlot()
- def homeHead(self):
- self._controller.homeHead(self)
-
- @pyqtSlot()
- def homeBed(self):
- self._controller.homeBed(self)
-
- @pyqtSlot(str)
- def sendRawCommand(self, command: str):
- self._controller.sendRawCommand(self, command)
-
- @pyqtProperty("QVariantList", constant = True)
- def extruders(self):
- return self._extruders
-
- @pyqtProperty(QVariant, notify = headPositionChanged)
- def headPosition(self):
- return {"x": self._head_position.x, "y": self._head_position.y, "z": self.head_position.z}
-
- def updateHeadPosition(self, x, y, z):
- 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, y, z, speed = 3000):
- self.updateHeadPosition(x, y, z)
- self._controller.setHeadPosition(self, x, y, z, speed)
-
- @pyqtProperty(float)
- @pyqtProperty(float, float)
- def setHeadX(self, x, speed = 3000):
- 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, speed = 3000):
- 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, speed = 3000):
- 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 = 0, y = 0, z = 0, speed = 3000):
- 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, duration):
- self._controller.preheatBed(self, temperature, duration)
-
- @pyqtSlot()
- def cancelPreheatBed(self):
- self._controller.cancelPreheatBed(self)
-
- def getController(self):
- return self._controller
-
- @pyqtProperty(str, notify=nameChanged)
- def name(self):
- return self._name
-
- def setName(self, name):
- self._setName(name)
- self.updateName(name)
-
- def updateName(self, name):
- if self._name != name:
- self._name = name
- self.nameChanged.emit()
-
- ## Update the bed temperature. This only changes it locally.
- def updateBedTemperature(self, temperature):
- if self._bed_temperature != temperature:
- self._bed_temperature = temperature
- self.bedTemperatureChanged.emit()
-
- def updateTargetBedTemperature(self, temperature):
- 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(int)
- def setTargetBedTemperature(self, temperature):
- self._controller.setTargetBedTemperature(self, temperature)
- self.updateTargetBedTemperature(temperature)
-
- def updateActivePrintJob(self, print_job):
- 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):
- if self._printer_state != printer_state:
- self._printer_state = printer_state
- self.stateChanged.emit()
-
- @pyqtProperty(QObject, notify = activePrintJobChanged)
- def activePrintJob(self):
- return self._active_print_job
-
- @pyqtProperty(str, notify=stateChanged)
- def state(self):
- return self._printer_state
-
- @pyqtProperty(int, notify = bedTemperatureChanged)
- def bedTemperature(self):
- return self._bed_temperature
-
- @pyqtProperty(int, notify=targetBedTemperatureChanged)
- def targetBedTemperature(self):
- return self._target_bed_temperature
-
- # Does the printer support pre-heating the bed at all
- @pyqtProperty(bool, constant=True)
- def canPreHeatBed(self):
- 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):
- 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):
- 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):
- if self._controller:
- return self._controller.can_pause
- return False
-
- # Does the printer support abort at all
- @pyqtProperty(bool, constant=True)
- def canAbort(self):
- 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):
- if self._controller:
- return self._controller.can_control_manually
- return False
-
- # Returns the configuration (material, variant and buildplate) of the current printer
- @pyqtProperty(QObject, notify = configurationChanged)
- def printerConfiguration(self):
- 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 5ea65adb8e..51e563410c 100644
--- a/cura/PrinterOutputDevice.py
+++ b/cura/PrinterOutputDevice.py
@@ -1,228 +1,4 @@
-# Copyright (c) 2018 Ultimaker B.V.
-# Cura is released under the terms of the LGPLv3 or higher.
-
-from UM.Decorators import deprecated
-from UM.i18n import i18nCatalog
-from UM.OutputDevice.OutputDevice import OutputDevice
-from PyQt5.QtCore import pyqtProperty, QObject, QTimer, pyqtSignal
-from PyQt5.QtWidgets import QMessageBox
-
-from UM.Logger import Logger
-from UM.FileHandler.FileHandler import FileHandler #For typing.
-from UM.Scene.SceneNode import SceneNode #For typing.
-from UM.Signal import signalemitter
-from UM.Qt.QtApplication import QtApplication
-
-from enum import IntEnum # For the connection state tracking.
-from typing import Callable, List, Optional
-
-MYPY = False
-if MYPY:
- from cura.PrinterOutput.PrinterOutputModel import PrinterOutputModel
- from cura.PrinterOutput.ConfigurationModel import ConfigurationModel
-
-i18n_catalog = i18nCatalog("cura")
-
-
-## The current processing state of the backend.
-class ConnectionState(IntEnum):
- closed = 0
- connecting = 1
- connected = 2
- busy = 3
- error = 4
-
-
-## 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, 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._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(str, 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 = list(set([printer.printerConfiguration for printer in self._printers if printer.printerConfiguration is not None]))
- self._unique_configurations.sort(key = lambda k: k.printerType)
- self.uniqueConfigurationsChanged.emit()
-
- 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
\ No newline at end of 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/BlockSlicingDecorator.py b/cura/Scene/BlockSlicingDecorator.py
index 3fc0015836..0536e1635f 100644
--- a/cura/Scene/BlockSlicingDecorator.py
+++ b/cura/Scene/BlockSlicingDecorator.py
@@ -1,9 +1,12 @@
+# Copyright (c) 2018 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+
from UM.Scene.SceneNodeDecorator import SceneNodeDecorator
class BlockSlicingDecorator(SceneNodeDecorator):
- def __init__(self):
+ def __init__(self) -> None:
super().__init__()
- def isBlockSlicing(self):
+ def isBlockSlicing(self) -> bool:
return True
diff --git a/cura/Scene/ConvexHullDecorator.py b/cura/Scene/ConvexHullDecorator.py
index 52e687832c..2d8224eecc 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()
@@ -78,7 +80,8 @@ class ConvexHullDecorator(SceneNodeDecorator):
def getConvexHull(self) -> Optional[Polygon]:
if self._node is None:
return None
-
+ if self._node.callDecoration("isNonPrintingMesh"):
+ return None
hull = self._compute2DConvexHull()
if self._global_stack and self._node is not None and hull is not None:
@@ -108,7 +111,8 @@ class ConvexHullDecorator(SceneNodeDecorator):
def getConvexHullHead(self) -> Optional[Polygon]:
if self._node is None:
return None
-
+ if self._node.callDecoration("isNonPrintingMesh"):
+ 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()
@@ -124,6 +128,9 @@ class ConvexHullDecorator(SceneNodeDecorator):
def getConvexHullBoundary(self) -> Optional[Polygon]:
if self._node is None:
return None
+
+ if self._node.callDecoration("isNonPrintingMesh"):
+ return None
if self._global_stack:
if self._global_stack.getProperty("print_sequence", "value") == "one_at_a_time" and not self.hasGroupAsParent(self._node):
@@ -142,6 +149,12 @@ class ConvexHullDecorator(SceneNodeDecorator):
controller = Application.getInstance().getController()
root = controller.getScene().getRoot()
if self._node is None or controller.isToolOperationActive() or not self.__isDescendant(root, self._node):
+ # If the tool operation is still active, we need to compute the convex hull later after the controller is
+ # no longer active.
+ if controller.isToolOperationActive():
+ self.recomputeConvexHullDelayed()
+ return
+
if self._convex_hull_node:
self._convex_hull_node.setParent(None)
self._convex_hull_node = None
@@ -181,7 +194,10 @@ class ConvexHullDecorator(SceneNodeDecorator):
for child in self._node.getChildren():
child_hull = child.callDecoration("_compute2DConvexHull")
if child_hull:
- points = numpy.append(points, child_hull.getPoints(), axis = 0)
+ try:
+ points = numpy.append(points, child_hull.getPoints(), axis = 0)
+ except ValueError:
+ pass
if points.size < 3:
return None
@@ -233,7 +249,7 @@ class ConvexHullDecorator(SceneNodeDecorator):
# See http://stackoverflow.com/questions/16970982/find-unique-rows-in-numpy-array
vertex_byte_view = numpy.ascontiguousarray(vertex_data).view(
numpy.dtype((numpy.void, vertex_data.dtype.itemsize * vertex_data.shape[1])))
- _, idx = numpy.unique(vertex_byte_view, return_index=True)
+ _, idx = numpy.unique(vertex_byte_view, return_index = True)
vertex_data = vertex_data[idx] # Select the unique rows by index.
hull = Polygon(vertex_data)
@@ -266,7 +282,7 @@ class ConvexHullDecorator(SceneNodeDecorator):
head_and_fans = self._getHeadAndFans().intersectionConvexHulls(mirrored)
# Min head hull is used for the push free
- convex_hull = self._compute2DConvexHeadFull()
+ convex_hull = self._compute2DConvexHull()
if convex_hull:
return convex_hull.getMinkowskiHull(head_and_fans)
return None
@@ -280,16 +296,21 @@ class ConvexHullDecorator(SceneNodeDecorator):
# Add extra margin depending on adhesion type
adhesion_type = self._global_stack.getProperty("adhesion_type", "value")
+ max_length_available = 0.5 * min(
+ self._getSettingProperty("machine_width", "value"),
+ self._getSettingProperty("machine_depth", "value")
+ )
+
if adhesion_type == "raft":
- extra_margin = max(0, self._getSettingProperty("raft_margin", "value"))
+ extra_margin = min(max_length_available, max(0, self._getSettingProperty("raft_margin", "value")))
elif adhesion_type == "brim":
- extra_margin = max(0, self._getSettingProperty("brim_line_count", "value") * self._getSettingProperty("skirt_brim_line_width", "value"))
+ extra_margin = min(max_length_available, max(0, self._getSettingProperty("brim_line_count", "value") * self._getSettingProperty("skirt_brim_line_width", "value")))
elif adhesion_type == "none":
extra_margin = 0
elif adhesion_type == "skirt":
- extra_margin = max(
+ extra_margin = min(max_length_available, max(
0, self._getSettingProperty("skirt_gap", "value") +
- self._getSettingProperty("skirt_line_count", "value") * self._getSettingProperty("skirt_brim_line_width", "value"))
+ self._getSettingProperty("skirt_line_count", "value") * self._getSettingProperty("skirt_brim_line_width", "value")))
else:
raise Exception("Unknown bed adhesion type. Did you forget to update the convex hull calculations for your new bed adhesion type?")
@@ -386,4 +407,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 4c79c7d5dc..90bf536308 100644
--- a/cura/Scene/ConvexHullNode.py
+++ b/cura/Scene/ConvexHullNode.py
@@ -1,7 +1,10 @@
# Copyright (c) 2015 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
+from typing import Optional
from UM.Application import Application
+from UM.Math.Polygon import Polygon
+from UM.Qt.QtApplication import QtApplication
from UM.Scene.SceneNode import SceneNode
from UM.Resources import Resources
from UM.Math.Color import Color
@@ -16,7 +19,7 @@ class ConvexHullNode(SceneNode):
# location an object uses on the buildplate. This area (or area's in case of one at a time printing) is
# then displayed as a transparent shadow. If the adhesion type is set to raft, the area is extruded
# to represent the raft as well.
- def __init__(self, node, hull, thickness, parent = None):
+ def __init__(self, node: SceneNode, hull: Optional[Polygon], thickness: float, parent: Optional[SceneNode] = None) -> None:
super().__init__(parent)
self.setCalculateBoundingBox(False)
@@ -25,7 +28,11 @@ class ConvexHullNode(SceneNode):
# Color of the drawn convex hull
if not Application.getInstance().getIsHeadLess():
- self._color = Color(*Application.getInstance().getTheme().getColor("convex_hull").getRgb())
+ theme = QtApplication.getInstance().getTheme()
+ if theme:
+ self._color = Color(*theme.getColor("convex_hull").getRgb())
+ else:
+ self._color = Color(0, 0, 0)
else:
self._color = Color(0, 0, 0)
@@ -47,7 +54,7 @@ class ConvexHullNode(SceneNode):
if hull_mesh_builder.addConvexPolygonExtrusion(
self._hull.getPoints()[::-1], # bottom layer is reversed
- self._mesh_height-thickness, self._mesh_height, color=self._color):
+ self._mesh_height - thickness, self._mesh_height, color = self._color):
hull_mesh = hull_mesh_builder.build()
self.setMeshData(hull_mesh)
@@ -75,7 +82,7 @@ class ConvexHullNode(SceneNode):
return True
- def _onNodeDecoratorsChanged(self, node):
+ def _onNodeDecoratorsChanged(self, node: SceneNode) -> None:
convex_hull_head = self._node.callDecoration("getConvexHullHead")
if convex_hull_head:
convex_hull_head_builder = MeshBuilder()
diff --git a/cura/Scene/CuraSceneController.py b/cura/Scene/CuraSceneController.py
index 4b19271538..91ff26cadc 100644
--- a/cura/Scene/CuraSceneController.py
+++ b/cura/Scene/CuraSceneController.py
@@ -3,7 +3,8 @@ from UM.Logger import Logger
from PyQt5.QtCore import Qt, pyqtSlot, QObject
from PyQt5.QtWidgets import QApplication
-from cura.ObjectsModel import ObjectsModel
+from UM.Scene.Camera import Camera
+from cura.UI.ObjectsModel import ObjectsModel
from cura.Machines.Models.MultiBuildPlateModel import MultiBuildPlateModel
from UM.Application import Application
@@ -33,7 +34,7 @@ class CuraSceneController(QObject):
source = args[0]
else:
source = None
- if not isinstance(source, SceneNode):
+ if not isinstance(source, SceneNode) or isinstance(source, Camera):
return
max_build_plate = self._calcMaxBuildPlate()
changed = False
diff --git a/cura/Scene/CuraSceneNode.py b/cura/Scene/CuraSceneNode.py
index 259c273329..4215c8fa84 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:
+ def collidesWithAreas(self, areas: List[Polygon]) -> bool:
convex_hull = self.callDecoration("getConvexHull")
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 572fea6ac4..d3dadb3f23 100644
--- a/cura/Scene/GCodeListDecorator.py
+++ b/cura/Scene/GCodeListDecorator.py
@@ -10,10 +10,10 @@ class GCodeListDecorator(SceneNodeDecorator):
def getGCodeList(self) -> List[str]:
return self._gcode_list
- def setGCodeList(self, list: List[str]):
+ def setGCodeList(self, list: List[str]) -> None:
self._gcode_list = list
def __deepcopy__(self, memo) -> "GCodeListDecorator":
copied_decorator = GCodeListDecorator()
copied_decorator.setGCodeList(self.getGCodeList())
- return copied_decorator
\ No newline at end of file
+ return copied_decorator
diff --git a/cura/Settings/ContainerManager.py b/cura/Settings/ContainerManager.py
index 3cfca1a944..2422fa3b21 100644
--- a/cura/Settings/ContainerManager.py
+++ b/cura/Settings/ContainerManager.py
@@ -47,8 +47,10 @@ 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
-
- super().__init__(parent = application)
+ try:
+ super().__init__(parent = application)
+ except TypeError:
+ super().__init__()
self._application = application # type: CuraApplication
self._plugin_registry = self._application.getPluginRegistry() # type: PluginRegistry
@@ -419,13 +421,13 @@ class ContainerManager(QObject):
self._container_name_filters[name_filter] = entry
## Import single profile, file_url does not have to end with curaprofile
- @pyqtSlot(QUrl, result="QVariantMap")
- def importProfile(self, file_url: QUrl):
+ @pyqtSlot(QUrl, result = "QVariantMap")
+ def importProfile(self, file_url: QUrl) -> Dict[str, str]:
if not file_url.isValid():
- return
+ return {"status": "error", "message": catalog.i18nc("@info:status", "Invalid file URL:") + " " + str(file_url)}
path = file_url.toLocalFile()
if not path:
- return
+ return {"status": "error", "message": catalog.i18nc("@info:status", "Invalid file URL:") + " " + str(file_url)}
return self._container_registry.importProfile(path)
@pyqtSlot(QObject, QUrl, str)
diff --git a/cura/Settings/CuraContainerRegistry.py b/cura/Settings/CuraContainerRegistry.py
index 11640adc0f..8e7c403f20 100644
--- a/cura/Settings/CuraContainerRegistry.py
+++ b/cura/Settings/CuraContainerRegistry.py
@@ -1,16 +1,16 @@
-# 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, Optional
-
+from typing import Any, cast, Dict, Optional
from PyQt5.QtWidgets import QMessageBox
from UM.Decorators import override
from UM.Settings.ContainerFormatError import ContainerFormatError
+from UM.Settings.Interfaces import ContainerInterface
from UM.Settings.ContainerRegistry import ContainerRegistry
from UM.Settings.ContainerStack import ContainerStack
from UM.Settings.InstanceContainer import InstanceContainer
@@ -28,7 +28,7 @@ from . import GlobalStack
import cura.CuraApplication
from cura.Machines.QualityManager import getMachineDefinitionIDForQualitySearch
-from cura.ReaderWriters.ProfileReader import NoProfileException
+from cura.ReaderWriters.ProfileReader import NoProfileException, ProfileReader
from UM.i18n import i18nCatalog
catalog = i18nCatalog("cura")
@@ -103,13 +103,14 @@ class CuraContainerRegistry(ContainerRegistry):
# \param instance_ids \type{list} the IDs of the profiles to export.
# \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, file_name, file_type) -> 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,7 +122,7 @@ 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:
@@ -132,17 +133,18 @@ 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
@@ -161,29 +163,29 @@ class CuraContainerRegistry(ContainerRegistry):
## Imports a profile from a file
#
- # \param file_name \type{str} the full path and filename of the profile to import
- # \return \type{Dict} dict with a 'status' key containing the string 'ok' or 'error', and a 'message' key
- # containing a message for the user
- def importProfile(self, file_name):
+ # \param file_name The full path and filename of the profile to import.
+ # \return Dict with a 'status' key containing the string 'ok' or 'error',
+ # and a 'message' key containing a message for the user.
+ def importProfile(self, file_name: str) -> Dict[str, str]:
Logger.log("d", "Attempting to import profile %s", file_name)
if not file_name:
- return { "status": "error", "message": catalog.i18nc("@info:status Don't translate the XML tags or !", "Failed to import profile from {0}: {1}", file_name, "Invalid path")}
-
- plugin_registry = PluginRegistry.getInstance()
- extension = file_name.split(".")[-1]
+ 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")}
global_stack = Application.getInstance().getGlobalContainerStack()
if not global_stack:
- return
+ 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)}
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
- profile_reader = plugin_registry.getPluginObject(plugin_id)
+ profile_reader = cast(ProfileReader, plugin_registry.getPluginObject(plugin_id))
try:
profile_or_list = profile_reader.read(file_name) # Try to open the file with the profile reader.
except NoProfileException:
@@ -221,13 +223,13 @@ class CuraContainerRegistry(ContainerRegistry):
# Make sure we have a profile_definition in the file:
if profile_definition is None:
break
- machine_definition = self.findDefinitionContainers(id = profile_definition)
- if not machine_definition:
+ machine_definitions = self.findDefinitionContainers(id = profile_definition)
+ if not machine_definitions:
Logger.log("e", "Incorrect profile [%s]. Unknown machine type [%s]", file_name, profile_definition)
return {"status": "error",
"message": catalog.i18nc("@info:status Don't translate the XML tags !", "This profile {0} contains incorrect data, could not import it.", file_name)
}
- machine_definition = machine_definition[0]
+ machine_definition = machine_definitions[0]
# Get the expected machine definition.
# i.e.: We expect gcode for a UM2 Extended to be defined as normal UM2 gcode...
@@ -267,20 +269,21 @@ class CuraContainerRegistry(ContainerRegistry):
profile.setMetaDataEntry("position", "0")
profile.setDirty(True)
if idx == 0:
- # move all per-extruder settings to the first extruder's quality_changes
+ # Move all per-extruder settings to the first extruder's quality_changes
for qc_setting_key in global_profile.getAllKeys():
settable_per_extruder = global_stack.getProperty(qc_setting_key, "settable_per_extruder")
if settable_per_extruder:
setting_value = global_profile.getProperty(qc_setting_key, "value")
setting_definition = global_stack.getSettingDefinition(qc_setting_key)
- new_instance = SettingInstance(setting_definition, profile)
- new_instance.setProperty("value", setting_value)
- new_instance.resetState() # Ensure that the state is not seen as a user state.
- profile.addInstance(new_instance)
- profile.setDirty(True)
+ if setting_definition is not None:
+ new_instance = SettingInstance(setting_definition, profile)
+ new_instance.setProperty("value", setting_value)
+ new_instance.resetState() # Ensure that the state is not seen as a user state.
+ 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:
@@ -290,7 +293,7 @@ class CuraContainerRegistry(ContainerRegistry):
for profile_index, profile in enumerate(profile_or_list):
if profile_index == 0:
# This is assumed to be the global profile
- profile_id = (global_stack.getBottom().getId() + "_" + name_seed).lower().replace(" ", "_")
+ profile_id = (cast(ContainerInterface, global_stack.getBottom()).getId() + "_" + name_seed).lower().replace(" ", "_")
elif profile_index < len(machine_extruders) + 1:
# This is assumed to be an extruder profile
@@ -302,8 +305,8 @@ class CuraContainerRegistry(ContainerRegistry):
profile.setMetaDataEntry("position", extruder_position)
profile_id = (extruder_id + "_" + name_seed).lower().replace(" ", "_")
- else: #More extruders in the imported file than in the machine.
- continue #Delete the additional profiles.
+ else: # More extruders in the imported file than in the machine.
+ continue # Delete the additional profiles.
result = self._configureProfile(profile, profile_id, new_name, expected_machine_definition)
if result is not None:
@@ -326,6 +329,23 @@ class CuraContainerRegistry(ContainerRegistry):
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.
@@ -385,30 +405,6 @@ class CuraContainerRegistry(ContainerRegistry):
result.append( (plugin_id, meta_data) )
return result
- ## Returns true if the current machine requires its own materials
- # \return True if the current machine requires its own materials
- def _machineHasOwnMaterials(self):
- global_container_stack = Application.getInstance().getGlobalContainerStack()
- if global_container_stack:
- return global_container_stack.getMetaDataEntry("has_materials", False)
- return False
-
- ## Gets the ID of the active material
- # \return the ID of the active material or the empty string
- def _activeMaterialId(self):
- global_container_stack = Application.getInstance().getGlobalContainerStack()
- if global_container_stack and global_container_stack.material:
- return global_container_stack.material.getId()
- return ""
-
- ## Returns true if the current machine requires its own quality profiles
- # \return true if the current machine requires its own quality profiles
- def _machineHasOwnQualities(self):
- global_container_stack = Application.getInstance().getGlobalContainerStack()
- if global_container_stack:
- return parseBool(global_container_stack.getMetaDataEntry("has_machine_quality", False))
- return False
-
## Convert an "old-style" pure ContainerStack to either an Extruder or Global stack.
def _convertContainerStack(self, container):
assert type(container) == ContainerStack
@@ -520,7 +516,7 @@ class CuraContainerRegistry(ContainerRegistry):
user_container.setMetaDataEntry("position", extruder_stack.getMetaDataEntry("position"))
if machine.userChanges:
- # for the newly created extruder stack, we need to move all "per-extruder" settings to the user changes
+ # For the newly created extruder stack, we need to move all "per-extruder" settings to the user changes
# container to the extruder stack.
for user_setting_key in machine.userChanges.getAllKeys():
settable_per_extruder = machine.getProperty(user_setting_key, "settable_per_extruder")
@@ -582,7 +578,7 @@ class CuraContainerRegistry(ContainerRegistry):
extruder_quality_changes_container.setMetaDataEntry("position", extruder_definition.getMetaDataEntry("position"))
extruder_stack.qualityChanges = self.findInstanceContainers(id = quality_changes_id)[0]
else:
- # if we still cannot find a quality changes container for the extruder, create a new one
+ # If we still cannot find a quality changes container for the extruder, create a new one
container_name = machine_quality_changes.getName()
container_id = self.uniqueName(extruder_stack.getId() + "_qc_" + container_name)
extruder_quality_changes_container = InstanceContainer(container_id, parent = application)
@@ -600,7 +596,7 @@ class CuraContainerRegistry(ContainerRegistry):
Logger.log("w", "Could not find quality_changes named [%s] for extruder [%s]",
machine_quality_changes.getName(), extruder_stack.getId())
else:
- # move all per-extruder settings to the extruder's quality changes
+ # Move all per-extruder settings to the extruder's quality changes
for qc_setting_key in machine_quality_changes.getAllKeys():
settable_per_extruder = machine.getProperty(qc_setting_key, "settable_per_extruder")
if settable_per_extruder:
@@ -641,7 +637,7 @@ class CuraContainerRegistry(ContainerRegistry):
if qc_name not in qc_groups:
qc_groups[qc_name] = []
qc_groups[qc_name].append(qc)
- # try to find from the quality changes cura directory too
+ # Try to find from the quality changes cura directory too
quality_changes_container = self._findQualityChangesContainerInCuraFolder(machine_quality_changes.getName())
if quality_changes_container:
qc_groups[qc_name].append(quality_changes_container)
@@ -655,7 +651,7 @@ class CuraContainerRegistry(ContainerRegistry):
else:
qc_dict["global"] = qc
if qc_dict["global"] is not None and len(qc_dict["extruders"]) == 1:
- # move per-extruder settings
+ # Move per-extruder settings
for qc_setting_key in qc_dict["global"].getAllKeys():
settable_per_extruder = machine.getProperty(qc_setting_key, "settable_per_extruder")
if settable_per_extruder:
@@ -689,17 +685,17 @@ class CuraContainerRegistry(ContainerRegistry):
try:
parser.read([file_path])
except:
- # skip, it is not a valid stack file
+ # Skip, it is not a valid stack file
continue
if not parser.has_option("general", "name"):
continue
if parser["general"]["name"] == name:
- # load the container
+ # Load the container
container_id = os.path.basename(file_path).replace(".inst.cfg", "")
if self.findInstanceContainers(id = container_id):
- # this container is already in the registry, skip it
+ # This container is already in the registry, skip it
continue
instance_container = InstanceContainer(container_id)
@@ -733,8 +729,8 @@ class CuraContainerRegistry(ContainerRegistry):
else:
Logger.log("w", "Could not find machine {machine} for extruder {extruder}", machine = extruder_stack.getMetaDataEntry("machine"), extruder = extruder_stack.getId())
- #Override just for the type.
+ # Override just for the type.
@classmethod
@override(ContainerRegistry)
def getInstance(cls, *args, **kwargs) -> "CuraContainerRegistry":
- return cast(CuraContainerRegistry, super().getInstance(*args, **kwargs))
\ No newline at end of file
+ return cast(CuraContainerRegistry, super().getInstance(*args, **kwargs))
diff --git a/cura/Settings/CuraContainerStack.py b/cura/Settings/CuraContainerStack.py
index 0ec95e2e41..042b065226 100755
--- a/cura/Settings/CuraContainerStack.py
+++ b/cura/Settings/CuraContainerStack.py
@@ -145,13 +145,11 @@ class CuraContainerStack(ContainerStack):
def setDefinition(self, new_definition: DefinitionContainerInterface) -> None:
self.replaceContainer(_ContainerIndexes.Definition, new_definition)
- ## Get the definition container.
- #
- # \return The definition container. Should always be a valid container, but can be equal to the empty InstanceContainer.
- @pyqtProperty(QObject, fset = setDefinition, notify = pyqtContainersChanged)
- def definition(self) -> DefinitionContainer:
+ def getDefinition(self) -> "DefinitionContainer":
return cast(DefinitionContainer, self._containers[_ContainerIndexes.Definition])
+ definition = pyqtProperty(QObject, fget = getDefinition, fset = setDefinition, notify = pyqtContainersChanged)
+
@override(ContainerStack)
def getBottom(self) -> "DefinitionContainer":
return self.definition
diff --git a/cura/Settings/CuraFormulaFunctions.py b/cura/Settings/CuraFormulaFunctions.py
index 1db01857f8..a8b416eeb5 100644
--- a/cura/Settings/CuraFormulaFunctions.py
+++ b/cura/Settings/CuraFormulaFunctions.py
@@ -5,6 +5,7 @@ from typing import Any, List, Optional, TYPE_CHECKING
from UM.Settings.PropertyEvaluationContext import PropertyEvaluationContext
from UM.Settings.SettingFunction import SettingFunction
+from UM.Logger import Logger
if TYPE_CHECKING:
from cura.CuraApplication import CuraApplication
@@ -38,7 +39,18 @@ class CuraFormulaFunctions:
extruder_position = int(machine_manager.defaultExtruderPosition)
global_stack = machine_manager.activeMachine
- extruder_stack = global_stack.extruders[str(extruder_position)]
+ try:
+ extruder_stack = global_stack.extruders[str(extruder_position)]
+ except KeyError:
+ 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)
if isinstance(value, SettingFunction):
diff --git a/cura/Settings/CuraStackBuilder.py b/cura/Settings/CuraStackBuilder.py
index 58109d3a8d..d20e686279 100644
--- a/cura/Settings/CuraStackBuilder.py
+++ b/cura/Settings/CuraStackBuilder.py
@@ -125,11 +125,16 @@ class CuraStackBuilder:
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 as e:
+ # It still needs to break, but we want to know what extruder ID made it break.
+ Logger.log("e", "Unable to find extruder with the id %s", extruder_definition_id)
+ raise e
# get material container for extruders
material_container = application.empty_material_container
- material_node = material_manager.getDefaultMaterial(global_stack, extruder_position, extruder_variant_name,
+ 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()
@@ -145,7 +150,6 @@ class CuraStackBuilder:
quality_container = application.empty_quality_container
)
new_extruder.setNextStack(global_stack)
- global_stack.addExtruder(new_extruder)
registry.addContainer(new_extruder)
diff --git a/cura/Settings/ExtruderManager.py b/cura/Settings/ExtruderManager.py
index 2514e17075..c00852cbc0 100755
--- a/cura/Settings/ExtruderManager.py
+++ b/cura/Settings/ExtruderManager.py
@@ -12,7 +12,7 @@ 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 UM.Decorators import deprecated
from typing import Any, cast, Dict, List, Optional, TYPE_CHECKING, Union
@@ -63,7 +63,7 @@ class ExtruderManager(QObject):
if not self._application.getGlobalContainerStack():
return None # No active machine, so no active extruder.
try:
- return self._extruder_trains[self._application.getGlobalContainerStack().getId()][str(self._active_extruder_index)].getId()
+ return self._extruder_trains[self._application.getGlobalContainerStack().getId()][str(self.activeExtruderIndex)].getId()
except KeyError: # Extruder index could be -1 if the global tab is selected, or the entry doesn't exist if the machine definition is wrong.
return None
@@ -83,8 +83,9 @@ class ExtruderManager(QObject):
# \param index The index of the new active extruder.
@pyqtSlot(int)
def setActiveExtruderIndex(self, index: int) -> None:
- self._active_extruder_index = index
- self.activeExtruderChanged.emit()
+ if self._active_extruder_index != index:
+ self._active_extruder_index = index
+ self.activeExtruderChanged.emit()
@pyqtProperty(int, notify = activeExtruderChanged)
def activeExtruderIndex(self) -> int:
@@ -94,6 +95,7 @@ class ExtruderManager(QObject):
#
# \param index The index of the extruder whose name to get.
@pyqtSlot(int, result = str)
+ @deprecated("Use Cura.MachineManager.activeMachine.extruders[index].name instead", "4.3")
def getExtruderName(self, index: int) -> str:
try:
return self.getActiveExtruderStacks()[index].getName()
@@ -113,7 +115,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
@@ -130,7 +132,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
@@ -139,12 +141,12 @@ 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)
def getActiveExtruderStack(self) -> Optional["ExtruderStack"]:
- return self.getExtruderStack(self._active_extruder_index)
+ return self.getExtruderStack(self.activeExtruderIndex)
## Get an extruder stack by index
def getExtruderStack(self, index) -> Optional["ExtruderStack"]:
@@ -179,7 +181,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():
@@ -204,7 +206,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()
@@ -223,7 +225,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
@@ -263,11 +274,14 @@ class ExtruderManager(QObject):
used_extruder_stack_ids.add(self.extruderIds[self.extruderValueWithDefault(str(global_stack.getProperty("support_roof_extruder_nr", "value")))])
# The platform adhesion extruder. Not used if using none.
- if global_stack.getProperty("adhesion_type", "value") != "none":
+ if global_stack.getProperty("adhesion_type", "value") != "none" or (
+ global_stack.getProperty("prime_tower_brim_enable", "value") and
+ global_stack.getProperty("adhesion_type", "value") != 'raft'):
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]
@@ -300,12 +314,7 @@ class ExtruderManager(QObject):
global_stack = self._application.getGlobalContainerStack()
if not global_stack:
return []
-
- result_tuple_list = sorted(list(global_stack.extruders.items()), key = lambda x: int(x[0]))
- result_list = [item[1] for item in result_tuple_list]
-
- machine_extruder_count = global_stack.getProperty("machine_extruder_count", "value")
- return result_list[:machine_extruder_count]
+ return global_stack.extruderList
def _globalContainerStackChanged(self) -> None:
# If the global container changed, the machine changed and might have extruders that were not registered yet
@@ -340,14 +349,15 @@ class ExtruderManager(QObject):
extruder_train.setNextStack(global_stack)
extruders_changed = True
- self._fixSingleExtrusionMachineExtruderDefinition(global_stack)
+ self.fixSingleExtrusionMachineExtruderDefinition(global_stack)
if extruders_changed:
self.extrudersChanged.emit(global_stack_id)
self.setActiveExtruderIndex(0)
+ self.activeExtruderChanged.emit()
# 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:
+ 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")
@@ -374,8 +384,6 @@ class ExtruderManager(QObject):
extruder_definition = container_registry.findDefinitionContainers(id = expected_extruder_definition_0_id)[0]
extruder_stack_0.definition = extruder_definition
- extruder_stack_0.setNextStack(global_stack)
-
## Get all extruder values for a certain setting.
#
# This is exposed to qml for display purposes
diff --git a/cura/Settings/ExtruderStack.py b/cura/Settings/ExtruderStack.py
index ca687e358b..edb0e7d41f 100644
--- a/cura/Settings/ExtruderStack.py
+++ b/cura/Settings/ExtruderStack.py
@@ -52,8 +52,8 @@ class ExtruderStack(CuraContainerStack):
return super().getNextStack()
def setEnabled(self, enabled: bool) -> None:
- if "enabled" not in self._metadata:
- self.setMetaDataEntry("enabled", "True")
+ if self.getMetaDataEntry("enabled", True) == enabled: # No change.
+ return # Don't emit a signal then.
self.setMetaDataEntry("enabled", str(enabled))
self.enabledChanged.emit()
@@ -65,16 +65,33 @@ class ExtruderStack(CuraContainerStack):
def getLoadingPriority(cls) -> int:
return 3
+ compatibleMaterialDiameterChanged = pyqtSignal()
+
## Return the filament diameter that the machine requires.
#
# If the machine has no requirement for the diameter, -1 is returned.
# \return The filament diameter for the printer
- @property
- def materialDiameter(self) -> float:
+ def getCompatibleMaterialDiameter(self) -> float:
context = PropertyEvaluationContext(self)
context.context["evaluate_from_container_index"] = _ContainerIndexes.Variant
- return self.getProperty("material_diameter", "value", context = context)
+ return float(self.getProperty("material_diameter", "value", context = context))
+
+ def setCompatibleMaterialDiameter(self, value: float) -> None:
+ old_approximate_diameter = self.getApproximateMaterialDiameter()
+ if self.getCompatibleMaterialDiameter() != value:
+ self.definitionChanges.setProperty("material_diameter", "value", value)
+ self.compatibleMaterialDiameterChanged.emit()
+
+ # Emit approximate diameter changed signal if needed
+ if old_approximate_diameter != self.getApproximateMaterialDiameter():
+ self.approximateMaterialDiameterChanged.emit()
+
+ compatibleMaterialDiameter = pyqtProperty(float, fset = setCompatibleMaterialDiameter,
+ fget = getCompatibleMaterialDiameter,
+ notify = compatibleMaterialDiameterChanged)
+
+ approximateMaterialDiameterChanged = pyqtSignal()
## Return the approximate filament diameter that the machine requires.
#
@@ -84,9 +101,11 @@ class ExtruderStack(CuraContainerStack):
# If the machine has no requirement for the diameter, -1 is returned.
#
# \return The approximate filament diameter for the printer
- @pyqtProperty(float)
- def approximateMaterialDiameter(self) -> float:
- return round(float(self.materialDiameter))
+ def getApproximateMaterialDiameter(self) -> float:
+ return round(self.getCompatibleMaterialDiameter())
+
+ approximateMaterialDiameter = pyqtProperty(float, fget = getApproximateMaterialDiameter,
+ notify = approximateMaterialDiameterChanged)
## Overridden from ContainerStack
#
diff --git a/cura/Settings/GlobalStack.py b/cura/Settings/GlobalStack.py
index 517b45eb98..3502088e2d 100755
--- a/cura/Settings/GlobalStack.py
+++ b/cura/Settings/GlobalStack.py
@@ -3,8 +3,10 @@
from collections import defaultdict
import threading
-from typing import Any, Dict, Optional, Set, TYPE_CHECKING
-from PyQt5.QtCore import pyqtProperty
+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.MimeTypeDatabase import MimeType, MimeTypeDatabase
@@ -13,6 +15,8 @@ from UM.Settings.SettingInstance import InstanceState
from UM.Settings.ContainerRegistry import ContainerRegistry
from UM.Settings.Interfaces import PropertyEvaluationContext
from UM.Logger import Logger
+from UM.Resources import Resources
+from UM.Platform import Platform
from UM.Util import parseBool
import cura.CuraApplication
@@ -32,6 +36,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
@@ -40,17 +50,79 @@ class GlobalStack(CuraContainerStack):
# Per thread we have our own resolving_settings, or strange things sometimes occur.
self._resolving_settings = defaultdict(set) #type: Dict[str, Set[str]] # keys are thread names
+ # Since the metadatachanged is defined in container stack, we can't use it here as a notifier for pyqt
+ # properties. So we need to tie them together like this.
+ self.metaDataChanged.connect(self.configuredConnectionTypesChanged)
+
+ extrudersChanged = pyqtSignal()
+ configuredConnectionTypesChanged = pyqtSignal()
+
## Get the list of extruders of this stack.
#
# \return The extruders registered with this stack.
- @pyqtProperty("QVariantMap")
+ @pyqtProperty("QVariantMap", notify = extrudersChanged)
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_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
+ ## The configured connection types can be used to find out if the global
+ # stack is configured to be connected with a printer, without having to
+ # know all the details as to how this is exactly done (and without
+ # actually setting the stack to be active).
+ #
+ # This data can then in turn also be used when the global stack is active;
+ # If we can't get a network connection, but it is configured to have one,
+ # we can display a different icon to indicate the difference.
+ @pyqtProperty("QVariantList", notify=configuredConnectionTypesChanged)
+ def configuredConnectionTypes(self) -> List[int]:
+ # 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(",")
+ 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
+
+ ## \sa configuredConnectionTypes
+ def addConfiguredConnectionType(self, connection_type: int) -> None:
+ configured_connection_types = self.configuredConnectionTypes
+ if connection_type not in configured_connection_types:
+ # Store the values as a string.
+ configured_connection_types.append(connection_type)
+ self.setMetaDataEntry("connection_type", ",".join([str(c_type) for c_type in configured_connection_types]))
+
+ ## \sa configuredConnectionTypes
+ def removeConfiguredConnectionType(self, connection_type: int) -> None:
+ configured_connection_types = self.configuredConnectionTypes
+ if connection_type in self.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]))
+
@classmethod
def getConfigurationTypeFromSerialized(cls, serialized: str) -> Optional[str]:
configuration_type = super().getConfigurationTypeFromSerialized(serialized)
@@ -85,6 +157,7 @@ class GlobalStack(CuraContainerStack):
return
self._extruders[position] = extruder
+ self.extrudersChanged.emit()
Logger.log("i", "Extruder[%s] added to [%s] at position [%s]", extruder.id, self.id, position)
## Overridden from ContainerStack
@@ -151,7 +224,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
@@ -191,15 +264,43 @@ class GlobalStack(CuraContainerStack):
def getHeadAndFansCoordinates(self):
return self.getProperty("machine_head_with_fans_polygon", "value")
- def getHasMaterials(self) -> bool:
+ @pyqtProperty(int, constant=True)
+ def hasMaterials(self):
return parseBool(self.getMetaDataEntry("has_materials", False))
- def getHasVariants(self) -> bool:
+ @pyqtProperty(int, constant=True)
+ def hasVariants(self):
return parseBool(self.getMetaDataEntry("has_variants", False))
- def getHasMachineQuality(self) -> bool:
- return parseBool(self.getMetaDataEntry("has_machine_quality", False))
+ @pyqtProperty(int, 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)
+ def getDefaultFirmwareName(self) -> str:
+ machine_has_heated_bed = self.getProperty("machine_heated_bed", "value")
+
+ baudrate = 250000
+ if Platform.isLinux():
+ # Linux prefers a baudrate of 115200 here because older versions of
+ # pySerial did not support a baudrate of 250000
+ baudrate = 115200
+
+ # If a firmware file is available, it should be specified in the definition for the printer
+ hex_file = self.getMetaDataEntry("firmware_file", None)
+ if machine_has_heated_bed:
+ hex_file = self.getMetaDataEntry("firmware_hbk_file", hex_file)
+
+ if not hex_file:
+ Logger.log("w", "There is no firmware for machine %s.", self.getBottom().id)
+ return ""
+
+ try:
+ return Resources.getPath(cura.CuraApplication.CuraApplication.ResourceTypes.Firmware, hex_file.format(baudrate=baudrate))
+ except FileNotFoundError:
+ Logger.log("w", "Firmware file %s not found.", hex_file)
+ return ""
## private:
global_stack_mime = MimeType(
diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py
index 063f894d23..7ae635baaa 100755
--- a/cura/Settings/MachineManager.py
+++ b/cura/Settings/MachineManager.py
@@ -1,17 +1,19 @@
# Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
-import collections
import time
-from typing import Any, Callable, List, Dict, TYPE_CHECKING, Optional, cast
+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
@@ -20,24 +22,26 @@ from UM.Message import Message
from UM.Settings.SettingFunction import SettingFunction
from UM.Signal import postponeSignals, CompressTechnique
-import cura.CuraApplication
from cura.Machines.QualityManager import getMachineDefinitionIDForQualitySearch
-from cura.PrinterOutputDevice import PrinterOutputDevice
-from cura.PrinterOutput.ConfigurationModel import ConfigurationModel
-from cura.PrinterOutput.ExtruderConfigurationModel import ExtruderConfigurationModel
-from cura.PrinterOutput.MaterialOutputModel import MaterialOutputModel
+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)
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
@@ -47,7 +51,7 @@ if TYPE_CHECKING:
class MachineManager(QObject):
- def __init__(self, parent: QObject = None) -> None:
+ def __init__(self, application: "CuraApplication", parent: Optional["QObject"] = None) -> None:
super().__init__(parent)
self._active_container_stack = None # type: Optional[ExtruderStack]
@@ -59,18 +63,17 @@ class MachineManager(QObject):
self._default_extruder_position = "0" # to be updated when extruders are switched on and off
- self.machine_extruder_material_update_dict = collections.defaultdict(list) #type: Dict[str, List[Callable[[], None]]]
-
- self._instance_container_timer = QTimer() #type: QTimer
+ self._instance_container_timer = QTimer() # type: QTimer
self._instance_container_timer.setInterval(250)
self._instance_container_timer.setSingleShot(True)
self._instance_container_timer.timeout.connect(self.__emitChangedSignals)
- self._application = cura.CuraApplication.CuraApplication.getInstance() #type: cura.CuraApplication.CuraApplication
+ self._application = application
+ self._container_registry = self._application.getContainerRegistry()
self._application.globalContainerStackChanged.connect(self._onGlobalContainerChanged)
- self._application.getContainerRegistry().containerLoadComplete.connect(self._onContainersChanged)
+ self._container_registry.containerLoadComplete.connect(self._onContainersChanged)
- ## When the global container is changed, active material probably needs to be updated.
+ # When the global container is changed, active material probably needs to be updated.
self.globalContainerChanged.connect(self.activeMaterialChanged)
self.globalContainerChanged.connect(self.activeVariantChanged)
self.globalContainerChanged.connect(self.activeQualityChanged)
@@ -80,21 +83,16 @@ class MachineManager(QObject):
self._stacks_have_errors = None # type: Optional[bool]
- self._empty_container = CuraContainerRegistry.getInstance().getEmptyInstanceContainer() #type: InstanceContainer
- self._empty_definition_changes_container = CuraContainerRegistry.getInstance().findContainers(id = "empty_definition_changes")[0] #type: InstanceContainer
- self._empty_variant_container = CuraContainerRegistry.getInstance().findContainers(id = "empty_variant")[0] #type: InstanceContainer
- self._empty_material_container = CuraContainerRegistry.getInstance().findContainers(id = "empty_material")[0] #type: InstanceContainer
- self._empty_quality_container = CuraContainerRegistry.getInstance().findContainers(id = "empty_quality")[0] #type: InstanceContainer
- self._empty_quality_changes_container = CuraContainerRegistry.getInstance().findContainers(id = "empty_quality_changes")[0] #type: InstanceContainer
-
self._onGlobalContainerChanged()
- ExtruderManager.getInstance().activeExtruderChanged.connect(self._onActiveExtruderStackChanged)
+ extruder_manager = self._application.getExtruderManager()
+
+ extruder_manager.activeExtruderChanged.connect(self._onActiveExtruderStackChanged)
self._onActiveExtruderStackChanged()
- ExtruderManager.getInstance().activeExtruderChanged.connect(self.activeMaterialChanged)
- ExtruderManager.getInstance().activeExtruderChanged.connect(self.activeVariantChanged)
- ExtruderManager.getInstance().activeExtruderChanged.connect(self.activeQualityChanged)
+ extruder_manager.activeExtruderChanged.connect(self.activeMaterialChanged)
+ extruder_manager.activeExtruderChanged.connect(self.activeVariantChanged)
+ extruder_manager.activeExtruderChanged.connect(self.activeQualityChanged)
self.globalContainerChanged.connect(self.activeStackChanged)
self.globalValueChanged.connect(self.activeStackValueChanged)
@@ -108,7 +106,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
@@ -116,17 +114,13 @@ class MachineManager(QObject):
self._application.callLater(self.setInitialActiveMachine)
- self._material_incompatible_message = Message(catalog.i18nc("@info:status",
- "The selected material is incompatible with the selected machine or configuration."),
- title = catalog.i18nc("@info:title", "Incompatible Material")) #type: Message
-
- containers = CuraContainerRegistry.getInstance().findInstanceContainers(id = self.activeMaterialId) #type: List[InstanceContainer]
+ containers = CuraContainerRegistry.getInstance().findInstanceContainers(id = self.activeMaterialId) # type: List[InstanceContainer]
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
+ 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.
@@ -159,10 +153,11 @@ class MachineManager(QObject):
blurSettings = pyqtSignal() # Emitted to force fields in the advanced sidebar to un-focus, so they update properly
outputDevicesChanged = pyqtSignal()
- currentConfigurationChanged = pyqtSignal() # Emitted every time the current configurations of the machine changes
+ currentConfigurationChanged = pyqtSignal() # Emitted every time the current configurations of the machine changes
printerConnectedStatusChanged = pyqtSignal() # Emitted every time the active machine change or the outputdevices change
rootMaterialChanged = pyqtSignal()
+ discoveredPrintersChanged = pyqtSignal()
def setInitialActiveMachine(self) -> None:
active_machine_id = self._application.getPreferences().getValue("cura/active_machine")
@@ -179,7 +174,7 @@ class MachineManager(QObject):
self.outputDevicesChanged.emit()
@pyqtProperty(QObject, notify = currentConfigurationChanged)
- def currentConfiguration(self) -> ConfigurationModel:
+ def currentConfiguration(self) -> PrinterConfigurationModel:
return self._current_printer_configuration
def _onCurrentConfigurationChanged(self) -> None:
@@ -192,23 +187,25 @@ class MachineManager(QObject):
for extruder in self._global_container_stack.extruders.values():
extruder_configuration = ExtruderConfigurationModel()
# For compare just the GUID is needed at this moment
- mat_type = extruder.material.getMetaDataEntry("material") if extruder.material != self._empty_material_container else None
- mat_guid = extruder.material.getMetaDataEntry("GUID") if extruder.material != self._empty_material_container else None
- mat_color = extruder.material.getMetaDataEntry("color_name") if extruder.material != self._empty_material_container else None
- mat_brand = extruder.material.getMetaDataEntry("brand") if extruder.material != self._empty_material_container else None
- mat_name = extruder.material.getMetaDataEntry("name") if extruder.material != self._empty_material_container else None
+ 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
+ mat_color = extruder.material.getMetaDataEntry("color_name") if extruder.material != empty_material_container else None
+ mat_brand = extruder.material.getMetaDataEntry("brand") if extruder.material != empty_material_container else None
+ mat_name = extruder.material.getMetaDataEntry("name") if extruder.material != empty_material_container else None
material_model = MaterialOutputModel(mat_guid, mat_type, mat_color, mat_brand, mat_name)
extruder_configuration.position = int(extruder.getMetaDataEntry("position"))
extruder_configuration.material = material_model
- extruder_configuration.hotendID = extruder.variant.getName() if extruder.variant != self._empty_variant_container else None
+ extruder_configuration.hotendID = extruder.variant.getName() if extruder.variant != empty_variant_container else None
self._current_printer_configuration.extruderConfigurations.append(extruder_configuration)
- self._current_printer_configuration.buildplateConfiguration = self._global_container_stack.getProperty("machine_buildplate_type", "value") if self._global_container_stack.variant != self._empty_variant_container else None
+ # 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.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)
@@ -248,7 +245,7 @@ class MachineManager(QObject):
self.updateNumberExtrudersEnabled()
self.globalContainerChanged.emit()
- # after switching the global stack we reconnect all the signals and set the variant and material references
+ # After switching the global stack we reconnect all the signals and set the variant and material references
if self._global_container_stack:
self._application.getPreferences().setValue("cura/active_machine", self._global_container_stack.getId())
@@ -258,44 +255,33 @@ class MachineManager(QObject):
# Global stack can have only a variant if it is a buildplate
global_variant = self._global_container_stack.variant
- if global_variant != self._empty_variant_container:
+ if global_variant != empty_variant_container:
if global_variant.getMetaDataEntry("hardware_type") != "buildplate":
- self._global_container_stack.setVariant(self._empty_variant_container)
+ self._global_container_stack.setVariant(empty_variant_container)
- # set the global material to empty as we now use the extruder stack at all times - CURA-4482
+ # Set the global material to empty as we now use the extruder stack at all times - CURA-4482
global_material = self._global_container_stack.material
- if global_material != self._empty_material_container:
- self._global_container_stack.setMaterial(self._empty_material_container)
+ if global_material != empty_material_container:
+ self._global_container_stack.setMaterial(empty_material_container)
# Listen for changes on all extruder stacks
for extruder_stack in ExtruderManager.getInstance().getActiveExtruderStacks():
extruder_stack.propertyChanged.connect(self._onPropertyChanged)
extruder_stack.containersChanged.connect(self._onContainersChanged)
- if self._global_container_stack.getId() in self.machine_extruder_material_update_dict:
- for func in self.machine_extruder_material_update_dict[self._global_container_stack.getId()]:
- self._application.callLater(func)
- del self.machine_extruder_material_update_dict[self._global_container_stack.getId()]
-
self.activeQualityGroupChanged.emit()
def _onActiveExtruderStackChanged(self) -> None:
self.blurSettings.emit() # Ensure no-one has focus.
- old_active_container_stack = self._active_container_stack
-
self._active_container_stack = ExtruderManager.getInstance().getActiveExtruderStack()
- if old_active_container_stack != self._active_container_stack:
- # Many methods and properties related to the active quality actually depend
- # on _active_container_stack. If it changes, then the properties change.
- self.activeQualityChanged.emit()
-
def __emitChangedSignals(self) -> None:
self.activeQualityChanged.emit()
self.activeVariantChanged.emit()
self.activeMaterialChanged.emit()
self.rootMaterialChanged.emit()
+ self.numberExtrudersEnabledChanged.emit()
def _onContainersChanged(self, container: ContainerInterface) -> None:
self._instance_container_timer.start()
@@ -367,18 +353,27 @@ class MachineManager(QObject):
return
global_stack = containers[0]
- ExtruderManager.getInstance()._fixSingleExtrusionMachineExtruderDefinition(global_stack)
+
+ # Make sure that the default machine actions for this machine have been added
+ self._application.getMachineActionManager().addDefaultMachineActions(global_stack)
+
+ ExtruderManager.getInstance().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
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)
+ ExtruderManager.getInstance().setActiveExtruderIndex(default_extruder_position)
+
self.__emitChangedSignals()
## Given a definition id, return the machine with this id.
@@ -392,12 +387,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())
@@ -416,7 +420,7 @@ class MachineManager(QObject):
# Not a very pretty solution, but the extruder manager doesn't really know how many extruders there are
machine_extruder_count = self._global_container_stack.getProperty("machine_extruder_count", "value")
extruder_stacks = ExtruderManager.getInstance().getActiveExtruderStacks()
- count = 1 # we start with the global stack
+ count = 1 # We start with the global stack
for stack in extruder_stacks:
md = stack.getMetaData()
if "position" in md and int(md["position"]) >= machine_extruder_count:
@@ -435,12 +439,12 @@ class MachineManager(QObject):
if not self._global_container_stack:
return False
- if self._global_container_stack.getTop().findInstances():
+ if self._global_container_stack.getTop().getNumInstances() != 0:
return True
stacks = ExtruderManager.getInstance().getActiveExtruderStacks()
for stack in stacks:
- if stack.getTop().findInstances():
+ if stack.getTop().getNumInstances() != 0:
return True
return False
@@ -450,16 +454,17 @@ class MachineManager(QObject):
if not self._global_container_stack:
return 0
num_user_settings = 0
- num_user_settings += len(self._global_container_stack.getTop().findInstances())
- stacks = ExtruderManager.getInstance().getActiveExtruderStacks()
+ num_user_settings += self._global_container_stack.getTop().getNumInstances()
+ stacks = self._global_container_stack.extruderList
for stack in stacks:
- num_user_settings += len(stack.getTop().findInstances())
+ num_user_settings += stack.getTop().getNumInstances()
return num_user_settings
## Delete a user setting from the global stack and all extruder stacks.
# \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
@@ -495,28 +500,79 @@ class MachineManager(QObject):
return bool(self._stacks_have_errors)
@pyqtProperty(str, notify = globalContainerChanged)
+ @deprecated("use Cura.MachineManager.activeMachine.definition.name instead", "4.1")
def activeMachineDefinitionName(self) -> str:
if self._global_container_stack:
return self._global_container_stack.definition.getName()
return ""
@pyqtProperty(str, notify = globalContainerChanged)
+ @deprecated("use Cura.MachineManager.activeMachine.name instead", "4.1")
def activeMachineName(self) -> str:
if self._global_container_stack:
- return self._global_container_stack.getName()
+ return self._global_container_stack.getMetaDataEntry("group_name", self._global_container_stack.getName())
return ""
@pyqtProperty(str, notify = globalContainerChanged)
+ @deprecated("use Cura.MachineManager.activeMachine.id instead", "4.1")
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:
+ return ""
+ return self._printer_output_devices[0].firmwareVersion
+
+ @pyqtProperty(str, notify = globalContainerChanged)
+ def activeMachineAddress(self) -> str:
+ if not self._printer_output_devices:
+ return ""
+ return self._printer_output_devices[0].address
+
@pyqtProperty(bool, notify = printerConnectedStatusChanged)
- def printerConnected(self):
+ def printerConnected(self) -> bool:
return bool(self._printer_output_devices)
- @pyqtProperty(str, notify = printerConnectedStatusChanged)
+ @pyqtProperty(bool, notify = printerConnectedStatusChanged)
+ @deprecated("use Cura.MachineManager.activeMachine.configuredConnectionTypes instead", "4.2")
+ 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)
+ @deprecated("use Cura.MachineManager.activeMachine.configuredConnectionTypes instead", "4.1")
+ 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
+
+ @pyqtProperty(bool, notify = printerConnectedStatusChanged)
+ def activeMachineHasNetworkConnection(self) -> bool:
+ # A network connection is only available if any output device is actually a network connected device.
+ return any(d.connectionType == ConnectionType.NetworkConnection for d in self._printer_output_devices)
+
+ @pyqtProperty(bool, notify = printerConnectedStatusChanged)
+ def activeMachineHasCloudConnection(self) -> bool:
+ # A cloud connection is only available if any output device actually is a cloud connected device.
+ return any(d.connectionType == ConnectionType.CloudConnection for d in self._printer_output_devices)
+
+ @pyqtProperty(bool, notify = printerConnectedStatusChanged)
+ def activeMachineIsUsingCloudConnection(self) -> bool:
+ return self.activeMachineHasCloudConnection and not self.activeMachineHasNetworkConnection
+
def activeMachineNetworkKey(self) -> str:
if self._global_container_stack:
return self._global_container_stack.getMetaDataEntry("um_network_key", "")
@@ -525,7 +581,7 @@ class MachineManager(QObject):
@pyqtProperty(str, notify = printerConnectedStatusChanged)
def activeMachineNetworkGroupName(self) -> str:
if self._global_container_stack:
- return self._global_container_stack.getMetaDataEntry("connect_group_name", "")
+ return self._global_container_stack.getMetaDataEntry("group_name", "")
return ""
@pyqtProperty(QObject, notify = globalContainerChanged)
@@ -542,7 +598,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
@@ -593,7 +649,7 @@ class MachineManager(QObject):
def globalVariantName(self) -> str:
if self._global_container_stack:
variant = self._global_container_stack.variant
- if variant and not isinstance(variant, type(self._empty_variant_container)):
+ if variant and not isinstance(variant, type(empty_variant_container)):
return variant.getName()
return ""
@@ -613,6 +669,14 @@ class MachineManager(QObject):
is_supported = self._current_quality_group.is_available
return is_supported
+ @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
+
## Returns whether there is anything unsupported in the current set-up.
#
# The current set-up signifies the global stack and all extruder stacks,
@@ -630,11 +694,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:
@@ -643,7 +702,7 @@ class MachineManager(QObject):
new_value = self._active_container_stack.getProperty(key, "value")
extruder_stacks = [stack for stack in ExtruderManager.getInstance().getActiveExtruderStacks()]
- # check in which stack the value has to be replaced
+ # Check in which stack the value has to be replaced
for extruder_stack in extruder_stacks:
if extruder_stack != self._active_container_stack and extruder_stack.getProperty(key, "value") != new_value:
extruder_stack.userChanges.setProperty(key, "value", new_value) # TODO: nested property access, should be improved
@@ -659,10 +718,11 @@ class MachineManager(QObject):
for key in self._active_container_stack.userChanges.getAllKeys():
new_value = self._active_container_stack.getProperty(key, "value")
- # check if the value has to be replaced
+ # Check if the value has to be replaced
extruder_stack.userChanges.setProperty(key, "value", new_value)
@pyqtProperty(str, notify = activeVariantChanged)
+ @deprecated("use Cura.MachineManager.activeStack.variant.name instead", "4.1")
def activeVariantName(self) -> str:
if self._active_container_stack:
variant = self._active_container_stack.variant
@@ -672,6 +732,7 @@ class MachineManager(QObject):
return ""
@pyqtProperty(str, notify = activeVariantChanged)
+ @deprecated("use Cura.MachineManager.activeStack.variant.id instead", "4.1")
def activeVariantId(self) -> str:
if self._active_container_stack:
variant = self._active_container_stack.variant
@@ -681,6 +742,7 @@ class MachineManager(QObject):
return ""
@pyqtProperty(str, notify = activeVariantChanged)
+ @deprecated("use Cura.MachineManager.activeMachine.variant.name instead", "4.1")
def activeVariantBuildplateName(self) -> str:
if self._global_container_stack:
variant = self._global_container_stack.variant
@@ -690,6 +752,7 @@ class MachineManager(QObject):
return ""
@pyqtProperty(str, notify = globalContainerChanged)
+ @deprecated("use Cura.MachineManager.activeMachine.definition.id instead", "4.1")
def activeDefinitionId(self) -> str:
if self._global_container_stack:
return self._global_container_stack.definition.id
@@ -725,10 +788,11 @@ 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)
- # activate a new machine before removing a machine because this is safer
+ # Activate a new machine before removing a machine because this is safer
if activate_new_machine:
machine_stacks = CuraContainerRegistry.getInstance().findContainerStacksMetadata(type = "machine")
other_machine_stacks = [s for s in machine_stacks if s["id"] != machine_id]
@@ -736,7 +800,6 @@ class MachineManager(QObject):
self.setActiveMachine(other_machine_stacks[0]["id"])
metadata = CuraContainerRegistry.getInstance().findContainerStacksMetadata(id = machine_id)[0]
- network_key = metadata["um_network_key"] if "um_network_key" in metadata else None
ExtruderManager.getInstance().removeMachineExtruders(machine_id)
containers = CuraContainerRegistry.getInstance().findInstanceContainersMetadata(type = "user", machine = machine_id)
for container in containers:
@@ -744,29 +807,33 @@ 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)
+ @deprecated("use Cura.MachineManager.activeMachine.hasMaterials instead", "4.2")
def hasMaterials(self) -> bool:
if self._global_container_stack:
- return Util.parseBool(self._global_container_stack.getMetaDataEntry("has_materials", False))
+ return self._global_container_stack.hasMaterials
return False
@pyqtProperty(bool, notify = globalContainerChanged)
+ @deprecated("use Cura.MachineManager.activeMachine.hasVariants instead", "4.2")
def hasVariants(self) -> bool:
if self._global_container_stack:
- return Util.parseBool(self._global_container_stack.getMetaDataEntry("has_variants", False))
+ return self._global_container_stack.hasVariants
return False
@pyqtProperty(bool, notify = globalContainerChanged)
+ @deprecated("use Cura.MachineManager.activeMachine.hasVariantBuildplates instead", "4.2")
def hasVariantBuildplates(self) -> bool:
if self._global_container_stack:
- return Util.parseBool(self._global_container_stack.getMetaDataEntry("has_variant_buildplates", False))
+ return self._global_container_stack.hasVariantBuildplates
return False
## The selected buildplate is compatible if it is compatible with all the materials in all the extruders
@@ -781,7 +848,7 @@ class MachineManager(QObject):
if not stack.isEnabled:
continue
material_container = stack.material
- if material_container == self._empty_material_container:
+ 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]
@@ -803,7 +870,7 @@ class MachineManager(QObject):
extruder_stacks = self._global_container_stack.extruders.values()
for stack in extruder_stacks:
material_container = stack.material
- if material_container == self._empty_material_container:
+ if material_container == empty_material_container:
continue
buildplate_compatible = material_container.getMetaDataEntry("buildplate_compatible")[self.activeVariantBuildplateName] if material_container.getMetaDataEntry("buildplate_compatible") else True
buildplate_usable = material_container.getMetaDataEntry("buildplate_recommended")[self.activeVariantBuildplateName] if material_container.getMetaDataEntry("buildplate_recommended") else True
@@ -829,17 +896,12 @@ 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:
@@ -858,10 +920,9 @@ 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)),
- lifetime=0,
+ 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()
@@ -873,7 +934,7 @@ class MachineManager(QObject):
extruder_manager = self._application.getExtruderManager()
definition_changes_container = self._global_container_stack.definitionChanges
- if not self._global_container_stack or definition_changes_container == self._empty_definition_changes_container:
+ if not self._global_container_stack or definition_changes_container == empty_definition_changes_container:
return
previous_extruder_count = self._global_container_stack.getProperty("machine_extruder_count", "value")
@@ -888,7 +949,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")
@@ -906,21 +967,18 @@ class MachineManager(QObject):
# After CURA-4482 this should not be the case anymore, but we still want to support older project files.
global_user_container = self._global_container_stack.userChanges
- # Make sure extruder_stacks exists
- extruder_stacks = [] #type: List[ExtruderStack]
-
- if previous_extruder_count == 1:
- extruder_stacks = ExtruderManager.getInstance().getActiveExtruderStacks()
- global_user_container = self._global_container_stack.userChanges
-
for setting_instance in global_user_container.findInstances():
setting_key = setting_instance.definition.key
settable_per_extruder = self._global_container_stack.getProperty(setting_key, "settable_per_extruder")
if settable_per_extruder:
limit_to_extruder = int(self._global_container_stack.getProperty(setting_key, "limit_to_extruder"))
- extruder_stack = extruder_stacks[max(0, limit_to_extruder)]
- extruder_stack.userChanges.setProperty(setting_key, "value", global_user_container.getProperty(setting_key, "value"))
+ extruder_position = max(0, limit_to_extruder)
+ extruder_stack = self.getExtruder(extruder_position)
+ if extruder_stack:
+ extruder_stack.userChanges.setProperty(setting_key, "value", global_user_container.getProperty(setting_key, "value"))
+ else:
+ Logger.log("e", "Unable to find extruder on position %s", extruder_position)
global_user_container.removeInstance(setting_key)
# Signal that the global stack has changed
@@ -929,10 +987,14 @@ class MachineManager(QObject):
@pyqtSlot(int, result = QObject)
def getExtruder(self, position: int) -> Optional[ExtruderStack]:
- extruder = None
+ return self._getExtruder(position)
+
+ # This is a workaround for the deprecated decorator and the pyqtSlot not playing well together.
+ @deprecated("use Cura.MachineManager.activeMachine.extruders instead", "4.2")
+ def _getExtruder(self, position) -> Optional[ExtruderStack]:
if self._global_container_stack:
- extruder = self._global_container_stack.extruders.get(str(position))
- return extruder
+ return self._global_container_stack.extruders.get(str(position))
+ return None
def updateDefaultExtruder(self) -> None:
if self._global_container_stack is None:
@@ -998,12 +1060,12 @@ class MachineManager(QObject):
if not enabled and position == ExtruderManager.getInstance().activeExtruderIndex:
ExtruderManager.getInstance().setActiveExtruderIndex(int(self._default_extruder_position))
- # ensure that the quality profile is compatible with current combination, or choose a compatible one if available
+ # Ensure that the quality profile is compatible with current combination, or choose a compatible one if available
self._updateQualityWithMaterial()
self.extruderChanged.emit()
- # update material compatibility color
+ # Update material compatibility color
self.activeQualityGroupChanged.emit()
- # update items in SettingExtruder
+ # Update items in SettingExtruder
ExtruderManager.getInstance().extrudersChanged.emit(self._global_container_stack.getId())
# Make sure the front end reflects changes
self.forceUpdateAllSettings()
@@ -1016,9 +1078,6 @@ class MachineManager(QObject):
def _onMaterialNameChanged(self) -> None:
self.activeMaterialChanged.emit()
- def _onQualityNameChanged(self) -> None:
- self.activeQualityChanged.emit()
-
def _getContainerChangedSignals(self) -> List[Signal]:
if self._global_container_stack is None:
return []
@@ -1045,6 +1104,7 @@ class MachineManager(QObject):
container.removeInstance(setting_name)
@pyqtProperty("QVariantList", notify = globalContainerChanged)
+ @deprecated("use Cura.MachineManager.activeMachine.extruders instead", "4.2")
def currentExtruderPositions(self) -> List[str]:
if self._global_container_stack is None:
return []
@@ -1054,9 +1114,17 @@ class MachineManager(QObject):
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")
+ material_id = self._global_container_stack.extruders[position].material.getMetaDataEntry("base_file")
+ 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]:
@@ -1072,12 +1140,11 @@ class MachineManager(QObject):
for stack in active_stacks:
variant_container = stack.variant
position = stack.getMetaDataEntry("position")
- if variant_container and variant_container != self._empty_variant_container:
+ 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.
#
@@ -1086,11 +1153,11 @@ class MachineManager(QObject):
return
self._current_quality_group = None
self._current_quality_changes_group = None
- self._global_container_stack.quality = self._empty_quality_container
- self._global_container_stack.qualityChanges = self._empty_quality_changes_container
+ 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():
- extruder.quality = self._empty_quality_container
- extruder.qualityChanges = self._empty_quality_changes_container
+ extruder.quality = empty_quality_container
+ extruder.qualityChanges = empty_quality_changes_container
self.activeQualityGroupChanged.emit()
self.activeQualityChangesGroupChanged.emit()
@@ -1115,13 +1182,13 @@ class MachineManager(QObject):
# Set quality and quality_changes for the GlobalStack
self._global_container_stack.quality = quality_group.node_for_global.getContainer()
if empty_quality_changes:
- self._global_container_stack.qualityChanges = self._empty_quality_changes_container
+ 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()
if empty_quality_changes:
- self._global_container_stack.extruders[str(position)].qualityChanges = self._empty_quality_changes_container
+ self._global_container_stack.extruders[str(position)].qualityChanges = empty_quality_changes_container
self.activeQualityGroupChanged.emit()
self.activeQualityChangesGroupChanged.emit()
@@ -1136,7 +1203,7 @@ class MachineManager(QObject):
def _setQualityChangesGroup(self, quality_changes_group: "QualityChangesGroup") -> None:
if self._global_container_stack is None:
- return #Can't change that.
+ return # Can't change that.
quality_type = quality_changes_group.quality_type
# A custom quality can be created based on "not supported".
# In that case, do not set quality containers to empty.
@@ -1147,8 +1214,8 @@ class MachineManager(QObject):
if quality_group is None:
self._fixQualityChangesGroupToNotSupported(quality_changes_group)
- quality_changes_container = self._empty_quality_changes_container
- quality_container = self._empty_quality_container # type: Optional[InstanceContainer]
+ 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():
@@ -1163,8 +1230,8 @@ class MachineManager(QObject):
if quality_group is not None:
quality_node = quality_group.nodes_for_extruders.get(position)
- quality_changes_container = self._empty_quality_changes_container
- quality_container = self._empty_quality_container
+ 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():
@@ -1198,7 +1265,7 @@ class MachineManager(QObject):
self._global_container_stack.extruders[position].material = container_node.getContainer()
root_material_id = container_node.getMetaDataEntry("base_file", None)
else:
- self._global_container_stack.extruders[position].material = self._empty_material_container
+ self._global_container_stack.extruders[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]:
@@ -1206,12 +1273,12 @@ class MachineManager(QObject):
self.rootMaterialChanged.emit()
def activeMaterialsCompatible(self) -> bool:
- # check material - variant compatibility
+ # 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
+ if not extruder.isEnabled:
+ continue
if not extruder.material.getMetaDataEntry("compatible"):
return False
return True
@@ -1220,7 +1287,7 @@ class MachineManager(QObject):
def _updateQualityWithMaterial(self, *args: Any) -> None:
if self._global_container_stack is None:
return
- Logger.log("i", "Updating quality/quality_changes due to material change")
+ Logger.log("d", "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
@@ -1273,14 +1340,10 @@ class MachineManager(QObject):
current_material_base_name = extruder.material.getMetaDataEntry("base_file")
current_nozzle_name = None
- if extruder.variant.getId() != self._empty_variant_container.getId():
+ if extruder.variant.getId() != empty_variant_container.getId():
current_nozzle_name = extruder.variant.getMetaDataEntry("name")
- from UM.Settings.Interfaces import PropertyEvaluationContext
- from cura.Settings.CuraContainerStack import _ContainerIndexes
- context = PropertyEvaluationContext(extruder)
- context.context["evaluate_from_container_index"] = _ContainerIndexes.DefinitionChanges
- material_diameter = extruder.getProperty("material_diameter", "value", context)
+ material_diameter = extruder.getCompatibleMaterialDiameter()
candidate_materials = self._material_manager.getAvailableMaterials(
self._global_container_stack.definition,
current_nozzle_name,
@@ -1305,96 +1368,125 @@ class MachineManager(QObject):
# instance with the same network key.
@pyqtSlot(str)
def switchPrinterType(self, machine_name: str) -> None:
+ Logger.log("i", "Attempting to switch the printer type to [%s]", machine_name)
# 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:
return
# 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"),
+ "um_network_key": self.activeMachineNetworkKey(),
+ }
+ 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("connect_group_name", self.activeMachineNetworkGroupName)
- new_machine.setMetaDataEntry("hidden", False)
+ new_machine.setMetaDataEntry("group_id", self._global_container_stack.getMetaDataEntry("group_id"))
+ new_machine.setMetaDataEntry("um_network_key", self.activeMachineNetworkKey())
+ new_machine.setMetaDataEntry("group_name", self.activeMachineNetworkGroupName)
+ new_machine.setMetaDataEntry("connection_type", self._global_container_stack.getMetaDataEntry("connection_type"))
else:
- Logger.log("i", "Found a %s with the key %s. Let's use it!", machine_name, self.activeMachineNetworkKey)
- new_machine.setMetaDataEntry("hidden", False)
+ Logger.log("i", "Found a %s with the key %s. Let's use it!", machine_name, self.activeMachineNetworkKey())
# 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()
with postponeSignals(*self._getContainerChangedSignals(), compress = CompressTechnique.CompressPerParameterValue):
self.switchPrinterType(configuration.printerType)
+
+ disabled_used_extruder_position_set = set()
+ extruders_to_disable = set()
+
+ # If an extruder that's currently used to print a model gets disabled due to the syncing, we need to show
+ # a message explaining why.
+ need_to_show_message = False
+
+ for extruder_configuration in configuration.extruderConfigurations:
+ # 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):
+ extruders_to_disable.remove(min(extruders_to_disable))
+
for extruder_configuration in configuration.extruderConfigurations:
position = str(extruder_configuration.position)
- 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 = self._empty_variant_container
+ # 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)
+
+ need_to_show_message = True
+ disabled_used_extruder_position_set.add(int(position))
- if material_container_node:
- self._setMaterial(position, material_container_node)
else:
- self._global_container_stack.extruders[position].material = self._empty_material_container
- self.updateMaterialWithVariant(position)
+ 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
+
+ if material_container_node:
+ self._setMaterial(position, material_container_node)
+ else:
+ self._global_container_stack.extruders[position].material = empty_material_container
+ 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 = self._empty_variant_container
+ self._global_container_stack.variant = empty_variant_container
else:
- self._global_container_stack.variant = self._empty_variant_container
+ self._global_container_stack.variant = empty_variant_container
self._updateQualityWithMaterial()
+ if need_to_show_message:
+ msg_str = "{extruders} is disabled because there is no material loaded. Please load a material or use custom configurations."
+
+ # 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_name = extruder_stack.definition.getName()
+ extruder_names.append(extruder_name)
+ extruders_str = ", ".join(extruder_names)
+ msg_str = msg_str.format(extruders = extruders_str)
+ message = Message(catalog.i18nc("@info:status", msg_str),
+ title = catalog.i18nc("@info:title", "Extruder(s) Disabled"))
+ message.show()
+
# See if we need to show the Discard or Keep changes screen
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 connect_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("connect_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()
@@ -1415,12 +1507,12 @@ class MachineManager(QObject):
position = str(position)
extruder_stack = self._global_container_stack.extruders[position]
nozzle_name = extruder_stack.variant.getName()
- material_diameter = extruder_stack.approximateMaterialDiameter
+ material_diameter = extruder_stack.getApproximateMaterialDiameter()
material_node = self._material_manager.getMaterialNode(machine_definition_id, nozzle_name, buildplate_name,
material_diameter, 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
+ ## Global_stack: if you want to provide your own global_stack instead of the current active one
# if you update an active machine, special measures have to be taken.
@pyqtSlot(str, "QVariant")
def setMaterial(self, position: str, container_node, global_stack: Optional["GlobalStack"] = None) -> None:
@@ -1481,7 +1573,7 @@ class MachineManager(QObject):
# 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():
- quality_container = self._empty_quality_container
+ quality_container = empty_quality_container
if extruder_nr in quality_group.nodes_for_extruders:
container = quality_group.nodes_for_extruders[extruder_nr].getContainer()
quality_container = container if container is not None else quality_container
@@ -1523,18 +1615,49 @@ class MachineManager(QObject):
def activeQualityChangesGroup(self) -> Optional["QualityChangesGroup"]:
return self._current_quality_changes_group
+ @pyqtProperty(bool, notify = activeQualityChangesGroupChanged)
+ def hasCustomQuality(self) -> bool:
+ return self._current_quality_changes_group is not None
+
@pyqtProperty(str, notify = activeQualityGroupChanged)
def activeQualityOrQualityChangesName(self) -> str:
- name = self._empty_quality_container.getName()
+ 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
+ @pyqtProperty(bool, notify = activeQualityGroupChanged)
+ def hasNotSupportedQuality(self) -> bool:
+ return self._current_quality_group is None and self._current_quality_changes_group is None
+
def _updateUponMaterialMetadataChange(self) -> None:
if self._global_container_stack is None:
return
with postponeSignals(*self._getContainerChangedSignals(), compress = CompressTechnique.CompressPerParameterValue):
self.updateMaterialWithVariant(None)
self._updateQualityWithMaterial()
+
+ ## This function will translate any printer type name to an abbreviated printer type name
+ @pyqtSlot(str, result = str)
+ def getAbbreviatedMachineName(self, machine_type_name: str) -> str:
+ abbr_machine = ""
+ for word in re.findall(r"[\w']+", machine_type_name):
+ if word.lower() == "ultimaker":
+ abbr_machine += "UM"
+ elif word.isdigit():
+ abbr_machine += word
+ else:
+ stripped_word = "".join(char for char in unicodedata.normalize("NFD", word.upper()) if unicodedata.category(char) != "Mn")
+ # - use only the first character if the word is too long (> 3 characters)
+ # - use the whole word if it's not too long (<= 3 characters)
+ if len(stripped_word) > 3:
+ stripped_word = stripped_word[0]
+ abbr_machine += stripped_word
+
+ return abbr_machine
+
+ # Gets all machines that belong to the given group_id.
+ def getMachinesInGroup(self, group_id: str) -> List["GlobalStack"]:
+ return self._container_registry.findContainerStacks(type = "machine", group_id = group_id)
diff --git a/cura/Settings/PerObjectContainerStack.py b/cura/Settings/PerObjectContainerStack.py
index 3589029517..7ed9eb6fb7 100644
--- a/cura/Settings/PerObjectContainerStack.py
+++ b/cura/Settings/PerObjectContainerStack.py
@@ -34,7 +34,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 +42,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 9cd24558b7..12b541c3d8 100644
--- a/cura/Settings/SettingInheritanceManager.py
+++ b/cura/Settings/SettingInheritanceManager.py
@@ -1,6 +1,6 @@
# Copyright (c) 2017 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
-from typing import List
+from typing import List, Optional, TYPE_CHECKING
from PyQt5.QtCore import QObject, QTimer, pyqtProperty, pyqtSignal
from UM.FlameProfiler import pyqtSlot
@@ -20,13 +20,18 @@ from UM.Settings.SettingInstance import InstanceState
from cura.Settings.ExtruderManager import ExtruderManager
+if TYPE_CHECKING:
+ from cura.Settings.ExtruderStack import ExtruderStack
+ from UM.Settings.SettingDefinition import SettingDefinition
+
+
class SettingInheritanceManager(QObject):
- def __init__(self, parent = None):
+ def __init__(self, parent = None) -> None:
super().__init__(parent)
Application.getInstance().globalContainerStackChanged.connect(self._onGlobalContainerChanged)
- self._global_container_stack = None
- self._settings_with_inheritance_warning = []
- self._active_container_stack = None
+ 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)
@@ -41,7 +46,9 @@ class SettingInheritanceManager(QObject):
## Get the keys of all children settings with an override.
@pyqtSlot(str, result = "QStringList")
- def getChildrenKeysWithOverride(self, key):
+ def getChildrenKeysWithOverride(self, key: str) -> List[str]:
+ if self._global_container_stack is None:
+ return []
definitions = self._global_container_stack.definition.findDefinitions(key=key)
if not definitions:
Logger.log("w", "Could not find definition for key [%s]", key)
@@ -53,9 +60,11 @@ class SettingInheritanceManager(QObject):
return result
@pyqtSlot(str, str, result = "QStringList")
- def getOverridesForExtruder(self, key, extruder_index):
- result = []
+ def getOverridesForExtruder(self, key: str, extruder_index: str) -> List[str]:
+ if self._global_container_stack is None:
+ return []
+ result = [] # type: List[str]
extruder_stack = ExtruderManager.getInstance().getExtruderStack(extruder_index)
if not extruder_stack:
Logger.log("w", "Unable to find extruder for current machine with index %s", extruder_index)
@@ -73,16 +82,16 @@ class SettingInheritanceManager(QObject):
return result
@pyqtSlot(str)
- def manualRemoveOverride(self, key):
+ def manualRemoveOverride(self, key: str) -> None:
if key in self._settings_with_inheritance_warning:
self._settings_with_inheritance_warning.remove(key)
self.settingsWithIntheritanceChanged.emit()
@pyqtSlot()
- def forceUpdate(self):
+ def forceUpdate(self) -> None:
self._update()
- def _onActiveExtruderChanged(self):
+ def _onActiveExtruderChanged(self) -> None:
new_active_stack = ExtruderManager.getInstance().getActiveExtruderStack()
if not new_active_stack:
self._active_container_stack = None
@@ -94,13 +103,14 @@ class SettingInheritanceManager(QObject):
self._active_container_stack.containersChanged.disconnect(self._onContainersChanged)
self._active_container_stack = new_active_stack
- self._active_container_stack.propertyChanged.connect(self._onPropertyChanged)
- self._active_container_stack.containersChanged.connect(self._onContainersChanged)
+ 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.
- def _onPropertyChanged(self, key, property_name):
+ def _onPropertyChanged(self, key: str, property_name: str) -> None:
if (property_name == "value" or property_name == "enabled") and self._global_container_stack:
- definitions = self._global_container_stack.definition.findDefinitions(key = key)
+ definitions = self._global_container_stack.definition.findDefinitions(key = key) # type: List["SettingDefinition"]
if not definitions:
return
@@ -139,7 +149,7 @@ class SettingInheritanceManager(QObject):
if settings_with_inheritance_warning_changed:
self.settingsWithIntheritanceChanged.emit()
- def _recursiveCheck(self, definition):
+ def _recursiveCheck(self, definition: "SettingDefinition") -> bool:
for child in definition.children:
if child.key in self._settings_with_inheritance_warning:
return True
@@ -149,7 +159,7 @@ class SettingInheritanceManager(QObject):
return False
@pyqtProperty("QVariantList", notify = settingsWithIntheritanceChanged)
- def settingsWithInheritanceWarning(self):
+ def settingsWithInheritanceWarning(self) -> List[str]:
return self._settings_with_inheritance_warning
## Check if a setting has an inheritance function that is overwritten
@@ -157,9 +167,14 @@ class SettingInheritanceManager(QObject):
has_setting_function = False
if not stack:
stack = self._active_container_stack
- if not stack: #No active container stack yet!
+ if not stack: # No active container stack yet!
return False
- containers = [] # type: List[ContainerInterface]
+
+ if self._active_container_stack is None:
+ return False
+ all_keys = self._active_container_stack.getAllKeys()
+
+ containers = [] # type: List[ContainerInterface]
## Check if the setting has a user state. If not, it is never overwritten.
has_user_state = stack.getProperty(key, "state") == InstanceState.User
@@ -190,8 +205,8 @@ class SettingInheritanceManager(QObject):
has_setting_function = isinstance(value, SettingFunction)
if has_setting_function:
for setting_key in value.getUsedSettingKeys():
- if setting_key in self._active_container_stack.getAllKeys():
- break # We found an actual setting. So has_setting_function can remain true
+ if setting_key in all_keys:
+ break # We found an actual setting. So has_setting_function can remain true
else:
# All of the setting_keys turned out to not be setting keys at all!
# This can happen due enum keys also being marked as settings.
@@ -205,7 +220,7 @@ class SettingInheritanceManager(QObject):
break # There is a setting function somewhere, stop looking deeper.
return has_setting_function and has_non_function_value
- def _update(self):
+ def _update(self) -> None:
self._settings_with_inheritance_warning = [] # Reset previous data.
# Make sure that the GlobalStack is not None. sometimes the globalContainerChanged signal gets here late.
@@ -226,7 +241,7 @@ class SettingInheritanceManager(QObject):
# Notify others that things have changed.
self.settingsWithIntheritanceChanged.emit()
- def _onGlobalContainerChanged(self):
+ def _onGlobalContainerChanged(self) -> None:
if self._global_container_stack:
self._global_container_stack.propertyChanged.disconnect(self._onPropertyChanged)
self._global_container_stack.containersChanged.disconnect(self._onContainersChanged)
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/SettingVisibilityPreset.py b/cura/Settings/SettingVisibilityPreset.py
new file mode 100644
index 0000000000..e8a4211d69
--- /dev/null
+++ b/cura/Settings/SettingVisibilityPreset.py
@@ -0,0 +1,90 @@
+import os
+import urllib.parse
+from configparser import ConfigParser
+from typing import List
+
+from PyQt5.QtCore import pyqtProperty, QObject, pyqtSignal
+
+from UM.Logger import Logger
+from UM.MimeTypeDatabase import MimeTypeDatabase
+
+
+class SettingVisibilityPreset(QObject):
+ onSettingsChanged = pyqtSignal()
+ onNameChanged = pyqtSignal()
+ onWeightChanged = pyqtSignal()
+ onIdChanged = pyqtSignal()
+
+ def __init__(self, preset_id: str = "", name: str = "", weight: int = 0, parent = None) -> None:
+ super().__init__(parent)
+ self._settings = [] # type: List[str]
+ self._id = preset_id
+ self._weight = weight
+ self._name = name
+
+ @pyqtProperty("QStringList", notify = onSettingsChanged)
+ def settings(self) -> List[str]:
+ return self._settings
+
+ @pyqtProperty(str, notify = onIdChanged)
+ def presetId(self) -> str:
+ return self._id
+
+ @pyqtProperty(int, notify = onWeightChanged)
+ def weight(self) -> int:
+ return self._weight
+
+ @pyqtProperty(str, notify = onNameChanged)
+ def name(self) -> str:
+ return self._name
+
+ def setName(self, name: str) -> None:
+ if name != self._name:
+ self._name = name
+ self.onNameChanged.emit()
+
+ def setId(self, id: str) -> None:
+ if id != self._id:
+ self._id = id
+ self.onIdChanged.emit()
+
+ def setWeight(self, weight: int) -> None:
+ if weight != self._weight:
+ self._weight = weight
+ self.onWeightChanged.emit()
+
+ def setSettings(self, settings: List[str]) -> None:
+ if set(settings) != set(self._settings):
+ self._settings = list(set(settings)) # filter out non unique
+ self.onSettingsChanged.emit()
+
+ # Load a preset from file. We expect a file that can be parsed by means of the config parser.
+ # The sections indicate the categories and the parameters placed in it (which don't need values) are the settings
+ # that should be considered visible.
+ def loadFromFile(self, file_path: str) -> None:
+ mime_type = MimeTypeDatabase.getMimeTypeForFile(file_path)
+
+ item_id = urllib.parse.unquote_plus(mime_type.stripExtension(os.path.basename(file_path)))
+ if not os.path.isfile(file_path):
+ Logger.log("e", "[%s] is not a file", file_path)
+ return None
+
+ parser = ConfigParser(interpolation = None, allow_no_value = True) # Accept options without any value,
+
+ parser.read([file_path])
+ if not parser.has_option("general", "name") or not parser.has_option("general", "weight"):
+ return None
+
+ settings = [] # type: List[str]
+ for section in parser.sections():
+ if section == "general":
+ continue
+
+ settings.append(section)
+ for option in parser[section].keys():
+ settings.append(option)
+ self.setSettings(settings)
+ self.setId(item_id)
+ self.setName(parser["general"]["name"])
+ self.setWeight(int(parser["general"]["weight"]))
+
diff --git a/cura/Settings/SimpleModeSettingsManager.py b/cura/Settings/SimpleModeSettingsManager.py
index fce43243bd..b1896a9205 100644
--- a/cura/Settings/SimpleModeSettingsManager.py
+++ b/cura/Settings/SimpleModeSettingsManager.py
@@ -1,7 +1,8 @@
# Copyright (c) 2017 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
+from typing import Set
-from PyQt5.QtCore import QObject, pyqtSignal, pyqtProperty
+from PyQt5.QtCore import QObject, pyqtSignal, pyqtProperty, pyqtSlot
from UM.Application import Application
@@ -16,15 +17,11 @@ class SimpleModeSettingsManager(QObject):
self._is_profile_user_created = False # True when profile was custom created by user
self._machine_manager.activeStackValueChanged.connect(self._updateIsProfileCustomized)
- self._machine_manager.activeQualityGroupChanged.connect(self._updateIsProfileUserCreated)
- self._machine_manager.activeQualityChangesGroupChanged.connect(self._updateIsProfileUserCreated)
# update on create as the activeQualityChanged signal is emitted before this manager is created when Cura starts
self._updateIsProfileCustomized()
- self._updateIsProfileUserCreated()
isProfileCustomizedChanged = pyqtSignal()
- isProfileUserCreatedChanged = pyqtSignal()
@pyqtProperty(bool, notify = isProfileCustomizedChanged)
def isProfileCustomized(self):
@@ -57,33 +54,6 @@ class SimpleModeSettingsManager(QObject):
self._is_profile_customized = has_customized_user_settings
self.isProfileCustomizedChanged.emit()
- @pyqtProperty(bool, notify = isProfileUserCreatedChanged)
- def isProfileUserCreated(self):
- return self._is_profile_user_created
-
- def _updateIsProfileUserCreated(self):
- quality_changes_keys = set()
-
- if not self._machine_manager.activeMachine:
- return False
-
- global_stack = self._machine_manager.activeMachine
-
- # check quality changes settings in the global stack
- quality_changes_keys.update(global_stack.qualityChanges.getAllKeys())
-
- # check quality changes settings in the extruder stacks
- if global_stack.extruders:
- for extruder_stack in global_stack.extruders.values():
- quality_changes_keys.update(extruder_stack.qualityChanges.getAllKeys())
-
- # check if the qualityChanges container is not empty (meaning it is a user created profile)
- has_quality_changes = len(quality_changes_keys) > 0
-
- if has_quality_changes != self._is_profile_user_created:
- self._is_profile_user_created = has_quality_changes
- self.isProfileUserCreatedChanged.emit()
-
# These are the settings included in the Simple ("Recommended") Mode, so only when the other settings have been
# changed, we consider it as a user customized profile in the Simple ("Recommended") Mode.
__ignored_custom_setting_keys = ["support_enable",
diff --git a/cura/Settings/cura_empty_instance_containers.py b/cura/Settings/cura_empty_instance_containers.py
index d76407ed79..0eedfc8654 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
@@ -28,7 +30,7 @@ empty_material_container.setMetaDataEntry("type", "material")
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)
@@ -41,6 +43,22 @@ empty_quality_changes_container.setMetaDataEntry("type", "quality_changes")
empty_quality_changes_container.setMetaDataEntry("quality_type", "not_supported")
+# 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,
+}
+
+
+# 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",
"empty_container", # For convenience
"EMPTY_DEFINITION_CHANGES_CONTAINER_ID",
@@ -52,5 +70,7 @@ __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",
]
diff --git a/cura/Snapshot.py b/cura/Snapshot.py
index b730c1fdcf..033b453684 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)
diff --git a/cura/Stages/CuraStage.py b/cura/Stages/CuraStage.py
index b2f6d61799..6c4d46dd72 100644
--- a/cura/Stages/CuraStage.py
+++ b/cura/Stages/CuraStage.py
@@ -1,23 +1,32 @@
-# Copyright (c) 2017 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
-
-
-class CuraStage(Stage):
-
- def __init__(self, parent = None):
- super().__init__(parent)
-
- @pyqtProperty(str, constant = True)
- def stageId(self):
- return self.getPluginId()
-
- @pyqtProperty(QUrl, constant = True)
- def mainComponent(self):
- return self.getDisplayComponent("main")
-
- @pyqtProperty(QUrl, constant = True)
- def sidebarComponent(self):
- return self.getDisplayComponent("sidebar")
+# 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 100%
rename from cura/CuraSplashScreen.py
rename to cura/UI/CuraSplashScreen.py
diff --git a/cura/MachineActionManager.py b/cura/UI/MachineActionManager.py
similarity index 58%
rename from cura/MachineActionManager.py
rename to cura/UI/MachineActionManager.py
index 65eb33b54c..aa90e909e2 100644
--- a/cura/MachineActionManager.py
+++ b/cura/UI/MachineActionManager.py
@@ -1,12 +1,18 @@
# Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
+from typing import TYPE_CHECKING, Optional, List, Set, Dict
+
from PyQt5.QtCore import QObject
from UM.FlameProfiler import pyqtSlot
from UM.Logger import Logger
from UM.PluginRegistry import PluginRegistry # So MachineAction can be added as plugin type
-from UM.Settings.DefinitionContainer import DefinitionContainer
+
+if TYPE_CHECKING:
+ from cura.CuraApplication import CuraApplication
+ from cura.Settings.GlobalStack import GlobalStack
+ from cura.MachineAction import MachineAction
## Raised when trying to add an unknown machine action as a required action
@@ -20,46 +26,54 @@ class NotUniqueMachineActionError(Exception):
class MachineActionManager(QObject):
- def __init__(self, application, parent = None):
- super().__init__(parent)
+ def __init__(self, application: "CuraApplication", parent: Optional["QObject"] = None) -> None:
+ super().__init__(parent = parent)
self._application = application
+ self._container_registry = self._application.getContainerRegistry()
- self._machine_actions = {} # Dict of all known machine actions
- self._required_actions = {} # Dict of all required actions by definition ID
- self._supported_actions = {} # Dict of all supported actions by definition ID
- self._first_start_actions = {} # Dict of all actions that need to be done when first added by definition ID
+ # Keeps track of which machines have already been processed so we don't do that again.
+ self._definition_ids_with_default_actions_added = set() # type: Set[str]
+
+ # Dict of all known machine actions
+ self._machine_actions = {} # type: Dict[str, MachineAction]
+ # Dict of all required actions by definition ID
+ self._required_actions = {} # type: Dict[str, List[MachineAction]]
+ # Dict of all supported actions by definition ID
+ self._supported_actions = {} # type: Dict[str, List[MachineAction]]
+ # Dict of all actions that need to be done when first added by definition ID
+ self._first_start_actions = {} # type: Dict[str, List[MachineAction]]
def initialize(self):
- container_registry = self._application.getContainerRegistry()
-
# Add machine_action as plugin type
PluginRegistry.addType("machine_action", self.addMachineAction)
- # Ensure that all containers that were registered before creation of this registry are also handled.
- # This should not have any effect, but it makes it safer if we ever refactor the order of things.
- for container in container_registry.findDefinitionContainers():
- self._onContainerAdded(container)
+ # Adds all default machine actions that are defined in the machine definition for the given machine.
+ def addDefaultMachineActions(self, global_stack: "GlobalStack") -> None:
+ definition_id = global_stack.definition.getId()
- container_registry.containerAdded.connect(self._onContainerAdded)
+ if definition_id in self._definition_ids_with_default_actions_added:
+ Logger.log("i", "Default machine actions have been added for machine definition [%s], do nothing.",
+ definition_id)
+ return
- def _onContainerAdded(self, container):
- ## Ensure that the actions are added to this manager
- if isinstance(container, DefinitionContainer):
- supported_actions = container.getMetaDataEntry("supported_actions", [])
- for action in supported_actions:
- self.addSupportedAction(container.getId(), action)
+ supported_actions = global_stack.getMetaDataEntry("supported_actions", [])
+ for action_key in supported_actions:
+ self.addSupportedAction(definition_id, action_key)
- required_actions = container.getMetaDataEntry("required_actions", [])
- for action in required_actions:
- self.addRequiredAction(container.getId(), action)
+ required_actions = global_stack.getMetaDataEntry("required_actions", [])
+ for action_key in required_actions:
+ self.addRequiredAction(definition_id, action_key)
- first_start_actions = container.getMetaDataEntry("first_start_actions", [])
- for action in first_start_actions:
- self.addFirstStartAction(container.getId(), action)
+ first_start_actions = global_stack.getMetaDataEntry("first_start_actions", [])
+ for action_key in first_start_actions:
+ self.addFirstStartAction(definition_id, action_key)
+
+ self._definition_ids_with_default_actions_added.add(definition_id)
+ Logger.log("i", "Default machine actions added for machine definition [%s]", definition_id)
## Add a required action to a machine
# Raises an exception when the action is not recognised.
- def addRequiredAction(self, definition_id, action_key):
+ def addRequiredAction(self, definition_id: str, action_key: str) -> None:
if action_key in self._machine_actions:
if definition_id in self._required_actions:
if self._machine_actions[action_key] not in self._required_actions[definition_id]:
@@ -70,7 +84,7 @@ class MachineActionManager(QObject):
raise UnknownMachineActionError("Action %s, which is required for %s is not known." % (action_key, definition_id))
## Add a supported action to a machine.
- def addSupportedAction(self, definition_id, action_key):
+ def addSupportedAction(self, definition_id: str, action_key: str) -> None:
if action_key in self._machine_actions:
if definition_id in self._supported_actions:
if self._machine_actions[action_key] not in self._supported_actions[definition_id]:
@@ -81,13 +95,10 @@ class MachineActionManager(QObject):
Logger.log("w", "Unable to add %s to %s, as the action is not recognised", action_key, definition_id)
## Add an action to the first start list of a machine.
- def addFirstStartAction(self, definition_id, action_key, index = None):
+ def addFirstStartAction(self, definition_id: str, action_key: str) -> None:
if action_key in self._machine_actions:
if definition_id in self._first_start_actions:
- if index is not None:
- self._first_start_actions[definition_id].insert(index, self._machine_actions[action_key])
- else:
- self._first_start_actions[definition_id].append(self._machine_actions[action_key])
+ self._first_start_actions[definition_id].append(self._machine_actions[action_key])
else:
self._first_start_actions[definition_id] = [self._machine_actions[action_key]]
else:
@@ -95,7 +106,7 @@ class MachineActionManager(QObject):
## Add a (unique) MachineAction
# if the Key of the action is not unique, an exception is raised.
- def addMachineAction(self, action):
+ def addMachineAction(self, action: "MachineAction") -> None:
if action.getKey() not in self._machine_actions:
self._machine_actions[action.getKey()] = action
else:
@@ -105,7 +116,7 @@ class MachineActionManager(QObject):
# \param definition_id The ID of the definition you want the supported actions of
# \returns set of supported actions.
@pyqtSlot(str, result = "QVariantList")
- def getSupportedActions(self, definition_id):
+ def getSupportedActions(self, definition_id: str) -> List["MachineAction"]:
if definition_id in self._supported_actions:
return list(self._supported_actions[definition_id])
else:
@@ -114,19 +125,19 @@ class MachineActionManager(QObject):
## Get all actions required by given machine
# \param definition_id The ID of the definition you want the required actions of
# \returns set of required actions.
- def getRequiredActions(self, definition_id):
+ def getRequiredActions(self, definition_id: str) -> List["MachineAction"]:
if definition_id in self._required_actions:
return self._required_actions[definition_id]
else:
- return set()
+ return list()
## Get all actions that need to be performed upon first start of a given machine.
# Note that contrary to required / supported actions a list is returned (as it could be required to run the same
# 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")
- def getFirstStartActions(self, definition_id):
+ @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]
else:
@@ -134,7 +145,7 @@ class MachineActionManager(QObject):
## Remove Machine action from manager
# \param action to remove
- def removeMachineAction(self, action):
+ def removeMachineAction(self, action: "MachineAction") -> None:
try:
del self._machine_actions[action.getKey()]
except KeyError:
@@ -143,7 +154,7 @@ class MachineActionManager(QObject):
## Get MachineAction by key
# \param key String of key to select
# \return Machine action if found, None otherwise
- def getMachineAction(self, key):
+ def getMachineAction(self, key: str) -> Optional["MachineAction"]:
if key in self._machine_actions:
return self._machine_actions[key]
else:
diff --git a/cura/UI/MachineSettingsManager.py b/cura/UI/MachineSettingsManager.py
new file mode 100644
index 0000000000..7ecd9ed65f
--- /dev/null
+++ b/cura/UI/MachineSettingsManager.py
@@ -0,0 +1,82 @@
+# 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
+
+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 usre 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()
+ material_manager = self._application.getMaterialManager()
+
+ 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:
+ material_node = material_manager.getDefaultMaterial(global_stack, position, None)
+ 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 67%
rename from cura/PrintInformation.py
rename to cura/UI/PrintInformation.py
index 85cf6651fa..3fafaaba12 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
+from typing import Dict, List, Optional, TYPE_CHECKING
from PyQt5.QtCore import QObject, pyqtSignal, pyqtProperty, pyqtSlot
@@ -14,57 +13,40 @@ from UM.Logger import Logger
from UM.Qt.Duration import Duration
from UM.Scene.SceneNode import SceneNode
from UM.i18n import i18nCatalog
-from UM.MimeTypeDatabase import MimeTypeDatabase
+from UM.MimeTypeDatabase import MimeTypeDatabase, MimeTypeNotFoundError
+
+if TYPE_CHECKING:
+ from cura.CuraApplication import CuraApplication
catalog = i18nCatalog("cura")
-## A class for processing and calculating minimum, current and maximum print time as well as managing the job name
-#
-# This class contains all the logic relating to calculation and slicing for the
-# time/quality slider concept. It is a rather tricky combination of event handling
-# and state management. The logic behind this is as follows:
-#
-# - A scene change or setting change event happens.
-# We track what the source was of the change, either a scene change, a setting change, an active machine change or something else.
-# - This triggers a new slice with the current settings - this is the "current settings pass".
-# - When the slice is done, we update the current print time and material amount.
-# - If the source of the slice was not a Setting change, we start the second slice pass, the "low quality settings pass". Otherwise we stop here.
-# - When that is done, we update the minimum print time and start the final slice pass, the "Extra Fine settings pass".
-# - When the Extra Fine pass is done, we update the maximum print time.
+## A class for processing and the print times per build plate as well as managing the job name
#
# This class also mangles the current machine name and the filename of the first loaded mesh into a job name.
# This job name is requested by the JobSpecs qml file.
class PrintInformation(QObject):
- class SlicePass:
- CurrentSettings = 1
- LowQualitySettings = 2
- HighQualitySettings = 3
- class SliceReason:
- SceneChanged = 1
- SettingChanged = 2
- ActiveMachineChanged = 3
- Other = 4
+ UNTITLED_JOB_NAME = "Untitled"
- def __init__(self, application, parent = None):
+ def __init__(self, application: "CuraApplication", parent = None) -> None:
super().__init__(parent)
self._application = application
- self.UNTITLED_JOB_NAME = "Untitled"
-
self.initializeCuraMessagePrintTimeProperties()
- self._material_lengths = {} # indexed by build plate number
- self._material_weights = {}
- self._material_costs = {}
- self._material_names = {}
+ # Indexed by build plate number
+ self._material_lengths = {} # type: Dict[int, List[float]]
+ self._material_weights = {} # type: Dict[int, List[float]]
+ self._material_costs = {} # type: Dict[int, List[float]]
+ self._material_names = {} # type: Dict[int, List[str]]
self._pre_sliced = False
self._backend = self._application.getBackend()
if self._backend:
self._backend.printDurationMessage.connect(self._onPrintDurationMessage)
+
self._application.getController().getScene().sceneChanged.connect(self._onSceneChanged)
self._is_user_specified_job_name = False
@@ -72,29 +54,23 @@ class PrintInformation(QObject):
self._abbr_machine = ""
self._job_name = ""
self._active_build_plate = 0
- self._initVariablesWithBuildPlate(self._active_build_plate)
+ self._initVariablesByBuildPlate(self._active_build_plate)
self._multi_build_plate_model = self._application.getMultiBuildPlateModel()
- ss = self._multi_build_plate_model.maxBuildPlate
-
self._application.globalContainerStackChanged.connect(self._updateJobName)
self._application.globalContainerStackChanged.connect(self.setToZeroPrintInformation)
self._application.fileLoaded.connect(self.setBaseName)
self._application.workspaceLoaded.connect(self.setProjectName)
- self._multi_build_plate_model.activeBuildPlateChanged.connect(self._onActiveBuildPlateChanged)
-
+ self._application.getMachineManager().rootMaterialChanged.connect(self._onActiveMaterialsChanged)
self._application.getInstance().getPreferences().preferenceChanged.connect(self._onPreferencesChanged)
- self._application.getMachineManager().rootMaterialChanged.connect(self._onActiveMaterialsChanged)
+ self._multi_build_plate_model.activeBuildPlateChanged.connect(self._onActiveBuildPlateChanged)
+ self._material_amounts = [] # type: List[float]
self._onActiveMaterialsChanged()
- self._material_amounts = []
-
- # Crate cura message translations and using translation keys initialize empty time Duration object for total time
- # and time for each feature
- def initializeCuraMessagePrintTimeProperties(self):
- self._current_print_time = {} # Duration(None, self)
+ def initializeCuraMessagePrintTimeProperties(self) -> None:
+ self._current_print_time = {} # type: Dict[int, Duration]
self._print_time_message_translations = {
"inset_0": catalog.i18nc("@tooltip", "Outer Wall"),
@@ -105,22 +81,23 @@ 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")
}
- self._print_time_message_values = {}
+ self._print_times_per_feature = {} # type: Dict[int, Dict[str, Duration]]
- def _initPrintTimeMessageValues(self, build_plate_number):
+ def _initPrintTimesPerFeature(self, build_plate_number: int) -> None:
# Full fill message values using keys from _print_time_message_translations
- self._print_time_message_values[build_plate_number] = {}
+ self._print_times_per_feature[build_plate_number] = {}
for key in self._print_time_message_translations.keys():
- self._print_time_message_values[build_plate_number][key] = Duration(None, self)
+ self._print_times_per_feature[build_plate_number][key] = Duration(None, self)
- def _initVariablesWithBuildPlate(self, build_plate_number):
- if build_plate_number not in self._print_time_message_values:
- self._initPrintTimeMessageValues(build_plate_number)
+ def _initVariablesByBuildPlate(self, build_plate_number: int) -> None:
+ if build_plate_number not in self._print_times_per_feature:
+ self._initPrintTimesPerFeature(build_plate_number)
if self._active_build_plate not in self._material_lengths:
self._material_lengths[self._active_build_plate] = []
if self._active_build_plate not in self._material_weights:
@@ -130,23 +107,24 @@ class PrintInformation(QObject):
if self._active_build_plate not in self._material_names:
self._material_names[self._active_build_plate] = []
if self._active_build_plate not in self._current_print_time:
- self._current_print_time[self._active_build_plate] = Duration(None, self)
+ self._current_print_time[self._active_build_plate] = Duration(parent = self)
currentPrintTimeChanged = pyqtSignal()
preSlicedChanged = pyqtSignal()
@pyqtProperty(bool, notify=preSlicedChanged)
- def preSliced(self):
+ def preSliced(self) -> bool:
return self._pre_sliced
- def setPreSliced(self, pre_sliced):
- self._pre_sliced = pre_sliced
- self._updateJobName()
- self.preSlicedChanged.emit()
+ def setPreSliced(self, pre_sliced: bool) -> None:
+ if self._pre_sliced != pre_sliced:
+ self._pre_sliced = pre_sliced
+ self._updateJobName()
+ self.preSlicedChanged.emit()
@pyqtProperty(Duration, notify = currentPrintTimeChanged)
- def currentPrintTime(self):
+ def currentPrintTime(self) -> Duration:
return self._current_print_time[self._active_build_plate]
materialLengthsChanged = pyqtSignal()
@@ -173,36 +151,41 @@ class PrintInformation(QObject):
def materialNames(self):
return self._material_names[self._active_build_plate]
- def printTimes(self):
- return self._print_time_message_values[self._active_build_plate]
+ # Get all print times (by feature) of the active buildplate.
+ def printTimes(self) -> Dict[str, Duration]:
+ return self._print_times_per_feature[self._active_build_plate]
- def _onPrintDurationMessage(self, build_plate_number, print_time: Dict[str, int], material_amounts: list):
- self._updateTotalPrintTimePerFeature(build_plate_number, print_time)
+ def _onPrintDurationMessage(self, build_plate_number: int, print_times_per_feature: Dict[str, int], material_amounts: List[float]) -> None:
+ self._updateTotalPrintTimePerFeature(build_plate_number, print_times_per_feature)
self.currentPrintTimeChanged.emit()
self._material_amounts = material_amounts
self._calculateInformation(build_plate_number)
- def _updateTotalPrintTimePerFeature(self, build_plate_number, print_time: Dict[str, int]):
+ def _updateTotalPrintTimePerFeature(self, build_plate_number: int, print_times_per_feature: Dict[str, int]) -> None:
total_estimated_time = 0
- if build_plate_number not in self._print_time_message_values:
- self._initPrintTimeMessageValues(build_plate_number)
+ if build_plate_number not in self._print_times_per_feature:
+ self._initPrintTimesPerFeature(build_plate_number)
+
+ for feature, time in print_times_per_feature.items():
+ if feature not in self._print_times_per_feature[build_plate_number]:
+ self._print_times_per_feature[build_plate_number][feature] = Duration(parent=self)
+ duration = self._print_times_per_feature[build_plate_number][feature]
- for feature, time in print_time.items():
if time != time: # Check for NaN. Engine can sometimes give us weird values.
- self._print_time_message_values[build_plate_number].get(feature).setDuration(0)
+ duration.setDuration(0)
Logger.log("w", "Received NaN for print duration message")
continue
total_estimated_time += time
- self._print_time_message_values[build_plate_number].get(feature).setDuration(time)
+ duration.setDuration(time)
if build_plate_number not in self._current_print_time:
self._current_print_time[build_plate_number] = Duration(None, self)
self._current_print_time[build_plate_number].setDuration(total_estimated_time)
- def _calculateInformation(self, build_plate_number):
+ def _calculateInformation(self, build_plate_number: int) -> None:
global_stack = self._application.getGlobalContainerStack()
if global_stack is None:
return
@@ -215,39 +198,46 @@ class PrintInformation(QObject):
material_preference_values = json.loads(self._application.getInstance().getPreferences().getValue("cura/material_settings"))
extruder_stacks = global_stack.extruders
- for position, extruder_stack in extruder_stacks.items():
+
+ for position in extruder_stacks:
+ extruder_stack = extruder_stacks[position]
index = int(position)
if index >= len(self._material_amounts):
continue
amount = self._material_amounts[index]
- ## Find the right extruder stack. As the list isn't sorted because it's a annoying generator, we do some
- # list comprehension filtering to solve this for us.
+ # Find the right extruder stack. As the list isn't sorted because it's a annoying generator, we do some
+ # list comprehension filtering to solve this for us.
density = extruder_stack.getMetaDataEntry("properties", {}).get("density", 0)
- material = extruder_stack.findContainer({"type": "material"})
+ material = extruder_stack.material
radius = extruder_stack.getProperty("material_diameter", "value") / 2
weight = float(amount) * float(density) / 1000
- cost = 0
- material_name = catalog.i18nc("@label unknown material", "Unknown")
- if material:
- material_guid = material.getMetaDataEntry("GUID")
- material_name = material.getName()
- if material_guid in material_preference_values:
- material_values = material_preference_values[material_guid]
+ cost = 0.
- weight_per_spool = float(material_values["spool_weight"] if material_values and "spool_weight" in material_values else 0)
- cost_per_spool = float(material_values["spool_cost"] if material_values and "spool_cost" in material_values else 0)
+ material_guid = material.getMetaDataEntry("GUID")
+ material_name = material.getName()
- if weight_per_spool != 0:
- cost = cost_per_spool * weight / weight_per_spool
- else:
- cost = 0
+ if material_guid in material_preference_values:
+ material_values = material_preference_values[material_guid]
+
+ if material_values and "spool_weight" in material_values:
+ weight_per_spool = float(material_values["spool_weight"])
+ else:
+ weight_per_spool = float(extruder_stack.getMetaDataEntry("properties", {}).get("weight", 0))
+
+ cost_per_spool = float(material_values["spool_cost"] if material_values and "spool_cost" in material_values else 0)
+
+ if weight_per_spool != 0:
+ cost = cost_per_spool * weight / weight_per_spool
+ else:
+ cost = 0
# Material amount is sent as an amount of mm^3, so calculate length from that
if radius != 0:
length = round((amount / (math.pi * radius ** 2)) / 1000, 2)
else:
length = 0
+
self._material_weights[build_plate_number].append(weight)
self._material_lengths[build_plate_number].append(length)
self._material_costs[build_plate_number].append(cost)
@@ -258,20 +248,20 @@ class PrintInformation(QObject):
self.materialCostsChanged.emit()
self.materialNamesChanged.emit()
- def _onPreferencesChanged(self, preference):
+ def _onPreferencesChanged(self, preference: str) -> None:
if preference != "cura/material_settings":
return
for build_plate_number in range(self._multi_build_plate_model.maxBuildPlate + 1):
self._calculateInformation(build_plate_number)
- def _onActiveBuildPlateChanged(self):
+ def _onActiveBuildPlateChanged(self) -> None:
new_active_build_plate = self._multi_build_plate_model.activeBuildPlate
if new_active_build_plate != self._active_build_plate:
self._active_build_plate = new_active_build_plate
self._updateJobName()
- self._initVariablesWithBuildPlate(self._active_build_plate)
+ self._initVariablesByBuildPlate(self._active_build_plate)
self.materialLengthsChanged.emit()
self.materialWeightsChanged.emit()
@@ -279,14 +269,14 @@ class PrintInformation(QObject):
self.materialNamesChanged.emit()
self.currentPrintTimeChanged.emit()
- def _onActiveMaterialsChanged(self, *args, **kwargs):
+ def _onActiveMaterialsChanged(self, *args, **kwargs) -> None:
for build_plate_number in range(self._multi_build_plate_model.maxBuildPlate + 1):
self._calculateInformation(build_plate_number)
# Manual override of job name should also set the base name so that when the printer prefix is updated, it the
# prefix can be added to the manually added name, not the old base name
@pyqtSlot(str, bool)
- def setJobName(self, name, is_user_specified_job_name = False):
+ def setJobName(self, name: str, is_user_specified_job_name = False) -> None:
self._is_user_specified_job_name = is_user_specified_job_name
self._job_name = name
self._base_name = name.replace(self._abbr_machine + "_", "")
@@ -300,7 +290,7 @@ class PrintInformation(QObject):
def jobName(self):
return self._job_name
- def _updateJobName(self):
+ def _updateJobName(self) -> None:
if self._base_name == "":
self._job_name = self.UNTITLED_JOB_NAME
self._is_user_specified_job_name = False
@@ -335,12 +325,12 @@ class PrintInformation(QObject):
self.jobNameChanged.emit()
@pyqtSlot(str)
- def setProjectName(self, name):
+ def setProjectName(self, name: str) -> None:
self.setBaseName(name, is_project_file = True)
baseNameChanged = pyqtSignal()
- def setBaseName(self, base_name: str, is_project_file: bool = False):
+ def setBaseName(self, base_name: str, is_project_file: bool = False) -> None:
self._is_user_specified_job_name = False
# Ensure that we don't use entire path but only filename
@@ -367,7 +357,7 @@ class PrintInformation(QObject):
try:
mime_type = MimeTypeDatabase.getMimeTypeForFile(name)
data = mime_type.stripExtension(name)
- except:
+ except MimeTypeNotFoundError:
Logger.log("w", "Unsupported Mime Type Database file extension %s", name)
if data is not None and check_name is not None:
@@ -375,6 +365,16 @@ class PrintInformation(QObject):
else:
self._base_name = ""
+ # Strip the old "curaproject" extension from the name
+ OLD_CURA_PROJECT_EXT = ".curaproject"
+ if self._base_name.lower().endswith(OLD_CURA_PROJECT_EXT):
+ self._base_name = self._base_name[:len(self._base_name) - len(OLD_CURA_PROJECT_EXT)]
+
+ # CURA-5896 Try to strip extra extensions with an infinite amount of ".curaproject.3mf".
+ OLD_CURA_PROJECT_3MF_EXT = ".curaproject.3mf"
+ while self._base_name.lower().endswith(OLD_CURA_PROJECT_3MF_EXT):
+ self._base_name = self._base_name[:len(self._base_name) - len(OLD_CURA_PROJECT_3MF_EXT)]
+
self._updateJobName()
@pyqtProperty(str, fset = setBaseName, notify = baseNameChanged)
@@ -384,39 +384,25 @@ class PrintInformation(QObject):
## Created an acronym-like abbreviated machine name from the currently
# active machine name.
# Called each time the global stack is switched.
- def _defineAbbreviatedMachineName(self):
+ def _defineAbbreviatedMachineName(self) -> None:
global_container_stack = self._application.getGlobalContainerStack()
if not global_container_stack:
self._abbr_machine = ""
return
active_machine_type_name = global_container_stack.definition.getName()
- abbr_machine = ""
- for word in re.findall(r"[\w']+", active_machine_type_name):
- if word.lower() == "ultimaker":
- abbr_machine += "UM"
- elif word.isdigit():
- abbr_machine += word
- else:
- stripped_word = self._stripAccents(word.upper())
- # - use only the first character if the word is too long (> 3 characters)
- # - use the whole word if it's not too long (<= 3 characters)
- if len(stripped_word) > 3:
- stripped_word = stripped_word[0]
- abbr_machine += stripped_word
-
- self._abbr_machine = abbr_machine
+ self._abbr_machine = self._application.getMachineManager().getAbbreviatedMachineName(active_machine_type_name)
## Utility method that strips accents from characters (eg: â -> a)
- def _stripAccents(self, str):
- return ''.join(char for char in unicodedata.normalize('NFD', str) if unicodedata.category(char) != 'Mn')
+ def _stripAccents(self, to_strip: str) -> str:
+ return ''.join(char for char in unicodedata.normalize('NFD', to_strip) if unicodedata.category(char) != 'Mn')
@pyqtSlot(result = "QVariantMap")
- def getFeaturePrintTimes(self):
+ def getFeaturePrintTimes(self) -> Dict[str, Duration]:
result = {}
- if self._active_build_plate not in self._print_time_message_values:
- self._initPrintTimeMessageValues(self._active_build_plate)
- for feature, time in self._print_time_message_values[self._active_build_plate].items():
+ if self._active_build_plate not in self._print_times_per_feature:
+ self._initPrintTimesPerFeature(self._active_build_plate)
+ for feature, time in self._print_times_per_feature[self._active_build_plate].items():
if feature in self._print_time_message_translations:
result[self._print_time_message_translations[feature]] = time
else:
@@ -424,22 +410,22 @@ class PrintInformation(QObject):
return result
# Simulate message with zero time duration
- def setToZeroPrintInformation(self, build_plate = None):
+ def setToZeroPrintInformation(self, build_plate: Optional[int] = None) -> None:
if build_plate is None:
build_plate = self._active_build_plate
# Construct the 0-time message
temp_message = {}
- if build_plate not in self._print_time_message_values:
- self._print_time_message_values[build_plate] = {}
- for key in self._print_time_message_values[build_plate].keys():
+ if build_plate not in self._print_times_per_feature:
+ self._print_times_per_feature[build_plate] = {}
+ for key in self._print_times_per_feature[build_plate].keys():
temp_message[key] = 0
- temp_material_amounts = [0]
+ temp_material_amounts = [0.]
self._onPrintDurationMessage(build_plate, temp_message, temp_material_amounts)
## Listen to scene changes to check if we need to reset the print information
- def _onSceneChanged(self, scene_node):
+ def _onSceneChanged(self, scene_node: SceneNode) -> None:
# Ignore any changes that are not related to sliceable objects
if not isinstance(scene_node, SceneNode)\
or not scene_node.callDecoration("isSliceable")\
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/UltimakerCloudAuthentication.py b/cura/UltimakerCloudAuthentication.py
new file mode 100644
index 0000000000..c8346e5c4e
--- /dev/null
+++ b/cura/UltimakerCloudAuthentication.py
@@ -0,0 +1,30 @@
+# Copyright (c) 2018 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+
+# ---------
+# Constants used for the Cloud API
+# ---------
+DEFAULT_CLOUD_API_ROOT = "https://api.ultimaker.com" # type: str
+DEFAULT_CLOUD_API_VERSION = "1" # type: str
+DEFAULT_CLOUD_ACCOUNT_API_ROOT = "https://account.ultimaker.com" # type: str
+
+try:
+ from cura.CuraVersion import CuraCloudAPIRoot # type: ignore
+ if CuraCloudAPIRoot == "":
+ CuraCloudAPIRoot = DEFAULT_CLOUD_API_ROOT
+except ImportError:
+ CuraCloudAPIRoot = DEFAULT_CLOUD_API_ROOT
+
+try:
+ from cura.CuraVersion import CuraCloudAPIVersion # type: ignore
+ if CuraCloudAPIVersion == "":
+ CuraCloudAPIVersion = DEFAULT_CLOUD_API_VERSION
+except ImportError:
+ CuraCloudAPIVersion = DEFAULT_CLOUD_API_VERSION
+
+try:
+ from cura.CuraVersion import CuraCloudAccountAPIRoot # type: ignore
+ if CuraCloudAccountAPIRoot == "":
+ CuraCloudAccountAPIRoot = DEFAULT_CLOUD_ACCOUNT_API_ROOT
+except ImportError:
+ CuraCloudAccountAPIRoot = DEFAULT_CLOUD_ACCOUNT_API_ROOT
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/Utils/Threading.py b/cura/Utils/Threading.py
index 3cd6200513..550a5421ff 100644
--- a/cura/Utils/Threading.py
+++ b/cura/Utils/Threading.py
@@ -1,3 +1,4 @@
+import functools
import threading
from cura.CuraApplication import CuraApplication
@@ -6,7 +7,7 @@ from cura.CuraApplication import CuraApplication
#
# HACK:
#
-# In project loading, when override the existing machine is selected, the stacks and containers that are correctly
+# In project loading, when override the existing machine is selected, the stacks and containers that are currently
# active in the system will be overridden at runtime. Because the project loading is done in a different thread than
# the Qt thread, something else can kick in the middle of the process. One of them is the rendering. It will access
# the current stacks and container, which have not completely been updated yet, so Cura will crash in this case.
@@ -22,7 +23,13 @@ class InterCallObject:
def call_on_qt_thread(func):
+ @functools.wraps(func)
def _call_on_qt_thread_wrapper(*args, **kwargs):
+ # If the current thread is the main thread, which is the Qt thread, directly call the function.
+ current_thread = threading.current_thread()
+ if isinstance(current_thread, threading._MainThread):
+ return func(*args, **kwargs)
+
def _handle_call(ico, *args, **kwargs):
ico.result = func(*args, **kwargs)
ico.finish_event.set()
diff --git a/cura_app.py b/cura_app.py
index 164e32e738..3599f127cc 100755
--- a/cura_app.py
+++ b/cura_app.py
@@ -9,6 +9,7 @@ import os
import sys
from UM.Platform import Platform
+from cura.ApplicationMetadata import CuraAppName
parser = argparse.ArgumentParser(prog = "cura",
add_help = False)
@@ -17,24 +18,22 @@ parser.add_argument("--debug",
default = False,
help = "Turn on the debug mode by setting this option."
)
-parser.add_argument("--trigger-early-crash",
- dest = "trigger_early_crash",
- action = "store_true",
- default = False,
- help = "FOR TESTING ONLY. Trigger an early crash to show the crash dialog."
- )
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/cura")
+ 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/cura")
+ return os.path.expanduser("~/.local/share/" + CuraAppName)
elif Platform.isOSX():
- return os.path.expanduser("~/Library/Logs/cura")
+ 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")
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/installer.nsi b/installer.nsi
deleted file mode 100644
index 7516f733a1..0000000000
--- a/installer.nsi
+++ /dev/null
@@ -1,156 +0,0 @@
-!ifndef VERSION
- !define VERSION '15.09.80'
-!endif
-
-; The name of the installer
-Name "Cura ${VERSION}"
-
-; The file to write
-OutFile "Cura_${VERSION}.exe"
-
-; The default installation directory
-InstallDir $PROGRAMFILES\Cura_${VERSION}
-
-; Registry key to check for directory (so if you install again, it will
-; overwrite the old one automatically)
-InstallDirRegKey HKLM "Software\Cura_${VERSION}" "Install_Dir"
-
-; Request application privileges for Windows Vista
-RequestExecutionLevel admin
-
-; Set the LZMA compressor to reduce size.
-SetCompressor /SOLID lzma
-;--------------------------------
-
-!include "MUI2.nsh"
-!include "Library.nsh"
-
-; !define MUI_ICON "dist/resources/cura.ico"
-!define MUI_BGCOLOR FFFFFF
-
-; Directory page defines
-!define MUI_DIRECTORYPAGE_VERIFYONLEAVE
-
-; Header
-; Don't show the component description box
-!define MUI_COMPONENTSPAGE_NODESC
-
-;Do not leave (Un)Installer page automaticly
-!define MUI_FINISHPAGE_NOAUTOCLOSE
-!define MUI_UNFINISHPAGE_NOAUTOCLOSE
-
-;Run Cura after installing
-!define MUI_FINISHPAGE_RUN
-!define MUI_FINISHPAGE_RUN_TEXT "Start Cura ${VERSION}"
-!define MUI_FINISHPAGE_RUN_FUNCTION "LaunchLink"
-
-;Add an option to show release notes
-!define MUI_FINISHPAGE_SHOWREADME "$INSTDIR\plugins\ChangeLogPlugin\changelog.txt"
-
-; Pages
-;!insertmacro MUI_PAGE_WELCOME
-!insertmacro MUI_PAGE_DIRECTORY
-!insertmacro MUI_PAGE_COMPONENTS
-!insertmacro MUI_PAGE_INSTFILES
-!insertmacro MUI_PAGE_FINISH
-!insertmacro MUI_UNPAGE_CONFIRM
-!insertmacro MUI_UNPAGE_INSTFILES
-!insertmacro MUI_UNPAGE_FINISH
-
-; Languages
-!insertmacro MUI_LANGUAGE "English"
-
-; Reserve Files
-!insertmacro MUI_RESERVEFILE_LANGDLL
-ReserveFile '${NSISDIR}\Plugins\InstallOptions.dll'
-
-;--------------------------------
-
-; The stuff to install
-Section "Cura ${VERSION}"
-
- SectionIn RO
-
- ; Set output path to the installation directory.
- SetOutPath $INSTDIR
-
- ; Put file there
- File /r "dist\"
-
- ; Write the installation path into the registry
- WriteRegStr HKLM "SOFTWARE\Cura_${VERSION}" "Install_Dir" "$INSTDIR"
-
- ; Write the uninstall keys for Windows
- WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Cura_${VERSION}" "DisplayName" "Cura ${VERSION}"
- WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Cura_${VERSION}" "UninstallString" '"$INSTDIR\uninstall.exe"'
- WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Cura_${VERSION}" "NoModify" 1
- WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Cura_${VERSION}" "NoRepair" 1
- WriteUninstaller "uninstall.exe"
-
- ; Write start menu entries for all users
- SetShellVarContext all
-
- CreateDirectory "$SMPROGRAMS\Cura ${VERSION}"
- CreateShortCut "$SMPROGRAMS\Cura ${VERSION}\Uninstall Cura ${VERSION}.lnk" "$INSTDIR\uninstall.exe" "" "$INSTDIR\uninstall.exe" 0
- CreateShortCut "$SMPROGRAMS\Cura ${VERSION}\Cura ${VERSION}.lnk" "$INSTDIR\Cura.exe" '' "$INSTDIR\Cura.exe" 0
-
-SectionEnd
-
-Function LaunchLink
- ; Write start menu entries for all users
- SetShellVarContext all
- Exec '"$WINDIR\explorer.exe" "$SMPROGRAMS\Cura ${VERSION}\Cura ${VERSION}.lnk"'
-FunctionEnd
-
-Section "Install Visual Studio 2010 Redistributable"
- SetOutPath "$INSTDIR"
- File "vcredist_2010_20110908_x86.exe"
-
- IfSilent +2
- ExecWait '"$INSTDIR\vcredist_2010_20110908_x86.exe" /q /norestart'
-
-SectionEnd
-
-Section "Install Arduino Drivers"
- ; Set output path to the driver directory.
- SetOutPath "$INSTDIR\drivers\"
- File /r "drivers\"
-
- ${If} ${RunningX64}
- IfSilent +2
- ExecWait '"$INSTDIR\drivers\dpinst64.exe" /lm'
- ${Else}
- IfSilent +2
- ExecWait '"$INSTDIR\drivers\dpinst32.exe" /lm'
- ${EndIf}
-SectionEnd
-
-Section "Open STL files with Cura"
- ${registerExtension} "$INSTDIR\Cura.exe" ".stl" "STL_File"
-SectionEnd
-
-Section /o "Open OBJ files with Cura"
- WriteRegStr HKCR .obj "" "Cura OBJ model file"
- DeleteRegValue HKCR .obj "Content Type"
- WriteRegStr HKCR "Cura OBJ model file\DefaultIcon" "" "$INSTDIR\Cura.exe,0"
- WriteRegStr HKCR "Cura OBJ model file\shell" "" "open"
- WriteRegStr HKCR "Cura OBJ model file\shell\open\command" "" '"$INSTDIR\Cura.exe" "%1"'
-SectionEnd
-
-;--------------------------------
-
-; Uninstaller
-
-Section "Uninstall"
-
- ; Remove registry keys
- DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Cura_${VERSION}"
- DeleteRegKey HKLM "SOFTWARE\Cura_${VERSION}"
-
- ; Write start menu entries for all users
- SetShellVarContext all
- ; Remove directories used
- RMDir /r "$SMPROGRAMS\Cura ${VERSION}"
- RMDir /r "$INSTDIR"
-
-SectionEnd
diff --git a/plugins/3MFReader/ThreeMFReader.py b/plugins/3MFReader/ThreeMFReader.py
index 49c6995d18..b81d0858a4 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,15 +9,16 @@ 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.Settings.ExtruderManager import ExtruderManager
from cura.Scene.CuraSceneNode import CuraSceneNode
from cura.Scene.BuildPlateDecorator import BuildPlateDecorator
@@ -25,11 +26,9 @@ 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:
@@ -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 429d4ab7d4..a9142c6d12 100755
--- a/plugins/3MFReader/ThreeMFWorkspaceReader.py
+++ b/plugins/3MFReader/ThreeMFWorkspaceReader.py
@@ -26,6 +26,7 @@ from UM.Preferences import Preferences
from cura.Machines.VariantType import VariantType
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.CuraContainerStack import _ContainerIndexes
@@ -258,7 +259,7 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
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
+ num_settings_overridden_by_quality_changes = 0 # How many settings are changed by the quality changes
num_user_settings = 0
quality_changes_conflict = False
@@ -296,9 +297,10 @@ 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(id = container_id)
+ quality_changes = self._container_registry.findInstanceContainers(name = custom_quality_name,
+ type = "quality_changes")
if quality_changes:
containers_found_dict["quality_changes"] = True
# Check if there really is a conflict by comparing the values
@@ -417,13 +419,17 @@ 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]
@@ -499,7 +505,7 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
is_printer_group = False
if machine_conflict:
- group_name = existing_global_stack.getMetaDataEntry("connect_group_name")
+ group_name = existing_global_stack.getMetaDataEntry("group_name")
if group_name is not None:
is_printer_group = True
machine_name = group_name
@@ -513,7 +519,7 @@ 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.setNumSettingsOverriddenByQualityChanges(num_settings_overridden_by_quality_changes)
self._dialog.setNumUserSettings(num_user_settings)
self._dialog.setActiveMode(active_mode)
self._dialog.setMachineName(machine_name)
@@ -780,6 +786,10 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
if not quality_changes_info.extruder_info_dict:
container_info = ContainerInfo(None, None, None)
quality_changes_info.extruder_info_dict["0"] = container_info
+ # If the global stack we're "targeting" has never been active, but was updated from Cura 3.4,
+ # it might not have it's extruders set properly.
+ if not global_stack.extruders:
+ ExtruderManager.getInstance().fixSingleExtrusionMachineExtruderDefinition(global_stack)
extruder_stack = global_stack.extruders["0"]
container = quality_manager._createQualityChanges(quality_changes_quality_type, quality_changes_name,
@@ -793,7 +803,8 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
# Clear all existing containers
quality_changes_info.global_info.container.clear()
for container_info in quality_changes_info.extruder_info_dict.values():
- container_info.container.clear()
+ if container_info.container:
+ container_info.container.clear()
# Loop over everything and override the existing containers
global_info = quality_changes_info.global_info
@@ -813,6 +824,8 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
container = quality_manager._createQualityChanges(quality_changes_quality_type, quality_changes_name,
global_stack, extruder_stack)
container_info.container = container
+ container.setDirty(True)
+ self._container_registry.addContainer(container)
for key, value in container_info.parser["values"].items():
container_info.container.setProperty(key, "value", value)
@@ -896,6 +909,10 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
continue
extruder_info = self._machine_info.extruder_info_dict[position]
if extruder_info.variant_info is None:
+ # If there is no variant_info, try to use the default variant. Otherwise, leave it be.
+ node = variant_manager.getDefaultVariantNode(global_stack.definition, VariantType.NOZZLE, global_stack)
+ if node is not None and node.getContainer() is not None:
+ extruder_stack.variant = node.getContainer()
continue
parser = extruder_info.variant_info.parser
@@ -926,7 +943,7 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
build_plate_id = global_stack.variant.getId()
# get material diameter of this extruder
- machine_material_diameter = extruder_stack.materialDiameter
+ machine_material_diameter = extruder_stack.getCompatibleMaterialDiameter()
material_node = material_manager.getMaterialNode(global_stack.definition.getId(),
extruder_stack.variant.getName(),
build_plate_id,
diff --git a/plugins/3MFReader/WorkspaceDialog.py b/plugins/3MFReader/WorkspaceDialog.py
index 6e1cbb2019..332c57ceb1 100644
--- a/plugins/3MFReader/WorkspaceDialog.py
+++ b/plugins/3MFReader/WorkspaceDialog.py
@@ -41,7 +41,7 @@ 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._machine_name = ""
self._machine_type = ""
@@ -151,10 +151,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)
diff --git a/plugins/3MFReader/plugin.json b/plugins/3MFReader/plugin.json
index 5e41975752..5af21a7033 100644
--- a/plugins/3MFReader/plugin.json
+++ b/plugins/3MFReader/plugin.json
@@ -1,8 +1,8 @@
{
"name": "3MF Reader",
"author": "Ultimaker B.V.",
- "version": "1.0.0",
+ "version": "1.0.1",
"description": "Provides support for reading 3MF files.",
- "api": 5,
+ "api": "6.0",
"i18n-catalog": "cura"
}
diff --git a/plugins/3MFWriter/plugin.json b/plugins/3MFWriter/plugin.json
index 9ec4fb0c20..3820ebd2e7 100644
--- a/plugins/3MFWriter/plugin.json
+++ b/plugins/3MFWriter/plugin.json
@@ -1,8 +1,8 @@
{
"name": "3MF Writer",
"author": "Ultimaker B.V.",
- "version": "1.0.0",
+ "version": "1.0.1",
"description": "Provides support for writing 3MF files.",
- "api": 5,
+ "api": "6.0",
"i18n-catalog": "cura"
}
diff --git a/plugins/AMFReader/AMFReader.py b/plugins/AMFReader/AMFReader.py
new file mode 100644
index 0000000000..d35fbe3d40
--- /dev/null
+++ b/plugins/AMFReader/AMFReader.py
@@ -0,0 +1,173 @@
+# Copyright (c) 2019 fieldOfView
+# 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..599dc03c76
--- /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": "6.0.0"
+}
diff --git a/plugins/ChangeLogPlugin/ChangeLog.py b/plugins/ChangeLogPlugin/ChangeLog.py
deleted file mode 100644
index 723c83a021..0000000000
--- a/plugins/ChangeLogPlugin/ChangeLog.py
+++ /dev/null
@@ -1,108 +0,0 @@
-# Copyright (c) 2015 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.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 e09a08564a..0000000000
--- a/plugins/ChangeLogPlugin/plugin.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "name": "Changelog",
- "author": "Ultimaker B.V.",
- "version": "1.0.0",
- "description": "Shows changes since latest checked version.",
- "api": 5,
- "i18n-catalog": "cura"
-}
diff --git a/plugins/CuraDrive/__init__.py b/plugins/CuraDrive/__init__.py
new file mode 100644
index 0000000000..eeb6b78689
--- /dev/null
+++ b/plugins/CuraDrive/__init__.py
@@ -0,0 +1,12 @@
+# Copyright (c) 2018 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+
+from .src.DrivePluginExtension import DrivePluginExtension
+
+
+def getMetaData():
+ return {}
+
+
+def register(app):
+ return {"extension": DrivePluginExtension()}
diff --git a/plugins/CuraDrive/plugin.json b/plugins/CuraDrive/plugin.json
new file mode 100644
index 0000000000..d1cab39ca5
--- /dev/null
+++ b/plugins/CuraDrive/plugin.json
@@ -0,0 +1,8 @@
+{
+ "name": "Cura Backups",
+ "author": "Ultimaker B.V.",
+ "description": "Backup and restore your configuration.",
+ "version": "1.2.0",
+ "api": 6,
+ "i18n-catalog": "cura"
+}
diff --git a/plugins/CuraDrive/src/DriveApiService.py b/plugins/CuraDrive/src/DriveApiService.py
new file mode 100644
index 0000000000..d8349ccc29
--- /dev/null
+++ b/plugins/CuraDrive/src/DriveApiService.py
@@ -0,0 +1,191 @@
+# Copyright (c) 2018 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+
+import base64
+import hashlib
+from datetime import datetime
+from tempfile import NamedTemporaryFile
+from typing import Any, Optional, List, Dict
+
+import requests
+
+from UM.Logger import Logger
+from UM.Message import Message
+from UM.Signal import Signal, signalemitter
+from cura.CuraApplication import CuraApplication
+
+from .UploadBackupJob import UploadBackupJob
+from .Settings import Settings
+
+from UM.i18n import i18nCatalog
+catalog = i18nCatalog("cura")
+
+
+## The DriveApiService is responsible for interacting with the CuraDrive API and Cura's backup handling.
+@signalemitter
+class DriveApiService:
+ BACKUP_URL = "{}/backups".format(Settings.DRIVE_API_URL)
+
+ # Emit signal when restoring backup started or finished.
+ restoringStateChanged = Signal()
+
+ # Emit signal when creating backup started or finished.
+ creatingStateChanged = Signal()
+
+ def __init__(self) -> None:
+ self._cura_api = CuraApplication.getInstance().getCuraAPI()
+
+ def getBackups(self) -> List[Dict[str, Any]]:
+ access_token = self._cura_api.account.accessToken
+ if not access_token:
+ Logger.log("w", "Could not get access token.")
+ return []
+ try:
+ backup_list_request = requests.get(self.BACKUP_URL, headers = {
+ "Authorization": "Bearer {}".format(access_token)
+ })
+ except requests.exceptions.ConnectionError:
+ Logger.logException("w", "Unable to connect with the server.")
+ return []
+
+ # HTTP status 300s mean redirection. 400s and 500s are errors.
+ # Technically 300s are not errors, but the use case here relies on "requests" to handle redirects automatically.
+ if backup_list_request.status_code >= 300:
+ Logger.log("w", "Could not get backups list from remote: %s", backup_list_request.text)
+ Message(catalog.i18nc("@info:backup_status", "There was an error listing your backups."), title = catalog.i18nc("@info:title", "Backup")).show()
+ return []
+
+ backup_list_response = backup_list_request.json()
+ if "data" not in backup_list_response:
+ Logger.log("w", "Could not get backups from remote, actual response body was: %s", str(backup_list_response))
+ return []
+
+ return backup_list_response["data"]
+
+ def createBackup(self) -> None:
+ self.creatingStateChanged.emit(is_creating = True)
+
+ # Create the backup.
+ backup_zip_file, backup_meta_data = self._cura_api.backups.createBackup()
+ if not backup_zip_file or not backup_meta_data:
+ self.creatingStateChanged.emit(is_creating = False, error_message ="Could not create backup.")
+ return
+
+ # Create an upload entry for the backup.
+ timestamp = datetime.now().isoformat()
+ backup_meta_data["description"] = "{}.backup.{}.cura.zip".format(timestamp, backup_meta_data["cura_release"])
+ backup_upload_url = self._requestBackupUpload(backup_meta_data, len(backup_zip_file))
+ if not backup_upload_url:
+ self.creatingStateChanged.emit(is_creating = False, error_message ="Could not upload backup.")
+ return
+
+ # Upload the backup to storage.
+ upload_backup_job = UploadBackupJob(backup_upload_url, backup_zip_file)
+ upload_backup_job.finished.connect(self._onUploadFinished)
+ upload_backup_job.start()
+
+ def _onUploadFinished(self, job: "UploadBackupJob") -> None:
+ if job.backup_upload_error_message != "":
+ # If the job contains an error message we pass it along so the UI can display it.
+ self.creatingStateChanged.emit(is_creating = False, error_message = job.backup_upload_error_message)
+ else:
+ self.creatingStateChanged.emit(is_creating = False)
+
+ def restoreBackup(self, backup: Dict[str, Any]) -> None:
+ self.restoringStateChanged.emit(is_restoring = True)
+ download_url = backup.get("download_url")
+ if not download_url:
+ # If there is no download URL, we can't restore the backup.
+ return self._emitRestoreError()
+
+ 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)
+ return self._emitRestoreError()
+
+ # We store the file in a temporary path fist to ensure integrity.
+ temporary_backup_file = NamedTemporaryFile(delete = False)
+ with open(temporary_backup_file.name, "wb") as write_backup:
+ for chunk in download_package:
+ write_backup.write(chunk)
+
+ if not self._verifyMd5Hash(temporary_backup_file.name, backup.get("md5_hash", "")):
+ # Don't restore the backup if the MD5 hashes do not match.
+ # This can happen if the download was interrupted.
+ Logger.log("w", "Remote and local MD5 hashes do not match, not restoring backup.")
+ return self._emitRestoreError()
+
+ # Tell Cura to place the backup back in the user data folder.
+ with open(temporary_backup_file.name, "rb") as read_backup:
+ self._cura_api.backups.restoreBackup(read_backup.read(), backup.get("metadata", {}))
+ self.restoringStateChanged.emit(is_restoring = False)
+
+ def _emitRestoreError(self) -> None:
+ self.restoringStateChanged.emit(is_restoring = False,
+ error_message = catalog.i18nc("@info:backup_status",
+ "There was an error trying to restore your backup."))
+
+ # Verify the MD5 hash of a file.
+ # \param file_path Full path to the file.
+ # \param known_hash The known MD5 hash of the file.
+ # \return: Success or not.
+ @staticmethod
+ def _verifyMd5Hash(file_path: str, known_hash: str) -> bool:
+ with open(file_path, "rb") as read_backup:
+ local_md5_hash = base64.b64encode(hashlib.md5(read_backup.read()).digest(), altchars = b"_-").decode("utf-8")
+ return known_hash == local_md5_hash
+
+ def deleteBackup(self, backup_id: str) -> bool:
+ access_token = self._cura_api.account.accessToken
+ if not access_token:
+ Logger.log("w", "Could not get access token.")
+ return False
+
+ 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
+ return True
+
+ # Request a backup upload slot from the API.
+ # \param backup_metadata: A dict containing some meta data about the backup.
+ # \param backup_size The size of the backup file in bytes.
+ # \return: The upload URL for the actual backup file if successful, otherwise None.
+ def _requestBackupUpload(self, backup_metadata: Dict[str, Any], backup_size: int) -> Optional[str]:
+ access_token = self._cura_api.account.accessToken
+ if not access_token:
+ Logger.log("w", "Could not get access token.")
+ return None
+ 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:
+ Logger.log("w", "Could not request backup upload: %s", backup_upload_request.text)
+ return None
+
+ return backup_upload_request.json()["data"]["upload_url"]
diff --git a/plugins/CuraDrive/src/DrivePluginExtension.py b/plugins/CuraDrive/src/DrivePluginExtension.py
new file mode 100644
index 0000000000..bcc326a133
--- /dev/null
+++ b/plugins/CuraDrive/src/DrivePluginExtension.py
@@ -0,0 +1,162 @@
+# Copyright (c) 2019 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+
+import os
+from datetime import datetime
+from typing import Any, cast, Dict, List, Optional
+
+from PyQt5.QtCore import QObject, pyqtSlot, pyqtProperty, pyqtSignal
+
+from UM.Extension import Extension
+from UM.Logger import Logger
+from UM.Message import Message
+from cura.CuraApplication import CuraApplication
+
+from .Settings import Settings
+from .DriveApiService import DriveApiService
+
+from UM.i18n import i18nCatalog
+catalog = i18nCatalog("cura")
+
+
+# The DivePluginExtension provides functionality to backup and restore your Cura configuration to Ultimaker's cloud.
+class DrivePluginExtension(QObject, Extension):
+
+ # Signal emitted when the list of backups changed.
+ backupsChanged = pyqtSignal()
+
+ # Signal emitted when restoring has started. Needed to prevent parallel restoring.
+ restoringStateChanged = pyqtSignal()
+
+ # Signal emitted when creating has started. Needed to prevent parallel creation of backups.
+ creatingStateChanged = pyqtSignal()
+
+ # Signal emitted when preferences changed (like auto-backup).
+ preferencesChanged = pyqtSignal()
+
+ DATE_FORMAT = "%d/%m/%Y %H:%M:%S"
+
+ def __init__(self) -> None:
+ QObject.__init__(self, None)
+ Extension.__init__(self)
+
+ # Local data caching for the UI.
+ self._drive_window = None # type: Optional[QObject]
+ self._backups = [] # type: List[Dict[str, Any]]
+ self._is_restoring_backup = False
+ self._is_creating_backup = False
+
+ # Initialize services.
+ preferences = CuraApplication.getInstance().getPreferences()
+ self._drive_api_service = DriveApiService()
+
+ # Attach signals.
+ CuraApplication.getInstance().getCuraAPI().account.loginStateChanged.connect(self._onLoginStateChanged)
+ self._drive_api_service.restoringStateChanged.connect(self._onRestoringStateChanged)
+ self._drive_api_service.creatingStateChanged.connect(self._onCreatingStateChanged)
+
+ # Register preferences.
+ preferences.addPreference(Settings.AUTO_BACKUP_ENABLED_PREFERENCE_KEY, False)
+ preferences.addPreference(Settings.AUTO_BACKUP_LAST_DATE_PREFERENCE_KEY,
+ datetime.now().strftime(self.DATE_FORMAT))
+
+ # Register the menu item
+ self.addMenuItem(catalog.i18nc("@item:inmenu", "Manage backups"), self.showDriveWindow)
+
+ # Make auto-backup on boot if required.
+ CuraApplication.getInstance().engineCreatedSignal.connect(self._autoBackup)
+
+ def showDriveWindow(self) -> None:
+ if not self._drive_window:
+ plugin_dir_path = cast(str, CuraApplication.getInstance().getPluginRegistry().getPluginPath(self.getPluginId())) # We know this plug-in exists because that's us, so this always returns str.
+ path = os.path.join(plugin_dir_path, "src", "qml", "main.qml")
+ self._drive_window = CuraApplication.getInstance().createQmlComponent(path, {"CuraDrive": self})
+ self.refreshBackups()
+ if self._drive_window:
+ self._drive_window.show()
+
+ def _autoBackup(self) -> None:
+ preferences = CuraApplication.getInstance().getPreferences()
+ if preferences.getValue(Settings.AUTO_BACKUP_ENABLED_PREFERENCE_KEY) and self._isLastBackupTooLongAgo():
+ self.createBackup()
+
+ def _isLastBackupTooLongAgo(self) -> bool:
+ current_date = datetime.now()
+ last_backup_date = self._getLastBackupDate()
+ date_diff = current_date - last_backup_date
+ return date_diff.days > 1
+
+ def _getLastBackupDate(self) -> "datetime":
+ preferences = CuraApplication.getInstance().getPreferences()
+ last_backup_date = preferences.getValue(Settings.AUTO_BACKUP_LAST_DATE_PREFERENCE_KEY)
+ return datetime.strptime(last_backup_date, self.DATE_FORMAT)
+
+ def _storeBackupDate(self) -> None:
+ backup_date = datetime.now().strftime(self.DATE_FORMAT)
+ preferences = CuraApplication.getInstance().getPreferences()
+ preferences.setValue(Settings.AUTO_BACKUP_LAST_DATE_PREFERENCE_KEY, backup_date)
+
+ def _onLoginStateChanged(self, logged_in: bool = False) -> None:
+ if logged_in:
+ self.refreshBackups()
+
+ def _onRestoringStateChanged(self, is_restoring: bool = False, error_message: str = None) -> None:
+ self._is_restoring_backup = is_restoring
+ self.restoringStateChanged.emit()
+ if error_message:
+ Message(error_message, title = catalog.i18nc("@info:title", "Backup")).show()
+
+ def _onCreatingStateChanged(self, is_creating: bool = False, error_message: str = None) -> None:
+ self._is_creating_backup = is_creating
+ self.creatingStateChanged.emit()
+ if error_message:
+ Message(error_message, title = catalog.i18nc("@info:title", "Backup")).show()
+ else:
+ self._storeBackupDate()
+ if not is_creating and not error_message:
+ # We've finished creating a new backup, to the list has to be updated.
+ self.refreshBackups()
+
+ @pyqtSlot(bool, name = "toggleAutoBackup")
+ def toggleAutoBackup(self, enabled: bool) -> None:
+ preferences = CuraApplication.getInstance().getPreferences()
+ preferences.setValue(Settings.AUTO_BACKUP_ENABLED_PREFERENCE_KEY, enabled)
+
+ @pyqtProperty(bool, notify = preferencesChanged)
+ def autoBackupEnabled(self) -> bool:
+ preferences = CuraApplication.getInstance().getPreferences()
+ return bool(preferences.getValue(Settings.AUTO_BACKUP_ENABLED_PREFERENCE_KEY))
+
+ @pyqtProperty("QVariantList", notify = backupsChanged)
+ def backups(self) -> List[Dict[str, Any]]:
+ return self._backups
+
+ @pyqtSlot(name = "refreshBackups")
+ def refreshBackups(self) -> None:
+ self._backups = self._drive_api_service.getBackups()
+ self.backupsChanged.emit()
+
+ @pyqtProperty(bool, notify = restoringStateChanged)
+ def isRestoringBackup(self) -> bool:
+ return self._is_restoring_backup
+
+ @pyqtProperty(bool, notify = creatingStateChanged)
+ def isCreatingBackup(self) -> bool:
+ return self._is_creating_backup
+
+ @pyqtSlot(str, name = "restoreBackup")
+ def restoreBackup(self, backup_id: str) -> None:
+ for backup in self._backups:
+ if backup.get("backup_id") == backup_id:
+ self._drive_api_service.restoreBackup(backup)
+ return
+ Logger.log("w", "Unable to find backup with the ID %s", backup_id)
+
+ @pyqtSlot(name = "createBackup")
+ def createBackup(self) -> None:
+ self._drive_api_service.createBackup()
+
+ @pyqtSlot(str, name = "deleteBackup")
+ def deleteBackup(self, backup_id: str) -> None:
+ self._drive_api_service.deleteBackup(backup_id)
+ self.refreshBackups()
diff --git a/plugins/CuraDrive/src/Settings.py b/plugins/CuraDrive/src/Settings.py
new file mode 100644
index 0000000000..abe64e0acd
--- /dev/null
+++ b/plugins/CuraDrive/src/Settings.py
@@ -0,0 +1,13 @@
+# Copyright (c) 2018 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+
+from cura import UltimakerCloudAuthentication
+
+
+class Settings:
+ # Keeps the plugin settings.
+ DRIVE_API_VERSION = 1
+ DRIVE_API_URL = "{}/cura-drive/v{}".format(UltimakerCloudAuthentication.CuraCloudAPIRoot, str(DRIVE_API_VERSION))
+
+ AUTO_BACKUP_ENABLED_PREFERENCE_KEY = "cura_drive/auto_backup_enabled"
+ AUTO_BACKUP_LAST_DATE_PREFERENCE_KEY = "cura_drive/auto_backup_date"
diff --git a/plugins/CuraDrive/src/UploadBackupJob.py b/plugins/CuraDrive/src/UploadBackupJob.py
new file mode 100644
index 0000000000..2e76ed9b4b
--- /dev/null
+++ b/plugins/CuraDrive/src/UploadBackupJob.py
@@ -0,0 +1,41 @@
+# Copyright (c) 2018 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+
+import requests
+
+from UM.Job import Job
+from UM.Logger import Logger
+from UM.Message import Message
+
+from UM.i18n import i18nCatalog
+catalog = i18nCatalog("cura")
+
+
+class UploadBackupJob(Job):
+ MESSAGE_TITLE = catalog.i18nc("@info:title", "Backups")
+
+ # This job is responsible for uploading the backup file to cloud storage.
+ # As it can take longer than some other tasks, we schedule this using a Cura Job.
+ def __init__(self, signed_upload_url: str, backup_zip: bytes) -> None:
+ super().__init__()
+ self._signed_upload_url = signed_upload_url
+ self._backup_zip = backup_zip
+ self._upload_success = False
+ self.backup_upload_error_message = ""
+
+ def run(self) -> None:
+ upload_message = Message(catalog.i18nc("@info:backup_status", "Uploading your backup..."), title = self.MESSAGE_TITLE, progress = -1)
+ upload_message.show()
+
+ backup_upload = requests.put(self._signed_upload_url, data = self._backup_zip)
+ upload_message.hide()
+
+ if backup_upload.status_code >= 300:
+ self.backup_upload_error_message = backup_upload.text
+ Logger.log("w", "Could not upload backup file: %s", backup_upload.text)
+ Message(catalog.i18nc("@info:backup_status", "There was an error while uploading your backup."), title = self.MESSAGE_TITLE).show()
+ else:
+ self._upload_success = True
+ Message(catalog.i18nc("@info:backup_status", "Your backup has finished uploading."), title = self.MESSAGE_TITLE).show()
+
+ self.finished.emit(self)
diff --git a/plugins/CuraDrive/src/__init__.py b/plugins/CuraDrive/src/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/plugins/CuraDrive/src/qml/components/BackupList.qml b/plugins/CuraDrive/src/qml/components/BackupList.qml
new file mode 100644
index 0000000000..a4a460a885
--- /dev/null
+++ b/plugins/CuraDrive/src/qml/components/BackupList.qml
@@ -0,0 +1,39 @@
+// 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.2
+import QtQuick.Layouts 1.3
+
+import UM 1.1 as UM
+
+ScrollView
+{
+ property alias model: backupList.model
+ width: parent.width
+ clip: true
+ ListView
+ {
+ id: backupList
+ width: parent.width
+ delegate: Item
+ {
+ // Add a margin, otherwise the scrollbar is on top of the right most component
+ width: parent.width - UM.Theme.getSize("default_margin").width
+ height: childrenRect.height
+
+ BackupListItem
+ {
+ id: backupListItem
+ width: parent.width
+ }
+
+ Rectangle
+ {
+ id: divider
+ color: UM.Theme.getColor("lining")
+ height: UM.Theme.getSize("default_lining").height
+ }
+ }
+ }
+}
diff --git a/plugins/CuraDrive/src/qml/components/BackupListFooter.qml b/plugins/CuraDrive/src/qml/components/BackupListFooter.qml
new file mode 100644
index 0000000000..8decdc5c27
--- /dev/null
+++ b/plugins/CuraDrive/src/qml/components/BackupListFooter.qml
@@ -0,0 +1,46 @@
+// 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.Layouts 1.3
+
+import UM 1.3 as UM
+import Cura 1.0 as Cura
+
+import "../components"
+
+RowLayout
+{
+ id: backupListFooter
+ width: parent.width
+ property bool showInfoButton: false
+
+ Cura.PrimaryButton
+ {
+ id: infoButton
+ text: catalog.i18nc("@button", "Want more?")
+ iconSource: UM.Theme.getIcon("info")
+ onClicked: Qt.openUrlExternally("https://goo.gl/forms/QACEP8pP3RV60QYG2")
+ visible: backupListFooter.showInfoButton
+ }
+
+ Cura.PrimaryButton
+ {
+ id: createBackupButton
+ text: catalog.i18nc("@button", "Backup Now")
+ iconSource: UM.Theme.getIcon("plus")
+ enabled: !CuraDrive.isCreatingBackup && !CuraDrive.isRestoringBackup
+ onClicked: CuraDrive.createBackup()
+ busy: CuraDrive.isCreatingBackup
+ }
+
+ Cura.CheckBoxWithTooltip
+ {
+ id: autoBackupEnabled
+ checked: CuraDrive.autoBackupEnabled
+ onClicked: CuraDrive.toggleAutoBackup(autoBackupEnabled.checked)
+ text: catalog.i18nc("@checkbox:description", "Auto Backup")
+ tooltip: catalog.i18nc("@checkbox:description", "Automatically create a backup each day that Cura is started.")
+ }
+}
diff --git a/plugins/CuraDrive/src/qml/components/BackupListItem.qml b/plugins/CuraDrive/src/qml/components/BackupListItem.qml
new file mode 100644
index 0000000000..5cdb500b4e
--- /dev/null
+++ b/plugins/CuraDrive/src/qml/components/BackupListItem.qml
@@ -0,0 +1,113 @@
+// 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.Layouts 1.3
+import QtQuick.Dialogs 1.1
+
+import UM 1.1 as UM
+import Cura 1.0 as Cura
+
+Item
+{
+ id: backupListItem
+ width: parent.width
+ height: showDetails ? dataRow.height + backupDetails.height : dataRow.height
+ property bool showDetails: false
+
+ // Backup details toggle animation.
+ Behavior on height
+ {
+ PropertyAnimation
+ {
+ duration: 70
+ }
+ }
+
+ RowLayout
+ {
+ id: dataRow
+ spacing: UM.Theme.getSize("wide_margin").width
+ width: parent.width
+ height: 50 * screenScaleFactor
+
+ UM.SimpleButton
+ {
+ width: UM.Theme.getSize("section_icon").width
+ height: UM.Theme.getSize("section_icon").height
+ color: UM.Theme.getColor("small_button_text")
+ hoverColor: UM.Theme.getColor("small_button_text_hover")
+ iconSource: UM.Theme.getIcon("info")
+ onClicked: backupListItem.showDetails = !backupListItem.showDetails
+ }
+
+ Label
+ {
+ text: new Date(modelData.generated_time).toLocaleString(UM.Preferences.getValue("general/language"))
+ color: UM.Theme.getColor("text")
+ elide: Text.ElideRight
+ Layout.minimumWidth: 100 * screenScaleFactor
+ Layout.maximumWidth: 500 * screenScaleFactor
+ Layout.fillWidth: true
+ font: UM.Theme.getFont("default")
+ renderType: Text.NativeRendering
+ }
+
+ Label
+ {
+ text: modelData.metadata.description
+ color: UM.Theme.getColor("text")
+ elide: Text.ElideRight
+ Layout.minimumWidth: 100 * screenScaleFactor
+ Layout.maximumWidth: 500 * screenScaleFactor
+ Layout.fillWidth: true
+ font: UM.Theme.getFont("default")
+ renderType: Text.NativeRendering
+ }
+
+ Cura.SecondaryButton
+ {
+ text: catalog.i18nc("@button", "Restore")
+ enabled: !CuraDrive.isCreatingBackup && !CuraDrive.isRestoringBackup
+ onClicked: confirmRestoreDialog.visible = true
+ }
+
+ UM.SimpleButton
+ {
+ width: UM.Theme.getSize("message_close").width
+ height: UM.Theme.getSize("message_close").height
+ color: UM.Theme.getColor("small_button_text")
+ hoverColor: UM.Theme.getColor("small_button_text_hover")
+ iconSource: UM.Theme.getIcon("cross1")
+ onClicked: confirmDeleteDialog.visible = true
+ }
+ }
+
+ BackupListItemDetails
+ {
+ id: backupDetails
+ backupDetailsData: modelData
+ width: parent.width
+ visible: parent.showDetails
+ anchors.top: dataRow.bottom
+ }
+
+ MessageDialog
+ {
+ id: confirmDeleteDialog
+ title: catalog.i18nc("@dialog:title", "Delete Backup")
+ text: catalog.i18nc("@dialog:info", "Are you sure you want to delete this backup? This cannot be undone.")
+ standardButtons: StandardButton.Yes | StandardButton.No
+ onYes: CuraDrive.deleteBackup(modelData.backup_id)
+ }
+
+ MessageDialog
+ {
+ id: confirmRestoreDialog
+ title: catalog.i18nc("@dialog:title", "Restore Backup")
+ text: catalog.i18nc("@dialog:info", "You will need to restart Cura before your backup is restored. Do you want to close Cura now?")
+ standardButtons: StandardButton.Yes | StandardButton.No
+ onYes: CuraDrive.restoreBackup(modelData.backup_id)
+ }
+}
diff --git a/plugins/CuraDrive/src/qml/components/BackupListItemDetails.qml b/plugins/CuraDrive/src/qml/components/BackupListItemDetails.qml
new file mode 100644
index 0000000000..4da15c6f16
--- /dev/null
+++ b/plugins/CuraDrive/src/qml/components/BackupListItemDetails.qml
@@ -0,0 +1,63 @@
+// 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.Layouts 1.3
+
+import UM 1.1 as UM
+
+ColumnLayout
+{
+ id: backupDetails
+ width: parent.width
+ spacing: UM.Theme.getSize("default_margin").width
+ property var backupDetailsData
+
+ // Cura version
+ BackupListItemDetailsRow
+ {
+ iconSource: UM.Theme.getIcon("application")
+ label: catalog.i18nc("@backuplist:label", "Cura Version")
+ value: backupDetailsData.metadata.cura_release
+ }
+
+ // Machine count.
+ BackupListItemDetailsRow
+ {
+ iconSource: UM.Theme.getIcon("printer_single")
+ label: catalog.i18nc("@backuplist:label", "Machines")
+ value: backupDetailsData.metadata.machine_count
+ }
+
+ // Material count
+ BackupListItemDetailsRow
+ {
+ iconSource: UM.Theme.getIcon("category_material")
+ label: catalog.i18nc("@backuplist:label", "Materials")
+ value: backupDetailsData.metadata.material_count
+ }
+
+ // Profile count.
+ BackupListItemDetailsRow
+ {
+ iconSource: UM.Theme.getIcon("settings")
+ label: catalog.i18nc("@backuplist:label", "Profiles")
+ value: backupDetailsData.metadata.profile_count
+ }
+
+ // Plugin count.
+ BackupListItemDetailsRow
+ {
+ iconSource: UM.Theme.getIcon("plugin")
+ label: catalog.i18nc("@backuplist:label", "Plugins")
+ value: backupDetailsData.metadata.plugin_count
+ }
+
+ // Spacer.
+ Item
+ {
+ width: parent.width
+ height: UM.Theme.getSize("default_margin").height
+ }
+}
diff --git a/plugins/CuraDrive/src/qml/components/BackupListItemDetailsRow.qml b/plugins/CuraDrive/src/qml/components/BackupListItemDetailsRow.qml
new file mode 100644
index 0000000000..9e4612fcf8
--- /dev/null
+++ b/plugins/CuraDrive/src/qml/components/BackupListItemDetailsRow.qml
@@ -0,0 +1,52 @@
+// 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.Layouts 1.3
+
+import UM 1.3 as UM
+
+RowLayout
+{
+ id: detailsRow
+ width: parent.width
+ height: 40 * screenScaleFactor
+
+ property alias iconSource: icon.source
+ property alias label: detailName.text
+ property alias value: detailValue.text
+
+ UM.RecolorImage
+ {
+ id: icon
+ width: 18 * screenScaleFactor
+ height: width
+ source: ""
+ color: UM.Theme.getColor("text")
+ }
+
+ Label
+ {
+ id: detailName
+ color: UM.Theme.getColor("text")
+ elide: Text.ElideRight
+ Layout.minimumWidth: 50 * screenScaleFactor
+ Layout.maximumWidth: 100 * screenScaleFactor
+ Layout.fillWidth: true
+ font: UM.Theme.getFont("default")
+ renderType: Text.NativeRendering
+ }
+
+ Label
+ {
+ id: detailValue
+ color: UM.Theme.getColor("text")
+ elide: Text.ElideRight
+ Layout.minimumWidth: 50 * screenScaleFactor
+ Layout.maximumWidth: 100 * screenScaleFactor
+ Layout.fillWidth: true
+ font: UM.Theme.getFont("default")
+ renderType: Text.NativeRendering
+ }
+}
diff --git a/plugins/CuraDrive/src/qml/images/icon.png b/plugins/CuraDrive/src/qml/images/icon.png
new file mode 100644
index 0000000000..3f75491786
Binary files /dev/null and b/plugins/CuraDrive/src/qml/images/icon.png differ
diff --git a/plugins/CuraDrive/src/qml/main.qml b/plugins/CuraDrive/src/qml/main.qml
new file mode 100644
index 0000000000..48bf3b6ea4
--- /dev/null
+++ b/plugins/CuraDrive/src/qml/main.qml
@@ -0,0 +1,44 @@
+// 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
+
+import "components"
+import "pages"
+
+Window
+{
+ id: curaDriveDialog
+ minimumWidth: Math.round(UM.Theme.getSize("modal_window_minimum").width)
+ minimumHeight: Math.round(UM.Theme.getSize("modal_window_minimum").height)
+ maximumWidth: Math.round(minimumWidth * 1.2)
+ maximumHeight: Math.round(minimumHeight * 1.2)
+ width: minimumWidth
+ height: minimumHeight
+ color: UM.Theme.getColor("main_background")
+ title: catalog.i18nc("@title:window", "Cura Backups")
+
+ // Globally available.
+ UM.I18nCatalog
+ {
+ id: catalog
+ name: "cura"
+ }
+
+ WelcomePage
+ {
+ id: welcomePage
+ visible: !Cura.API.account.isLoggedIn
+ }
+
+ BackupsPage
+ {
+ id: backupsPage
+ visible: Cura.API.account.isLoggedIn
+ }
+}
diff --git a/plugins/CuraDrive/src/qml/pages/BackupsPage.qml b/plugins/CuraDrive/src/qml/pages/BackupsPage.qml
new file mode 100644
index 0000000000..c337294744
--- /dev/null
+++ b/plugins/CuraDrive/src/qml/pages/BackupsPage.qml
@@ -0,0 +1,75 @@
+// 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.Layouts 1.3
+
+import UM 1.3 as UM
+import Cura 1.1 as Cura
+
+import "../components"
+
+Item
+{
+ id: backupsPage
+ anchors.fill: parent
+ anchors.margins: UM.Theme.getSize("wide_margin").width
+
+ ColumnLayout
+ {
+ spacing: UM.Theme.getSize("wide_margin").height
+ width: parent.width
+ anchors.fill: parent
+
+ Label
+ {
+ id: backupTitle
+ text: catalog.i18nc("@title", "My Backups")
+ font: UM.Theme.getFont("large")
+ color: UM.Theme.getColor("text")
+ Layout.fillWidth: true
+ renderType: Text.NativeRendering
+ }
+
+ Label
+ {
+ text: catalog.i18nc("@empty_state",
+ "You don't have any backups currently. Use the 'Backup Now' button to create one.")
+ width: parent.width
+ font: UM.Theme.getFont("default")
+ color: UM.Theme.getColor("text")
+ wrapMode: Label.WordWrap
+ visible: backupList.model.length == 0
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+ renderType: Text.NativeRendering
+ }
+
+ BackupList
+ {
+ id: backupList
+ model: CuraDrive.backups
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+ }
+
+ Label
+ {
+ text: catalog.i18nc("@backup_limit_info",
+ "During the preview phase, you'll be limited to 5 visible backups. Remove a backup to see older ones.")
+ width: parent.width
+ font: UM.Theme.getFont("default")
+ color: UM.Theme.getColor("text")
+ wrapMode: Label.WordWrap
+ visible: backupList.model.length > 4
+ renderType: Text.NativeRendering
+ }
+
+ BackupListFooter
+ {
+ id: backupListFooter
+ showInfoButton: backupList.model.length > 4
+ }
+ }
+}
diff --git a/plugins/CuraDrive/src/qml/pages/WelcomePage.qml b/plugins/CuraDrive/src/qml/pages/WelcomePage.qml
new file mode 100644
index 0000000000..0b207bc170
--- /dev/null
+++ b/plugins/CuraDrive/src/qml/pages/WelcomePage.qml
@@ -0,0 +1,56 @@
+// 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
+
+import "../components"
+
+
+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/icon.png"
+ anchors.horizontalCenter: parent.horizontalCenter
+ width: Math.round(parent.width / 4)
+ }
+
+ Label
+ {
+ id: welcomeTextLabel
+ text: catalog.i18nc("@description", "Backup and synchronize your Cura settings.")
+ 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/CuraEngineBackend/Cura.proto b/plugins/CuraEngineBackend/Cura.proto
index 292330576b..2eabe62366 100644
--- a/plugins/CuraEngineBackend/Cura.proto
+++ b/plugins/CuraEngineBackend/Cura.proto
@@ -29,7 +29,7 @@ message Object
bytes normals = 3; //An array of 3 floats.
bytes indices = 4; //An array of ints.
repeated Setting settings = 5; // Setting override per object, overruling the global settings.
- string name = 6;
+ string name = 6; //Mesh name
}
message Progress
@@ -58,6 +58,7 @@ message Polygon {
MoveCombingType = 8;
MoveRetractionType = 9;
SupportInterfaceType = 10;
+ PrimeTowerType = 11;
}
Type type = 1; // Type of move
bytes points = 2; // The points of the polygon, or two points if only a line segment (Currently only line segments are used)
@@ -108,8 +109,9 @@ message PrintTimeMaterialEstimates { // The print time for each feature and mate
float time_travel = 9;
float time_retract = 10;
float time_support_interface = 11;
+ float time_prime_tower = 12;
- repeated MaterialEstimates materialEstimates = 12; // materialEstimates data
+ repeated MaterialEstimates materialEstimates = 13; // materialEstimates data
}
message MaterialEstimates {
diff --git a/plugins/CuraEngineBackend/CuraEngineBackend.py b/plugins/CuraEngineBackend/CuraEngineBackend.py
index 58bc74f3f1..ae18e76e5a 100755
--- a/plugins/CuraEngineBackend/CuraEngineBackend.py
+++ b/plugins/CuraEngineBackend/CuraEngineBackend.py
@@ -15,14 +15,12 @@ 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
@@ -86,8 +84,8 @@ class CuraEngineBackend(QObject, Backend):
self._layer_view_active = False #type: bool
self._onActiveViewChanged()
- self._stored_layer_data = [] #type: List[Arcus.PythonMessage]
- self._stored_optimized_layer_data = {} #type: Dict[int, List[Arcus.PythonMessage]] # key is build plate number, then arrays are stored until they go to the ProcessSlicesLayersJob
+ self._stored_layer_data = [] # type: List[Arcus.PythonMessage]
+ self._stored_optimized_layer_data = {} # type: Dict[int, List[Arcus.PythonMessage]] # key is build plate number, then arrays are stored until they go to the ProcessSlicesLayersJob
self._scene = self._application.getController().getScene() #type: Scene
self._scene.sceneChanged.connect(self._onSceneChanged)
@@ -151,7 +149,7 @@ class CuraEngineBackend(QObject, Backend):
if self._multi_build_plate_model:
self._multi_build_plate_model.activeBuildPlateChanged.connect(self._onActiveViewChanged)
- self._application.globalContainerStackChanged.connect(self._onGlobalStackChanged)
+ self._application.getMachineManager().globalContainerChanged.connect(self._onGlobalStackChanged)
self._onGlobalStackChanged()
# extruder enable / disable. Actually wanted to use machine manager here, but the initialization order causes it to crash
@@ -203,13 +201,13 @@ class CuraEngineBackend(QObject, Backend):
@pyqtSlot()
def stopSlicing(self) -> None:
- self.backendStateChange.emit(BackendState.NotStarted)
+ self.setState(BackendState.NotStarted)
if self._slicing: # We were already slicing. Stop the old job.
self._terminate()
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
@@ -224,11 +222,12 @@ 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)
Logger.log("w", "Slice unnecessary, nothing has changed that needs reslicing.")
+ self.setState(BackendState.Done)
return
if self._process_layers_job:
@@ -245,7 +244,7 @@ class CuraEngineBackend(QObject, Backend):
num_objects = self._numObjectsPerBuildPlate()
self._stored_layer_data = []
- self._stored_optimized_layer_data[build_plate_to_be_sliced] = []
+
if build_plate_to_be_sliced not in num_objects or num_objects[build_plate_to_be_sliced] == 0:
self._scene.gcode_dict[build_plate_to_be_sliced] = [] #type: ignore #Because we created this attribute above.
@@ -253,7 +252,7 @@ class CuraEngineBackend(QObject, Backend):
if self._build_plates_to_be_sliced:
self.slice()
return
-
+ self._stored_optimized_layer_data[build_plate_to_be_sliced] = []
if self._application.getPrintInformation() and build_plate_to_be_sliced == active_build_plate:
self._application.getPrintInformation().setToZeroPrintInformation(build_plate_to_be_sliced)
@@ -322,7 +321,7 @@ class CuraEngineBackend(QObject, Backend):
self._start_slice_job = None
if job.isCancelled() or job.getError() or job.getResult() == StartJobResult.Error:
- self.backendStateChange.emit(BackendState.Error)
+ self.setState(BackendState.Error)
self.backendError.emit(job)
return
@@ -331,10 +330,10 @@ class CuraEngineBackend(QObject, Backend):
self._error_message = Message(catalog.i18nc("@info:status",
"Unable to slice with the current material as it is incompatible with the selected machine or configuration."), title = catalog.i18nc("@info:title", "Unable to slice"))
self._error_message.show()
- self.backendStateChange.emit(BackendState.Error)
+ self.setState(BackendState.Error)
self.backendError.emit(job)
else:
- self.backendStateChange.emit(BackendState.NotStarted)
+ self.setState(BackendState.NotStarted)
return
if job.getResult() == StartJobResult.SettingError:
@@ -362,15 +361,15 @@ class CuraEngineBackend(QObject, Backend):
self._error_message = Message(catalog.i18nc("@info:status", "Unable to slice with the current settings. The following settings have errors: {0}").format(", ".join(error_labels)),
title = catalog.i18nc("@info:title", "Unable to slice"))
self._error_message.show()
- self.backendStateChange.emit(BackendState.Error)
+ self.setState(BackendState.Error)
self.backendError.emit(job)
else:
- self.backendStateChange.emit(BackendState.NotStarted)
+ self.setState(BackendState.NotStarted)
return
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
@@ -386,7 +385,7 @@ class CuraEngineBackend(QObject, Backend):
self._error_message = Message(catalog.i18nc("@info:status", "Unable to slice due to some per-model settings. The following settings have errors on one or more models: {error_labels}").format(error_labels = ", ".join(errors.values())),
title = catalog.i18nc("@info:title", "Unable to slice"))
self._error_message.show()
- self.backendStateChange.emit(BackendState.Error)
+ self.setState(BackendState.Error)
self.backendError.emit(job)
return
@@ -395,28 +394,28 @@ class CuraEngineBackend(QObject, Backend):
self._error_message = Message(catalog.i18nc("@info:status", "Unable to slice because the prime tower or prime position(s) are invalid."),
title = catalog.i18nc("@info:title", "Unable to slice"))
self._error_message.show()
- self.backendStateChange.emit(BackendState.Error)
+ self.setState(BackendState.Error)
self.backendError.emit(job)
else:
- self.backendStateChange.emit(BackendState.NotStarted)
+ 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()),
title = catalog.i18nc("@info:title", "Unable to slice"))
self._error_message.show()
- self.backendStateChange.emit(BackendState.Error)
+ self.setState(BackendState.Error)
self.backendError.emit(job)
return
if job.getResult() == StartJobResult.NothingToSlice:
if self._application.platformActivity:
- self._error_message = Message(catalog.i18nc("@info:status", "Nothing to slice because none of the models fit the build volume. Please scale or rotate models to fit."),
+ self._error_message = Message(catalog.i18nc("@info:status", "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."),
title = catalog.i18nc("@info:title", "Unable to slice"))
self._error_message.show()
- self.backendStateChange.emit(BackendState.Error)
+ self.setState(BackendState.Error)
self.backendError.emit(job)
else:
- self.backendStateChange.emit(BackendState.NotStarted)
+ self.setState(BackendState.NotStarted)
self._invokeSlice()
return
@@ -424,7 +423,7 @@ class CuraEngineBackend(QObject, Backend):
self._socket.sendMessage(job.getSliceMessage())
# Notify the user that it's now up to the backend to do it's job
- self.backendStateChange.emit(BackendState.Processing)
+ self.setState(BackendState.Processing)
if self._slice_start_time:
Logger.log("d", "Sending slice message took %s seconds", time() - self._slice_start_time )
@@ -439,10 +438,10 @@ 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.backendStateChange.emit(BackendState.Disabled)
+ self.setState(BackendState.Disabled)
self._is_disabled = True
gcode_list = node.callDecoration("getGCodeList")
if gcode_list is not None:
@@ -451,7 +450,7 @@ class CuraEngineBackend(QObject, Backend):
if self._use_timer == enable_timer:
return self._use_timer
if enable_timer:
- self.backendStateChange.emit(BackendState.NotStarted)
+ self.setState(BackendState.NotStarted)
self.enableTimer()
return True
else:
@@ -461,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")
@@ -475,7 +474,7 @@ class CuraEngineBackend(QObject, Backend):
#
# \param source The scene node that was changed.
def _onSceneChanged(self, source: SceneNode) -> None:
- if not isinstance(source, SceneNode):
+ if not source.callDecoration("isSliceable"):
return
# This case checks if the source node is a node that contains GCode. In this case the
@@ -518,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.backendStateChange.emit(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()
@@ -552,10 +548,11 @@ class CuraEngineBackend(QObject, Backend):
# 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):
@@ -564,10 +561,10 @@ class CuraEngineBackend(QObject, Backend):
## Convenient function: mark everything to slice, emit state and clear layer data
def needsSlicing(self) -> None:
+ self.determineAutoSlicing()
self.stopSlicing()
self.markSliceAll()
self.processingProgress.emit(0.0)
- self.backendStateChange.emit(BackendState.NotStarted)
if not self._use_timer:
# With manually having to slice, we want to clear the old invalid layer data.
self._clearLayerData()
@@ -613,7 +610,7 @@ class CuraEngineBackend(QObject, Backend):
# \param message The protobuf message containing the slicing progress.
def _onProgressMessage(self, message: Arcus.PythonMessage) -> None:
self.processingProgress.emit(message.amount)
- self.backendStateChange.emit(BackendState.Processing)
+ self.setState(BackendState.Processing)
def _invokeSlice(self) -> None:
if self._use_timer:
@@ -632,7 +629,7 @@ class CuraEngineBackend(QObject, Backend):
#
# \param message The protobuf message signalling that slicing is finished.
def _onSlicingFinishedMessage(self, message: Arcus.PythonMessage) -> None:
- self.backendStateChange.emit(BackendState.Done)
+ 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.
@@ -736,6 +733,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
@@ -820,7 +818,7 @@ class CuraEngineBackend(QObject, Backend):
extruder.propertyChanged.disconnect(self._onSettingChanged)
extruder.containersChanged.disconnect(self._onChanged)
- self._global_container_stack = self._application.getGlobalContainerStack()
+ self._global_container_stack = self._application.getMachineManager().activeMachine
if self._global_container_stack:
self._global_container_stack.propertyChanged.connect(self._onSettingChanged) # Note: Only starts slicing when the value changed.
@@ -832,7 +830,10 @@ class CuraEngineBackend(QObject, Backend):
self._onChanged()
def _onProcessLayersFinished(self, job: ProcessSlicedLayersJob) -> None:
- del self._stored_optimized_layer_data[job.getBuildPlate()]
+ if job.getBuildPlate() in self._stored_optimized_layer_data:
+ del self._stored_optimized_layer_data[job.getBuildPlate()]
+ else:
+ Logger.log("w", "The optimized layer data was already deleted for buildplate %s", job.getBuildPlate())
self._process_layers_job = None
Logger.log("d", "See if there is more to slice(2)...")
self._invokeSlice()
diff --git a/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py b/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py
index 594bf3a43e..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,22 +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.
@@ -193,9 +194,9 @@ 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")) # Get the position
+ position = int(extruder.getMetaDataEntry("position", default = "0"))
try:
default_color = ExtrudersModel.defaultColors[position]
except IndexError:
@@ -205,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 79b1e5249c..b973a0775a 100644
--- a/plugins/CuraEngineBackend/StartSliceJob.py
+++ b/plugins/CuraEngineBackend/StartSliceJob.py
@@ -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.
@@ -66,11 +67,19 @@ class GcodeStartEndFormatter(Formatter):
return "{" + key + "}"
key = key_fragments[0]
- try:
- return kwargs[str(extruder_nr)][key]
- except KeyError:
+
+ default_value_str = "{" + key + "}"
+ 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"]
+ if str(extruder_nr) in kwargs and key in kwargs[str(extruder_nr)]:
+ value = kwargs[str(extruder_nr)][key]
+
+ if value == default_value_str:
Logger.log("w", "Unable to replace '%s' placeholder in start/end g-code", key)
- return "{" + key + "}"
+
+ return value
## Job class that builds up the message of scene data to send to CuraEngine.
@@ -99,7 +108,7 @@ class StartSliceJob(Job):
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()
@@ -125,6 +134,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:
@@ -142,7 +159,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
@@ -152,15 +169,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.
@@ -175,7 +193,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:
@@ -186,12 +205,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:
@@ -205,7 +222,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()
@@ -251,18 +268,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]
@@ -286,7 +304,7 @@ class StartSliceJob(Job):
obj.vertices = flat_verts
- self._handlePerObjectSettings(object, obj)
+ self._handlePerObjectSettings(cast(CuraSceneNode, object), obj)
Job.yieldThread()
@@ -318,6 +336,7 @@ class StartSliceJob(Job):
result["print_bed_temperature"] = result["material_bed_temperature"] # Renamed settings.
result["print_temperature"] = result["material_print_temperature"]
+ result["travel_speed"] = result["speed_travel"]
result["time"] = time.strftime("%H:%M:%S") #Some extra settings.
result["date"] = time.strftime("%d-%m-%Y")
result["day"] = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"][int(time.strftime("%w"))]
@@ -328,25 +347,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))
@@ -358,8 +381,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", "")
@@ -383,7 +412,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 111698d8d1..28f0e294e7 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": 5,
- "version": "1.0.0",
+ "api": "6.0",
+ "version": "1.0.1",
"i18n-catalog": "cura"
}
diff --git a/plugins/CuraProfileReader/CuraProfileReader.py b/plugins/CuraProfileReader/CuraProfileReader.py
index 11e58dac6d..92f2c31a8c 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 typing import List, Optional, Tuple
from UM.PluginRegistry import PluginRegistry
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.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,23 +68,24 @@ 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
@@ -88,21 +96,31 @@ class CuraProfileReader(ProfileReader):
## 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 66a2a6a56b..169fb43360 100644
--- a/plugins/CuraProfileReader/plugin.json
+++ b/plugins/CuraProfileReader/plugin.json
@@ -1,8 +1,8 @@
{
"name": "Cura Profile Reader",
"author": "Ultimaker B.V.",
- "version": "1.0.0",
+ "version": "1.0.1",
"description": "Provides support for importing Cura profiles.",
- "api": 5,
+ "api": "6.0",
"i18n-catalog": "cura"
}
diff --git a/plugins/CuraProfileWriter/plugin.json b/plugins/CuraProfileWriter/plugin.json
index 16c8c34152..9627c754d7 100644
--- a/plugins/CuraProfileWriter/plugin.json
+++ b/plugins/CuraProfileWriter/plugin.json
@@ -1,8 +1,8 @@
{
"name": "Cura Profile Writer",
"author": "Ultimaker B.V.",
- "version": "1.0.0",
+ "version": "1.0.1",
"description": "Provides support for exporting Cura profiles.",
- "api": 5,
+ "api": "6.0",
"i18n-catalog":"cura"
}
diff --git a/plugins/FirmwareUpdateChecker/FirmwareUpdateChecker.py b/plugins/FirmwareUpdateChecker/FirmwareUpdateChecker.py
index f01e8cb276..9c4d498d7e 100644
--- a/plugins/FirmwareUpdateChecker/FirmwareUpdateChecker.py
+++ b/plugins/FirmwareUpdateChecker/FirmwareUpdateChecker.py
@@ -1,18 +1,19 @@
-# Copyright (c) 2017 Ultimaker B.V.
+# Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
from PyQt5.QtCore import QUrl
from PyQt5.QtGui import QDesktopServices
+from typing import Set
+
from UM.Extension import Extension
from UM.Application import Application
from UM.Logger import Logger
from UM.i18n import i18nCatalog
from UM.Settings.ContainerRegistry import ContainerRegistry
-from cura.Settings.GlobalStack import GlobalStack
-
from .FirmwareUpdateCheckerJob import FirmwareUpdateCheckerJob
+from .FirmwareUpdateCheckerMessage import FirmwareUpdateCheckerMessage
i18n_catalog = i18nCatalog("cura")
@@ -21,35 +22,35 @@ i18n_catalog = i18nCatalog("cura")
# The plugin is currently only usable for applications maintained by Ultimaker. But it should be relatively easy
# to change it to work for other applications.
class FirmwareUpdateChecker(Extension):
- JEDI_VERSION_URL = "http://software.ultimaker.com/jedi/releases/latest.version?utm_source=cura&utm_medium=software&utm_campaign=resources"
- def __init__(self):
+ def __init__(self) -> None:
super().__init__()
- # Initialize the Preference called `latest_checked_firmware` that stores the last version
- # checked for the UM3. In the future if we need to check other printers' firmware
- Application.getInstance().getPreferences().addPreference("info/latest_checked_firmware", "")
-
# Listen to a Signal that indicates a change in the list of printers, just if the user has enabled the
- # 'check for updates' option
+ # "check for updates" option
Application.getInstance().getPreferences().addPreference("info/automatic_update_check", True)
if Application.getInstance().getPreferences().getValue("info/automatic_update_check"):
ContainerRegistry.getInstance().containerAdded.connect(self._onContainerAdded)
- self._download_url = None
self._check_job = None
+ self._checked_printer_names = set() # type: Set[str]
## Callback for the message that is spawned when there is a new version.
def _onActionTriggered(self, message, action):
- if action == "download":
- if self._download_url is not None:
- QDesktopServices.openUrl(QUrl(self._download_url))
-
- def _onSetDownloadUrl(self, download_url):
- self._download_url = download_url
+ if action == FirmwareUpdateCheckerMessage.STR_ACTION_DOWNLOAD:
+ machine_id = message.getMachineId()
+ download_url = message.getDownloadUrl()
+ if download_url is not None:
+ if QDesktopServices.openUrl(QUrl(download_url)):
+ Logger.log("i", "Redirected browser to {0} to show newly available firmware.".format(download_url))
+ else:
+ Logger.log("e", "Can't reach URL: {0}".format(download_url))
+ else:
+ Logger.log("e", "Can't find URL for {0}".format(machine_id))
def _onContainerAdded(self, container):
# Only take care when a new GlobalStack was added
+ from cura.Settings.GlobalStack import GlobalStack # otherwise circular imports
if isinstance(container, GlobalStack):
self.checkFirmwareVersion(container, True)
@@ -63,13 +64,18 @@ class FirmwareUpdateChecker(Extension):
# \param silent type(boolean) Suppresses messages other than "new version found" messages.
# This is used when checking for a new firmware version at startup.
def checkFirmwareVersion(self, container = None, silent = False):
- # Do not run multiple check jobs in parallel
- if self._check_job is not None:
- Logger.log("i", "A firmware update check is already running, do nothing.")
+ container_name = container.definition.getName()
+ if container_name in self._checked_printer_names:
+ return
+ self._checked_printer_names.add(container_name)
+
+ metadata = container.definition.getMetaData().get("firmware_update_info")
+ if metadata is None:
+ Logger.log("i", "No machine with name {0} in list of firmware to check.".format(container_name))
return
- self._check_job = FirmwareUpdateCheckerJob(container = container, silent = silent, url = self.JEDI_VERSION_URL,
- callback = self._onActionTriggered,
- set_download_url_callback = self._onSetDownloadUrl)
+ self._check_job = FirmwareUpdateCheckerJob(silent = silent,
+ machine_name = container_name, metadata = metadata,
+ callback = self._onActionTriggered)
self._check_job.start()
self._check_job.finished.connect(self._onJobFinished)
diff --git a/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py b/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py
index eadacf2c02..ad10a4f075 100644
--- a/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py
+++ b/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py
@@ -1,13 +1,18 @@
-# Copyright (c) 2017 Ultimaker B.V.
+# Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
from UM.Application import Application
from UM.Message import Message
from UM.Logger import Logger
from UM.Job import Job
+from UM.Version import Version
import urllib.request
-import codecs
+from urllib.error import URLError
+from typing import Dict, Optional
+
+from .FirmwareUpdateCheckerLookup import FirmwareUpdateCheckerLookup, getSettingsKeyForMachine
+from .FirmwareUpdateCheckerMessage import FirmwareUpdateCheckerMessage
from UM.i18n import i18nCatalog
i18n_catalog = i18nCatalog("cura")
@@ -15,75 +20,97 @@ i18n_catalog = i18nCatalog("cura")
## This job checks if there is an update available on the provided URL.
class FirmwareUpdateCheckerJob(Job):
- def __init__(self, container = None, silent = False, url = None, callback = None, set_download_url_callback = None):
- super().__init__()
- self._container = container
- self.silent = silent
- self._url = url
- self._callback = callback
- self._set_download_url_callback = set_download_url_callback
+ STRING_ZERO_VERSION = "0.0.0"
+ STRING_EPSILON_VERSION = "0.0.1"
+ ZERO_VERSION = Version(STRING_ZERO_VERSION)
+ EPSILON_VERSION = Version(STRING_EPSILON_VERSION)
- def run(self):
- if not self._url:
- Logger.log("e", "Can not check for a new release. URL not set!")
- return
+ def __init__(self, silent, machine_name, metadata, callback) -> None:
+ super().__init__()
+ self.silent = silent
+ self._callback = callback
+
+ self._machine_name = machine_name
+ self._metadata = metadata
+ self._lookups = FirmwareUpdateCheckerLookup(self._machine_name, self._metadata)
+ self._headers = {} # type:Dict[str, str] # Don't set headers yet.
+
+ def getUrlResponse(self, url: str) -> str:
+ result = self.STRING_ZERO_VERSION
try:
- application_name = Application.getInstance().getApplicationName()
- headers = {"User-Agent": "%s - %s" % (application_name, Application.getInstance().getVersion())}
- request = urllib.request.Request(self._url, headers = headers)
- current_version_file = urllib.request.urlopen(request)
- reader = codecs.getreader("utf-8")
+ request = urllib.request.Request(url, headers = self._headers)
+ response = urllib.request.urlopen(request)
+ result = response.read().decode("utf-8")
+ except URLError:
+ Logger.log("w", "Could not reach '{0}', if this URL is old, consider removal.".format(url))
+ return result
- # get machine name from the definition container
- machine_name = self._container.definition.getName()
- machine_name_parts = machine_name.lower().split(" ")
+ def parseVersionResponse(self, response: str) -> Version:
+ raw_str = response.split("\n", 1)[0].rstrip()
+ return Version(raw_str)
+
+ def getCurrentVersion(self) -> Version:
+ max_version = self.ZERO_VERSION
+ if self._lookups is None:
+ return max_version
+
+ machine_urls = self._lookups.getCheckUrls()
+ if machine_urls is not None:
+ for url in machine_urls:
+ version = self.parseVersionResponse(self.getUrlResponse(url))
+ if version > max_version:
+ max_version = version
+
+ if max_version < self.EPSILON_VERSION:
+ Logger.log("w", "MachineID {0} not handled!".format(self._lookups.getMachineName()))
+
+ return max_version
+
+ def run(self):
+ try:
+ # Initialize a Preference that stores the last version checked for this printer.
+ Application.getInstance().getPreferences().addPreference(
+ getSettingsKeyForMachine(self._lookups.getMachineId()), "")
+
+ # Get headers
+ application_name = Application.getInstance().getApplicationName()
+ application_version = Application.getInstance().getVersion()
+ self._headers = {"User-Agent": "%s - %s" % (application_name, application_version)}
# If it is not None, then we compare between the checked_version and the current_version
- # Now we just do that if the active printer is Ultimaker 3 or Ultimaker 3 Extended or any
- # other Ultimaker 3 that will come in the future
- if len(machine_name_parts) >= 2 and machine_name_parts[:2] == ["ultimaker", "3"]:
- Logger.log("i", "You have a UM3 in printer list. Let's check the firmware!")
+ machine_id = self._lookups.getMachineId()
+ if machine_id is not None:
+ Logger.log("i", "You have a(n) {0} in the printer list. Do firmware-check.".format(self._machine_name))
- # Nothing to parse, just get the string
- # TODO: In the future may be done by parsing a JSON file with diferent version for each printer model
- current_version = reader(current_version_file).readline().rstrip()
+ current_version = self.getCurrentVersion()
- # If it is the first time the version is checked, the checked_version is ''
- checked_version = Application.getInstance().getPreferences().getValue("info/latest_checked_firmware")
+ # This case indicates that was an error checking the version.
+ # It happens for instance when not connected to internet.
+ if current_version == self.ZERO_VERSION:
+ return
- # If the checked_version is '', it's because is the first time we check firmware and in this case
+ # If it is the first time the version is checked, the checked_version is ""
+ setting_key_str = getSettingsKeyForMachine(machine_id)
+ checked_version = Version(Application.getInstance().getPreferences().getValue(setting_key_str))
+
+ # If the checked_version is "", it's because is the first time we check firmware and in this case
# we will not show the notification, but we will store it for the next time
- Application.getInstance().getPreferences().setValue("info/latest_checked_firmware", current_version)
- Logger.log("i", "Reading firmware version of %s: checked = %s - latest = %s", machine_name, checked_version, current_version)
+ Application.getInstance().getPreferences().setValue(setting_key_str, current_version)
+ Logger.log("i", "Reading firmware version of %s: checked = %s - latest = %s",
+ self._machine_name, checked_version, current_version)
# The first time we want to store the current version, the notification will not be shown,
# 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")
-
- message = Message(i18n_catalog.i18nc(
- "@info Don't translate {machine_name}, since it gets replaced by a printer name!",
- "New features are available for your {machine_name}! It is recommended to update the firmware on your printer.").format(
- machine_name=machine_name),
- title=i18n_catalog.i18nc(
- "@info:title The %s gets replaced with the printer name.",
- "New %s firmware available") % machine_name)
-
- message.addAction("download",
- i18n_catalog.i18nc("@action:button", "How to update"),
- "[no_icon]",
- "[no_description]",
- button_style=Message.ActionButtonStyle.LINK,
- button_align=Message.ActionButtonStyle.BUTTON_ALIGN_LEFT)
-
-
- # If we do this in a cool way, the download url should be available in the JSON file
- if self._set_download_url_callback:
- self._set_download_url_callback("https://ultimaker.com/en/resources/20500-upgrade-firmware")
+ Logger.log("i", "Showing firmware update message for new version: {version}".format(current_version))
+ message = FirmwareUpdateCheckerMessage(machine_id, self._machine_name,
+ self._lookups.getRedirectUserUrl())
message.actionTriggered.connect(self._callback)
message.show()
+ else:
+ 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)
diff --git a/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerLookup.py b/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerLookup.py
new file mode 100644
index 0000000000..c78e6f6025
--- /dev/null
+++ b/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerLookup.py
@@ -0,0 +1,35 @@
+# Copyright (c) 2018 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+
+from typing import List, Optional
+
+from UM.i18n import i18nCatalog
+i18n_catalog = i18nCatalog("cura")
+
+
+def getSettingsKeyForMachine(machine_id: int) -> str:
+ return "info/latest_checked_firmware_for_{0}".format(machine_id)
+
+
+class FirmwareUpdateCheckerLookup:
+
+ def __init__(self, machine_name, machine_json) -> None:
+ # Parse all the needed lookup-tables from the ".json" file(s) in the resources folder.
+ self._machine_id = machine_json.get("id")
+ self._machine_name = machine_name.lower() # Lower in-case upper-case chars are added to the original json.
+ self._check_urls = [] # type:List[str]
+ for check_url in machine_json.get("check_urls", []):
+ self._check_urls.append(check_url)
+ self._redirect_user = machine_json.get("update_url")
+
+ def getMachineId(self) -> Optional[int]:
+ return self._machine_id
+
+ def getMachineName(self) -> Optional[int]:
+ return self._machine_name
+
+ def getCheckUrls(self) -> Optional[List[str]]:
+ return self._check_urls
+
+ def getRedirectUserUrl(self) -> Optional[str]:
+ return self._redirect_user
diff --git a/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerMessage.py b/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerMessage.py
new file mode 100644
index 0000000000..58c00850cb
--- /dev/null
+++ b/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerMessage.py
@@ -0,0 +1,37 @@
+# Copyright (c) 2018 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+
+from UM.i18n import i18nCatalog
+from UM.Message import Message
+
+i18n_catalog = i18nCatalog("cura")
+
+
+# Make a separate class, since we need an extra field: The machine-id that this message is about.
+class FirmwareUpdateCheckerMessage(Message):
+ STR_ACTION_DOWNLOAD = "download"
+
+ def __init__(self, machine_id: int, machine_name: str, download_url: str) -> None:
+ super().__init__(i18n_catalog.i18nc(
+ "@info Don't translate {machine_name}, since it gets replaced by a printer name!",
+ "New features are available for your {machine_name}! It is recommended to update the firmware on your printer.").format(
+ machine_name = machine_name),
+ title = i18n_catalog.i18nc(
+ "@info:title The %s gets replaced with the printer name.",
+ "New %s firmware available") % machine_name)
+
+ self._machine_id = machine_id
+ self._download_url = download_url
+
+ self.addAction(self.STR_ACTION_DOWNLOAD,
+ i18n_catalog.i18nc("@action:button", "How to update"),
+ "[no_icon]",
+ "[no_description]",
+ button_style = Message.ActionButtonStyle.LINK,
+ button_align = Message.ActionButtonAlignment.ALIGN_LEFT)
+
+ def getMachineId(self) -> int:
+ return self._machine_id
+
+ def getDownloadUrl(self) -> str:
+ return self._download_url
diff --git a/plugins/FirmwareUpdateChecker/plugin.json b/plugins/FirmwareUpdateChecker/plugin.json
index cbbd41e420..6c55d77fd8 100644
--- a/plugins/FirmwareUpdateChecker/plugin.json
+++ b/plugins/FirmwareUpdateChecker/plugin.json
@@ -1,8 +1,8 @@
{
"name": "Firmware Update Checker",
"author": "Ultimaker B.V.",
- "version": "1.0.0",
+ "version": "1.0.1",
"description": "Checks for firmware updates.",
- "api": 5,
+ "api": "6.0",
"i18n-catalog": "cura"
}
diff --git a/plugins/FirmwareUpdateChecker/tests/TestFirmwareUpdateChecker.py b/plugins/FirmwareUpdateChecker/tests/TestFirmwareUpdateChecker.py
new file mode 100644
index 0000000000..cf61e46d29
--- /dev/null
+++ b/plugins/FirmwareUpdateChecker/tests/TestFirmwareUpdateChecker.py
@@ -0,0 +1,62 @@
+# Copyright (c) 2018 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+
+import pytest
+
+from unittest.mock import MagicMock
+
+from UM.Version import Version
+
+import FirmwareUpdateChecker
+
+json_data = \
+ {
+ "ned":
+ {
+ "id": 1,
+ "name": "ned",
+ "check_urls": [""],
+ "update_url": "https://ultimaker.com/en/resources/20500-upgrade-firmware",
+ "version_parser": "default"
+ },
+ "olivia":
+ {
+ "id": 3,
+ "name": "olivia",
+ "check_urls": [""],
+ "update_url": "https://ultimaker.com/en/resources/20500-upgrade-firmware",
+ "version_parser": "default"
+ },
+ "emmerson":
+ {
+ "id": 5,
+ "name": "emmerson",
+ "check_urls": [""],
+ "update_url": "https://ultimaker.com/en/resources/20500-upgrade-firmware",
+ "version_parser": "default"
+ }
+ }
+
+@pytest.mark.parametrize("name, id", [
+ ("ned" , 1),
+ ("olivia" , 3),
+ ("emmerson", 5),
+])
+def test_FirmwareUpdateCheckerLookup(id, name):
+ lookup = FirmwareUpdateChecker.FirmwareUpdateCheckerLookup.FirmwareUpdateCheckerLookup(name, json_data.get(name))
+
+ assert lookup.getMachineName() == name
+ assert lookup.getMachineId() == id
+ assert len(lookup.getCheckUrls()) >= 1
+ assert lookup.getRedirectUserUrl() is not None
+
+@pytest.mark.parametrize("name, version", [
+ ("ned" , Version("5.1.2.3")),
+ ("olivia" , Version("4.3.2.1")),
+ ("emmerson", Version("6.7.8.1")),
+])
+def test_FirmwareUpdateCheckerJob_getCurrentVersion(name, version):
+ machine_data = json_data.get(name)
+ job = FirmwareUpdateChecker.FirmwareUpdateCheckerJob.FirmwareUpdateCheckerJob(False, name, machine_data, MagicMock)
+ job.getUrlResponse = MagicMock(return_value = str(version)) # Pretend like we got a good response from the server
+ assert job.getCurrentVersion() == version
diff --git a/plugins/FirmwareUpdateChecker/tests/__init__.py b/plugins/FirmwareUpdateChecker/tests/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.py b/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.py
new file mode 100644
index 0000000000..e2b0041674
--- /dev/null
+++ b/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.py
@@ -0,0 +1,69 @@
+# Copyright (c) 2018 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+
+from cura.CuraApplication import CuraApplication
+from UM.Settings.DefinitionContainer import DefinitionContainer
+from cura.MachineAction import MachineAction
+from UM.i18n import i18nCatalog
+from UM.Settings.ContainerRegistry import ContainerRegistry
+from cura.PrinterOutput.FirmwareUpdater import FirmwareUpdateState
+
+from PyQt5.QtCore import pyqtSignal, pyqtProperty, QObject
+from typing import Optional
+
+MYPY = False
+if MYPY:
+ from cura.PrinterOutput.FirmwareUpdater import FirmwareUpdater
+ from cura.PrinterOutput.PrinterOutputDevice import PrinterOutputDevice
+ from UM.Settings.ContainerInterface import ContainerInterface
+
+catalog = i18nCatalog("cura")
+
+## Upgrade the firmware of a machine by USB with this action.
+class FirmwareUpdaterMachineAction(MachineAction):
+ def __init__(self) -> None:
+ super().__init__("UpgradeFirmware", catalog.i18nc("@action", "Update Firmware"))
+ self._qml_url = "FirmwareUpdaterMachineAction.qml"
+ ContainerRegistry.getInstance().containerAdded.connect(self._onContainerAdded)
+
+ self._active_output_device = None # type: Optional[PrinterOutputDevice]
+ self._active_firmware_updater = None # type: Optional[FirmwareUpdater]
+
+ CuraApplication.getInstance().engineCreatedSignal.connect(self._onEngineCreated)
+
+ def _onEngineCreated(self) -> None:
+ CuraApplication.getInstance().getMachineManager().outputDevicesChanged.connect(self._onOutputDevicesChanged)
+
+ def _onContainerAdded(self, container: "ContainerInterface") -> None:
+ # Add this action as a supported action to all machine definitions if they support USB connection
+ if isinstance(container, DefinitionContainer) and container.getMetaDataEntry("type") == "machine" and container.getMetaDataEntry("supports_usb_connection"):
+ CuraApplication.getInstance().getMachineActionManager().addSupportedAction(container.getId(), self.getKey())
+
+ def _onOutputDevicesChanged(self) -> None:
+ if self._active_output_device and self._active_output_device.activePrinter:
+ self._active_output_device.activePrinter.getController().canUpdateFirmwareChanged.disconnect(self._onControllerCanUpdateFirmwareChanged)
+
+ output_devices = CuraApplication.getInstance().getMachineManager().printerOutputDevices
+ self._active_output_device = output_devices[0] if output_devices else None
+
+ if self._active_output_device and self._active_output_device.activePrinter:
+ self._active_output_device.activePrinter.getController().canUpdateFirmwareChanged.connect(self._onControllerCanUpdateFirmwareChanged)
+
+ self.outputDeviceCanUpdateFirmwareChanged.emit()
+
+ def _onControllerCanUpdateFirmwareChanged(self) -> None:
+ self.outputDeviceCanUpdateFirmwareChanged.emit()
+
+ outputDeviceCanUpdateFirmwareChanged = pyqtSignal()
+ @pyqtProperty(QObject, notify = outputDeviceCanUpdateFirmwareChanged)
+ def firmwareUpdater(self) -> Optional["FirmwareUpdater"]:
+ if self._active_output_device and self._active_output_device.activePrinter and self._active_output_device.activePrinter.getController() is not None and self._active_output_device.activePrinter.getController().can_update_firmware:
+ self._active_firmware_updater = self._active_output_device.getFirmwareUpdater()
+ return self._active_firmware_updater
+
+ elif self._active_firmware_updater and self._active_firmware_updater.firmwareUpdateState not in [FirmwareUpdateState.idle, FirmwareUpdateState.completed]:
+ # During a firmware update, the PrinterOutputDevice is disconnected but the FirmwareUpdater is still there
+ return self._active_firmware_updater
+
+ self._active_firmware_updater = None
+ return None
diff --git a/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml b/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml
new file mode 100644
index 0000000000..b5b6c15f50
--- /dev/null
+++ b/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml
@@ -0,0 +1,191 @@
+// 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 QtQuick.Dialogs 1.2 // For filedialog
+
+import UM 1.2 as UM
+import Cura 1.0 as Cura
+
+
+Cura.MachineAction
+{
+ anchors.fill: parent;
+ property bool printerConnected: Cura.MachineManager.printerConnected
+ property var activeOutputDevice: printerConnected ? Cura.MachineManager.printerOutputDevices[0] : null
+ property bool canUpdateFirmware: activeOutputDevice ? activeOutputDevice.activePrinter.canUpdateFirmware : false
+
+ Column
+ {
+ id: firmwareUpdaterMachineAction
+ anchors.fill: parent;
+ UM.I18nCatalog { id: catalog; name: "cura"}
+ spacing: UM.Theme.getSize("default_margin").height
+
+ Label
+ {
+ width: parent.width
+ text: catalog.i18nc("@title", "Update Firmware")
+ wrapMode: Text.WordWrap
+ font.pointSize: 18
+ }
+ Label
+ {
+ width: parent.width
+ wrapMode: Text.WordWrap
+ text: catalog.i18nc("@label", "Firmware is the piece of software running directly on your 3D printer. This firmware controls the step motors, regulates the temperature and ultimately makes your printer work.")
+ }
+
+ Label
+ {
+ width: parent.width
+ wrapMode: Text.WordWrap
+ text: catalog.i18nc("@label", "The firmware shipping with new printers works, but new versions tend to have more features and improvements.");
+ }
+
+ Row
+ {
+ anchors.horizontalCenter: parent.horizontalCenter
+ width: childrenRect.width
+ spacing: UM.Theme.getSize("default_margin").width
+ property string firmwareName: Cura.MachineManager.activeMachine.getDefaultFirmwareName()
+ Button
+ {
+ id: autoUpgradeButton
+ text: catalog.i18nc("@action:button", "Automatically upgrade Firmware");
+ enabled: parent.firmwareName != "" && canUpdateFirmware
+ onClicked:
+ {
+ updateProgressDialog.visible = true;
+ activeOutputDevice.updateFirmware(parent.firmwareName);
+ }
+ }
+ Button
+ {
+ id: manualUpgradeButton
+ text: catalog.i18nc("@action:button", "Upload custom Firmware");
+ enabled: canUpdateFirmware
+ onClicked:
+ {
+ customFirmwareDialog.open()
+ }
+ }
+ }
+
+ Label
+ {
+ width: parent.width
+ wrapMode: Text.WordWrap
+ visible: !printerConnected && !updateProgressDialog.visible
+ text: catalog.i18nc("@label", "Firmware can not be updated because there is no connection with the printer.");
+ }
+
+ Label
+ {
+ width: parent.width
+ wrapMode: Text.WordWrap
+ visible: printerConnected && !canUpdateFirmware
+ text: catalog.i18nc("@label", "Firmware can not be updated because the connection with the printer does not support upgrading firmware.");
+ }
+ }
+
+ FileDialog
+ {
+ id: customFirmwareDialog
+ title: catalog.i18nc("@title:window", "Select custom firmware")
+ nameFilters: "Firmware image files (*.hex)"
+ selectExisting: true
+ onAccepted:
+ {
+ updateProgressDialog.visible = true;
+ activeOutputDevice.updateFirmware(fileUrl);
+ }
+ }
+
+ UM.Dialog
+ {
+ id: updateProgressDialog
+
+ width: minimumWidth
+ minimumWidth: 500 * screenScaleFactor
+ height: minimumHeight
+ minimumHeight: 100 * screenScaleFactor
+
+ modality: Qt.ApplicationModal
+
+ title: catalog.i18nc("@title:window","Firmware Update")
+
+ Column
+ {
+ anchors.fill: parent
+
+ Label
+ {
+ anchors
+ {
+ left: parent.left
+ right: parent.right
+ }
+
+ text: {
+ if(manager.firmwareUpdater == null)
+ {
+ return "";
+ }
+ switch (manager.firmwareUpdater.firmwareUpdateState)
+ {
+ case 0:
+ return ""; //Not doing anything (eg; idling)
+ case 1:
+ return catalog.i18nc("@label","Updating firmware.");
+ case 2:
+ return catalog.i18nc("@label","Firmware update completed.");
+ case 3:
+ return catalog.i18nc("@label","Firmware update failed due to an unknown error.");
+ case 4:
+ return catalog.i18nc("@label","Firmware update failed due to an communication error.");
+ case 5:
+ return catalog.i18nc("@label","Firmware update failed due to an input/output error.");
+ case 6:
+ return catalog.i18nc("@label","Firmware update failed due to missing firmware.");
+ }
+ }
+
+ wrapMode: Text.Wrap
+ }
+
+ ProgressBar
+ {
+ id: prog
+ value: (manager.firmwareUpdater != null) ? manager.firmwareUpdater.firmwareProgress : 0
+ minimumValue: 0
+ maximumValue: 100
+ indeterminate:
+ {
+ if(manager.firmwareUpdater == null)
+ {
+ return false;
+ }
+ return manager.firmwareUpdater.firmwareProgress < 1 && manager.firmwareUpdater.firmwareProgress > 0;
+ }
+ anchors
+ {
+ left: parent.left;
+ right: parent.right;
+ }
+ }
+ }
+
+ rightButtons: [
+ Button
+ {
+ text: catalog.i18nc("@action:button","Close");
+ enabled: (manager.firmwareUpdater != null) ? manager.firmwareUpdater.firmwareUpdateState != 1 : true;
+ onClicked: updateProgressDialog.visible = false;
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/plugins/FirmwareUpdater/__init__.py b/plugins/FirmwareUpdater/__init__.py
new file mode 100644
index 0000000000..5a008d7d15
--- /dev/null
+++ b/plugins/FirmwareUpdater/__init__.py
@@ -0,0 +1,12 @@
+# Copyright (c) 2018 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+
+from . import FirmwareUpdaterMachineAction
+
+def getMetaData():
+ return {}
+
+def register(app):
+ return { "machine_action": [
+ FirmwareUpdaterMachineAction.FirmwareUpdaterMachineAction()
+ ]}
diff --git a/plugins/FirmwareUpdater/plugin.json b/plugins/FirmwareUpdater/plugin.json
new file mode 100644
index 0000000000..c1034e5e42
--- /dev/null
+++ b/plugins/FirmwareUpdater/plugin.json
@@ -0,0 +1,8 @@
+{
+ "name": "Firmware Updater",
+ "author": "Ultimaker B.V.",
+ "version": "1.0.1",
+ "description": "Provides a machine actions for updating firmware.",
+ "api": "6.0",
+ "i18n-catalog": "cura"
+}
diff --git a/plugins/GCodeGzReader/plugin.json b/plugins/GCodeGzReader/plugin.json
index 3bd6a4097d..d4f281682f 100644
--- a/plugins/GCodeGzReader/plugin.json
+++ b/plugins/GCodeGzReader/plugin.json
@@ -1,8 +1,8 @@
{
"name": "Compressed G-code Reader",
"author": "Ultimaker B.V.",
- "version": "1.0.0",
+ "version": "1.0.1",
"description": "Reads g-code from a compressed archive.",
- "api": 5,
+ "api": "6.0",
"i18n-catalog": "cura"
}
diff --git a/plugins/GCodeGzWriter/plugin.json b/plugins/GCodeGzWriter/plugin.json
index 4c6497317b..b0e6f8d605 100644
--- a/plugins/GCodeGzWriter/plugin.json
+++ b/plugins/GCodeGzWriter/plugin.json
@@ -1,8 +1,8 @@
{
"name": "Compressed G-code Writer",
"author": "Ultimaker B.V.",
- "version": "1.0.0",
+ "version": "1.0.1",
"description": "Writes g-code to a compressed archive.",
- "api": 5,
+ "api": "6.0",
"i18n-catalog": "cura"
}
diff --git a/plugins/GCodeProfileReader/plugin.json b/plugins/GCodeProfileReader/plugin.json
index 9677628c85..af1c2d1827 100644
--- a/plugins/GCodeProfileReader/plugin.json
+++ b/plugins/GCodeProfileReader/plugin.json
@@ -1,8 +1,8 @@
{
"name": "G-code Profile Reader",
"author": "Ultimaker B.V.",
- "version": "1.0.0",
+ "version": "1.0.1",
"description": "Provides support for importing profiles from g-code files.",
- "api": 5,
+ "api": "6.0",
"i18n-catalog": "cura"
}
diff --git a/plugins/GCodeReader/FlavorParser.py b/plugins/GCodeReader/FlavorParser.py
index eb19853748..12bed210d2 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
+
+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,7 +35,7 @@ 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
self._clearValues()
@@ -44,6 +46,7 @@ class FlavorParser:
self._extruder_offsets = {} # type: Dict[int, List[float]] # Offsets for multi extruders. key is index, value is [x-offset, y-offset]
self._current_layer_thickness = 0.2 # default
self._filament_diameter = 2.85 # default
+ self._previous_extrusion_value = 0.0 # keep track of the filament retractions
CuraApplication.getInstance().getPreferences().addPreference("gcodereader/show_caution", True)
@@ -106,6 +109,8 @@ class FlavorParser:
self._layer_data_builder.setLayerHeight(self._layer_number, path[0][2])
self._layer_data_builder.setLayerThickness(self._layer_number, layer_thickness)
this_layer = self._layer_data_builder.getLayer(self._layer_number)
+ if not this_layer:
+ return False
except ValueError:
return False
count = len(path)
@@ -182,6 +187,7 @@ class FlavorParser:
new_extrusion_value = params.e if self._is_absolute_extrusion else e[self._extruder_number] + params.e
if new_extrusion_value > e[self._extruder_number]:
path.append([x, y, z, f, new_extrusion_value + self._extrusion_length_offset[self._extruder_number], self._layer_type]) # extrusion
+ self._previous_extrusion_value = new_extrusion_value
else:
path.append([x, y, z, f, new_extrusion_value + self._extrusion_length_offset[self._extruder_number], LayerPolygon.MoveRetractionType]) # retraction
e[self._extruder_number] = new_extrusion_value
@@ -191,6 +197,8 @@ class FlavorParser:
if z > self._previous_z and (z - self._previous_z < 1.5):
self._current_layer_thickness = z - self._previous_z # allow a tiny overlap
self._previous_z = z
+ elif self._previous_extrusion_value > e[self._extruder_number]:
+ path.append([x, y, z, f, e[self._extruder_number] + self._extrusion_length_offset[self._extruder_number], LayerPolygon.MoveRetractionType])
else:
path.append([x, y, z, f, e[self._extruder_number] + self._extrusion_length_offset[self._extruder_number], LayerPolygon.MoveCombingType])
return self._position(x, y, z, f, e)
@@ -227,6 +235,9 @@ class FlavorParser:
# Sometimes a G92 E0 is introduced in the middle of the GCode so we need to keep those offsets for calculate the line_width
self._extrusion_length_offset[self._extruder_number] += position.e[self._extruder_number] - params.e
position.e[self._extruder_number] = params.e
+ self._previous_extrusion_value = params.e
+ else:
+ self._previous_extrusion_value = 0.0
return self._position(
params.x if params.x is not None else position.x,
params.y if params.y is not None else position.y,
@@ -286,7 +297,7 @@ class FlavorParser:
self._cancelled = False
# We obtain the filament diameter from the selected extruder to calculate line widths
global_stack = CuraApplication.getInstance().getGlobalContainerStack()
-
+
if not global_stack:
return None
@@ -329,6 +340,7 @@ class FlavorParser:
min_layer_number = 0
negative_layers = 0
previous_layer = 0
+ self._previous_extrusion_value = 0.0
for line in stream.split("\n"):
if self._cancelled:
@@ -356,6 +368,10 @@ class FlavorParser:
self._layer_type = LayerPolygon.SupportType
elif type == "FILL":
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)
@@ -413,7 +429,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:
@@ -451,7 +468,7 @@ class FlavorParser:
Logger.log("w", "File doesn't contain any valid layers")
settings = CuraApplication.getInstance().getGlobalContainerStack()
- if not settings.getProperty("machine_center_is_zero", "value"):
+ if settings is not None and not settings.getProperty("machine_center_is_zero", "value"):
machine_width = settings.getProperty("machine_width", "value")
machine_depth = settings.getProperty("machine_depth", "value")
scene_node.setPosition(Vector(-machine_width / 2, 0, machine_depth / 2))
diff --git a/plugins/GCodeReader/GCodeReader.py b/plugins/GCodeReader/GCodeReader.py
index 1bc22a3e62..b9e948dfea 100755
--- a/plugins/GCodeReader/GCodeReader.py
+++ b/plugins/GCodeReader/GCodeReader.py
@@ -12,9 +12,6 @@ catalog = i18nCatalog("cura")
from . import MarlinFlavorParser, RepRapFlavorParser
-
-
-
# Class for loading and parsing G-code files
class GCodeReader(MeshReader):
_flavor_default = "Marlin"
diff --git a/plugins/GCodeReader/RepRapFlavorParser.py b/plugins/GCodeReader/RepRapFlavorParser.py
index ba1e13f23d..2a24d16add 100644
--- a/plugins/GCodeReader/RepRapFlavorParser.py
+++ b/plugins/GCodeReader/RepRapFlavorParser.py
@@ -1,9 +1,9 @@
-# Copyright (c) 2017 Ultimaker B.V.
+# Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
from . import FlavorParser
-# This parser is intented for interpret the RepRap Firmware flavor
+## This parser is intended to interpret the RepRap Firmware g-code flavor.
class RepRapFlavorParser(FlavorParser.FlavorParser):
def __init__(self):
diff --git a/plugins/GCodeReader/plugin.json b/plugins/GCodeReader/plugin.json
index 75b4d0cd4f..bbc94fa917 100644
--- a/plugins/GCodeReader/plugin.json
+++ b/plugins/GCodeReader/plugin.json
@@ -1,8 +1,8 @@
{
"name": "G-code Reader",
- "author": "Victor Larchenko",
- "version": "1.0.0",
+ "author": "Victor Larchenko, Ultimaker",
+ "version": "1.0.1",
"description": "Allows loading and displaying G-code files.",
- "api": 5,
+ "api": "6.0",
"i18n-catalog": "cura"
}
diff --git a/plugins/GCodeWriter/plugin.json b/plugins/GCodeWriter/plugin.json
index 3bbbab8b95..f3a95ddb78 100644
--- a/plugins/GCodeWriter/plugin.json
+++ b/plugins/GCodeWriter/plugin.json
@@ -1,8 +1,8 @@
{
"name": "G-code Writer",
"author": "Ultimaker B.V.",
- "version": "1.0.0",
+ "version": "1.0.1",
"description": "Writes g-code to a file.",
- "api": 5,
+ "api": "6.0",
"i18n-catalog": "cura"
}
diff --git a/plugins/ImageReader/ConfigUI.qml b/plugins/ImageReader/ConfigUI.qml
index 12c6aa8dde..47ba10778c 100644
--- a/plugins/ImageReader/ConfigUI.qml
+++ b/plugins/ImageReader/ConfigUI.qml
@@ -20,7 +20,7 @@ UM.Dialog
GridLayout
{
- UM.I18nCatalog{id: catalog; name:"cura"}
+ UM.I18nCatalog{id: catalog; name: "cura"}
anchors.fill: parent;
Layout.fillWidth: true
columnSpacing: 16 * screenScaleFactor
@@ -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,9 +134,9 @@ 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) }
}
diff --git a/plugins/ImageReader/ImageReader.py b/plugins/ImageReader/ImageReader.py
index 5195b61595..e720ce4854 100644
--- a/plugins/ImageReader/ImageReader.py
+++ b/plugins/ImageReader/ImageReader.py
@@ -46,9 +46,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)
- 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):
scene_node = SceneNode()
mesh = MeshBuilder()
@@ -104,7 +104,7 @@ class ImageReader(MeshReader):
Job.yieldThread()
- if image_color_invert:
+ if not lighter_is_higher:
height_data = 1 - height_data
for _ in range(0, blur_iterations):
diff --git a/plugins/ImageReader/ImageReaderUI.py b/plugins/ImageReader/ImageReaderUI.py
index cb45afa4ad..213468a2ab 100644
--- a/plugins/ImageReader/ImageReaderUI.py
+++ b/plugins/ImageReader/ImageReaderUI.py
@@ -30,10 +30,10 @@ 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._ui_lock = threading.Lock()
self._cancelled = False
@@ -143,4 +143,4 @@ class ImageReaderUI(QObject):
@pyqtSlot(int)
def onImageColorInvertChanged(self, value):
- self.image_color_invert = (value == 1)
+ self.lighter_is_higher = (value == 1)
diff --git a/plugins/ImageReader/plugin.json b/plugins/ImageReader/plugin.json
index 08195863e8..d966537d99 100644
--- a/plugins/ImageReader/plugin.json
+++ b/plugins/ImageReader/plugin.json
@@ -1,8 +1,8 @@
{
"name": "Image Reader",
"author": "Ultimaker B.V.",
- "version": "1.0.0",
+ "version": "1.0.1",
"description": "Enables ability to generate printable geometry from 2D image files.",
- "api": 5,
+ "api": "6.0",
"i18n-catalog": "cura"
}
diff --git a/plugins/LegacyProfileReader/DictionaryOfDoom.json b/plugins/LegacyProfileReader/DictionaryOfDoom.json
index 0be413dd2c..f65cc271d1 100644
--- a/plugins/LegacyProfileReader/DictionaryOfDoom.json
+++ b/plugins/LegacyProfileReader/DictionaryOfDoom.json
@@ -1,6 +1,6 @@
{
"source_version": "15.04",
- "target_version": 3,
+ "target_version": "4.5",
"translation": {
"machine_nozzle_size": "nozzle_size",
diff --git a/plugins/LegacyProfileReader/LegacyProfileReader.py b/plugins/LegacyProfileReader/LegacyProfileReader.py
index cd577218d5..013bab6f11 100644
--- a/plugins/LegacyProfileReader/LegacyProfileReader.py
+++ b/plugins/LegacyProfileReader/LegacyProfileReader.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2017 Ultimaker B.V.
+# Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
import configparser # For reading the legacy profile INI files.
@@ -6,6 +6,7 @@ import io
import json # For reading the Dictionary of Doom.
import math # For mathematical operations included in the Dictionary of Doom.
import os.path # For concatenating the path to the plugin and the relative path to the Dictionary of Doom.
+from typing import Dict
from UM.Application import Application # To get the machine manager to create the new profile in.
from UM.Logger import Logger # Logging errors.
@@ -33,10 +34,11 @@ class LegacyProfileReader(ProfileReader):
# \param json The JSON file to load the default setting values from. This
# should not be a URL but a pre-loaded JSON handle.
# \return A dictionary of the default values of the legacy Cura version.
- def prepareDefaults(self, json):
+ def prepareDefaults(self, json: Dict[str, Dict[str, str]]) -> Dict[str, str]:
defaults = {}
- for key in json["defaults"]: # We have to copy over all defaults from the JSON handle to a normal dict.
- defaults[key] = json["defaults"][key]
+ if "defaults" in json:
+ for key in json["defaults"]: # We have to copy over all defaults from the JSON handle to a normal dict.
+ defaults[key] = json["defaults"][key]
return defaults
## Prepares the local variables that can be used in evaluation of computing
@@ -80,11 +82,10 @@ class LegacyProfileReader(ProfileReader):
Logger.log("i", "Importing legacy profile from file " + file_name + ".")
container_registry = ContainerRegistry.getInstance()
profile_id = container_registry.uniqueName("Imported Legacy Profile")
- profile = InstanceContainer(profile_id) # Create an empty profile.
- parser = configparser.ConfigParser(interpolation = None)
+ input_parser = configparser.ConfigParser(interpolation = None)
try:
- parser.read([file_name]) # Parse the INI file.
+ input_parser.read([file_name]) # Parse the INI file.
except Exception as e:
Logger.log("e", "Unable to open legacy profile %s: %s", file_name, str(e))
return None
@@ -92,7 +93,7 @@ class LegacyProfileReader(ProfileReader):
# Legacy Cura saved the profile under the section "profile_N" where N is the ID of a machine, except when you export in which case it saves it in the section "profile".
# Since importing multiple machine profiles is out of scope, just import the first section we find.
section = ""
- for found_section in parser.sections():
+ for found_section in input_parser.sections():
if found_section.startswith("profile"):
section = found_section
break
@@ -110,15 +111,13 @@ class LegacyProfileReader(ProfileReader):
return None
defaults = self.prepareDefaults(dict_of_doom)
- legacy_settings = self.prepareLocals(parser, section, defaults) #Gets the settings from the legacy profile.
+ legacy_settings = self.prepareLocals(input_parser, section, defaults) #Gets the settings from the legacy profile.
- #Check the target version in the Dictionary of Doom with this application version.
- if "target_version" not in dict_of_doom:
- Logger.log("e", "Dictionary of Doom has no target version. Is it the correct JSON file?")
- return None
- if InstanceContainer.Version != dict_of_doom["target_version"]:
- Logger.log("e", "Dictionary of Doom of legacy profile reader (version %s) is not in sync with the current instance container version (version %s)!", dict_of_doom["target_version"], str(InstanceContainer.Version))
- return None
+ # Serialised format into version 4.5. Do NOT upgrade this, let the version upgrader handle it.
+ output_parser = configparser.ConfigParser(interpolation = None)
+ output_parser.add_section("general")
+ output_parser.add_section("metadata")
+ output_parser.add_section("values")
if "translation" not in dict_of_doom:
Logger.log("e", "Dictionary of Doom has no translation. Is it the correct JSON file?")
@@ -127,7 +126,7 @@ class LegacyProfileReader(ProfileReader):
quality_definition = current_printer_definition.getMetaDataEntry("quality_definition")
if not quality_definition:
quality_definition = current_printer_definition.getId()
- profile.setDefinition(quality_definition)
+ output_parser["general"]["definition"] = quality_definition
for new_setting in dict_of_doom["translation"]: # Evaluate all new settings that would get a value from the translations.
old_setting_expression = dict_of_doom["translation"][new_setting]
compiled = compile(old_setting_expression, new_setting, "eval")
@@ -140,37 +139,34 @@ class LegacyProfileReader(ProfileReader):
definitions = current_printer_definition.findDefinitions(key = new_setting)
if definitions:
if new_value != value_using_defaults and definitions[0].default_value != new_value: # Not equal to the default in the new Cura OR the default in the legacy Cura.
- profile.setProperty(new_setting, "value", new_value) # Store the setting in the profile!
+ output_parser["values"][new_setting] = str(new_value) # Store the setting in the profile!
- if len(profile.getAllKeys()) == 0:
+ if len(output_parser["values"]) == 0:
Logger.log("i", "A legacy profile was imported but everything evaluates to the defaults, creating an empty profile.")
- profile.setMetaDataEntry("type", "profile")
- # don't know what quality_type it is based on, so use "normal" by default
- profile.setMetaDataEntry("quality_type", "normal")
- profile.setName(profile_id)
- profile.setDirty(True)
+ output_parser["general"]["version"] = "4"
+ output_parser["general"]["name"] = profile_id
+ output_parser["metadata"]["type"] = "quality_changes"
+ output_parser["metadata"]["quality_type"] = "normal" # Don't know what quality_type it is based on, so use "normal" by default.
+ output_parser["metadata"]["position"] = "0" # We only support single extrusion.
+ output_parser["metadata"]["setting_version"] = "5" # What the dictionary of doom is made for.
- #Serialise and deserialise in order to perform the version upgrade.
- parser = configparser.ConfigParser(interpolation = None)
- data = profile.serialize()
- parser.read_string(data)
- parser["general"]["version"] = "1"
- if parser.has_section("values"):
- parser["settings"] = parser["values"]
- del parser["values"]
+ # Serialise in order to perform the version upgrade.
stream = io.StringIO()
- parser.write(stream)
+ output_parser.write(stream)
data = stream.getvalue()
- profile.deserialize(data)
- # The definition can get reset to fdmprinter during the deserialization's upgrade. Here we set the definition
- # again.
- profile.setDefinition(quality_definition)
+ profile = InstanceContainer(profile_id)
+ profile.deserialize(data) # Also performs the version upgrade.
+ profile.setDirty(True)
#We need to return one extruder stack and one global stack.
global_container_id = container_registry.uniqueName("Global Imported Legacy Profile")
+ # We duplicate the extruder profile into the global stack.
+ # This may introduce some settings that are global in the extruder stack and some settings that are per-extruder in the global stack.
+ # We don't care about that. The engine will ignore them anyway.
global_profile = profile.duplicate(new_id = global_container_id, new_name = profile_id) #Needs to have the same name as the extruder profile.
+ del global_profile.getMetaData()["position"] # Has no position because it's global.
global_profile.setDirty(True)
profile_definition = "fdmprinter"
diff --git a/plugins/LegacyProfileReader/plugin.json b/plugins/LegacyProfileReader/plugin.json
index 179f5444e0..2f5264ad37 100644
--- a/plugins/LegacyProfileReader/plugin.json
+++ b/plugins/LegacyProfileReader/plugin.json
@@ -1,8 +1,8 @@
{
"name": "Legacy Cura Profile Reader",
"author": "Ultimaker B.V.",
- "version": "1.0.0",
+ "version": "1.0.1",
"description": "Provides support for importing profiles from legacy Cura versions.",
- "api": 5,
+ "api": "6.0",
"i18n-catalog": "cura"
}
diff --git a/plugins/LegacyProfileReader/tests/TestLegacyProfileReader.py b/plugins/LegacyProfileReader/tests/TestLegacyProfileReader.py
new file mode 100644
index 0000000000..480a61f301
--- /dev/null
+++ b/plugins/LegacyProfileReader/tests/TestLegacyProfileReader.py
@@ -0,0 +1,190 @@
+# Copyright (c) 2018 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+
+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 UM.Application # To mock the application out.
+import UM.PluginRegistry # To mock the plug-in registry out.
+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()
+
+test_prepareDefaultsData = [
+ {
+ "defaults":
+ {
+ "foo": "bar"
+ },
+ "cheese": "delicious"
+ },
+ {
+ "cat": "fluffy",
+ "dog": "floofy"
+ }
+]
+
+@pytest.mark.parametrize("input", test_prepareDefaultsData)
+def test_prepareDefaults(legacy_profile_reader, input):
+ output = legacy_profile_reader.prepareDefaults(input)
+ if "defaults" in input:
+ assert input["defaults"] == output
+ else:
+ assert output == {}
+
+test_prepareLocalsData = [
+ ( # Ordinary case.
+ { # Parser data.
+ "profile":
+ {
+ "layer_height": "0.2",
+ "infill_density": "30"
+ }
+ },
+ { # Defaults.
+ "layer_height": "0.1",
+ "infill_density": "20",
+ "line_width": "0.4"
+ }
+ ),
+ ( # Empty data.
+ { # Parser data.
+ "profile":
+ {
+ }
+ },
+ { # Defaults.
+ }
+ ),
+ ( # All defaults.
+ { # Parser data.
+ "profile":
+ {
+ }
+ },
+ { # Defaults.
+ "foo": "bar",
+ "boo": "far"
+ }
+ ),
+ ( # Multiple config sections.
+ { # Parser data.
+ "some_other_name":
+ {
+ "foo": "bar"
+ },
+ "profile":
+ {
+ "foo": "baz" #Not the same as in some_other_name
+ }
+ },
+ { # Defaults.
+ "foo": "bla"
+ }
+ )
+]
+
+@pytest.mark.parametrize("parser_data, defaults", test_prepareLocalsData)
+def test_prepareLocals(legacy_profile_reader, parser_data, defaults):
+ parser = configparser.ConfigParser()
+ parser.read_dict(parser_data)
+
+ output = legacy_profile_reader.prepareLocals(parser, "profile", defaults)
+
+ assert set(defaults.keys()) <= set(output.keys()) # All defaults must be in there.
+ assert set(parser_data["profile"]) <= set(output.keys()) # All overwritten values must be in there.
+ for key in output:
+ if key in parser_data["profile"]:
+ assert output[key] == parser_data["profile"][key] # If overwritten, must be the overwritten value.
+ else:
+ assert output[key] == defaults[key] # Otherwise must be equal to the default.
+
+test_prepareLocalsNoSectionErrorData = [
+ ( # Section does not exist.
+ { # Parser data.
+ "some_other_name":
+ {
+ "foo": "bar"
+ },
+ },
+ { # Defaults.
+ "foo": "baz"
+ }
+ )
+]
+
+## Test cases where a key error is expected.
+@pytest.mark.parametrize("parser_data, defaults", test_prepareLocalsNoSectionErrorData)
+def test_prepareLocalsNoSectionError(legacy_profile_reader, parser_data, defaults):
+ parser = configparser.ConfigParser()
+ parser.read_dict(parser_data)
+
+ with pytest.raises(configparser.NoSectionError):
+ legacy_profile_reader.prepareLocals(parser, "profile", defaults)
+
+intercepted_data = ""
+
+@pytest.mark.parametrize("file_name", ["normal_case.ini"])
+def test_read(legacy_profile_reader, file_name):
+ # Mock out all dependencies. Quite a lot!
+ global_stack = unittest.mock.MagicMock()
+ global_stack.getProperty = unittest.mock.MagicMock(return_value = 1) # For machine_extruder_count setting.
+ def getMetaDataEntry(key, default_value = ""):
+ if key == "quality_definition":
+ return "mocked_quality_definition"
+ if key == "has_machine_quality":
+ return "True"
+ global_stack.definition.getMetaDataEntry = getMetaDataEntry
+ global_stack.definition.getId = unittest.mock.MagicMock(return_value = "mocked_global_definition")
+ application = unittest.mock.MagicMock()
+ application.getGlobalContainerStack = unittest.mock.MagicMock(return_value = global_stack)
+ application_getInstance = unittest.mock.MagicMock(return_value = application)
+ container_registry = unittest.mock.MagicMock()
+ container_registry_getInstance = unittest.mock.MagicMock(return_value = container_registry)
+ container_registry.uniqueName = unittest.mock.MagicMock(return_value = "Imported Legacy Profile")
+ container_registry.findDefinitionContainers = unittest.mock.MagicMock(return_value = [global_stack.definition])
+ UM.Settings.InstanceContainer.setContainerRegistry(container_registry)
+ plugin_registry = unittest.mock.MagicMock()
+ plugin_registry_getInstance = unittest.mock.MagicMock(return_value = plugin_registry)
+ 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.
+ global intercepted_data
+ intercepted_data = data
+
+ parser = configparser.ConfigParser()
+ parser.read_string(data)
+ self._metadata["position"] = parser["metadata"]["position"]
+ def duplicate(self, new_id, new_name):
+ self._metadata["id"] = new_id
+ self._metadata["name"] = new_name
+ return self
+
+ with unittest.mock.patch.object(UM.Application.Application, "getInstance", application_getInstance):
+ with unittest.mock.patch.object(UM.Settings.ContainerRegistry.ContainerRegistry, "getInstance", container_registry_getInstance):
+ with unittest.mock.patch.object(UM.PluginRegistry.PluginRegistry, "getInstance", plugin_registry_getInstance):
+ with unittest.mock.patch.object(UM.Settings.InstanceContainer.InstanceContainer, "deserialize", deserialize):
+ with unittest.mock.patch.object(UM.Settings.InstanceContainer.InstanceContainer, "duplicate", duplicate):
+ result = legacy_profile_reader.read(os.path.join(os.path.dirname(__file__), file_name))
+
+ assert len(result) == 1
+
+ # Let's see what's inside the actual output file that we generated.
+ parser = configparser.ConfigParser()
+ parser.read_string(intercepted_data)
+ assert parser["general"]["definition"] == "mocked_quality_definition"
+ assert parser["general"]["version"] == "4" # Yes, before we upgraded.
+ assert parser["general"]["name"] == "Imported Legacy Profile" # Because we overwrote uniqueName.
+ 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
diff --git a/plugins/LegacyProfileReader/tests/normal_case.ini b/plugins/LegacyProfileReader/tests/normal_case.ini
new file mode 100644
index 0000000000..213444d2d3
--- /dev/null
+++ b/plugins/LegacyProfileReader/tests/normal_case.ini
@@ -0,0 +1,7 @@
+[profile]
+foo = bar
+boo = far
+fill_overlap = 3
+
+[alterations]
+some = values
diff --git a/plugins/MachineSettingsAction/MachineSettingsAction.py b/plugins/MachineSettingsAction/MachineSettingsAction.py
index afd7aac86d..cddc4e5fe8 100755
--- a/plugins/MachineSettingsAction/MachineSettingsAction.py
+++ b/plugins/MachineSettingsAction/MachineSettingsAction.py
@@ -1,16 +1,21 @@
-# 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 cura.MachineAction import MachineAction
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 +23,102 @@ 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 = []
-
- 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
-
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()
+ definition = global_stack.getDefinition()
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
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"
+ extruder_positions = list(global_stack.extruders.keys())
+ 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")
# set materials
for position in extruder_positions:
if has_materials:
- material_node = material_manager.getDefaultMaterial(self._global_container_stack, position, None)
+ material_node = material_manager.getDefaultMaterial(global_stack, position, None)
machine_manager.setMaterial(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 6c95dc2c92..a1540c22ab 100644
--- a/plugins/MachineSettingsAction/MachineSettingsAction.qml
+++ b/plugins/MachineSettingsAction/MachineSettingsAction.qml
@@ -1,911 +1,103 @@
-// 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
+//
+// This component contains the content for the "Welcome" page of the welcome on-boarding process.
+//
Cura.MachineAction
{
- id: base
- property var extrudersModel: Cura.ExtrudersModel{}
- 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.rowCount();
- 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);
- }
- }
- 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
+ UM.TabRow
{
- id: simpleCheckBox
- UM.TooltipArea
+ id: tabBar
+ 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
-
- 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)
- {
- 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..5ba331de2b
--- /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.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..2556eb3a9c
--- /dev/null
+++ b/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml
@@ -0,0 +1,361 @@
+// 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 the content in the "Printer" tab in the Machine Settings dialog.
+//
+Item
+{
+ id: base
+ UM.I18nCatalog { id: catalog; name: "cura" }
+
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.top: parent.top
+
+ 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.activeMachineId
+
+ property var forceUpdateFunction: manager.forceUpdate
+
+ 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 for "Printer Settings"
+ // =======================================
+ Column
+ {
+ anchors.top: parent.top
+ anchors.left: parent.left
+ width: base.columnWidth
+
+ 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.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
+ {
+ anchors.top: parent.top
+ anchors.right: parent.right
+ width: base.columnWidth
+
+ 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
+
+ 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
+
+ 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: 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: 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()
+ }
+ }
+ }
+ }
+
+ Item // 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 // "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", "Start G-code")
+ containerStackId: machineStackId
+ settingKey: "machine_start_gcode"
+ settingStoreIndex: propertyStoreIndex
+ }
+
+ Cura.GcodeTextArea // "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", "End G-code")
+ containerStackId: machineStackId
+ settingKey: "machine_end_gcode"
+ settingStoreIndex: propertyStoreIndex
+ }
+ }
+}
diff --git a/plugins/MachineSettingsAction/plugin.json b/plugins/MachineSettingsAction/plugin.json
index 571658e40a..d734c1adf5 100644
--- a/plugins/MachineSettingsAction/plugin.json
+++ b/plugins/MachineSettingsAction/plugin.json
@@ -1,8 +1,8 @@
{
"name": "Machine Settings action",
"author": "fieldOfView",
- "version": "1.0.0",
+ "version": "1.0.1",
"description": "Provides a way to change machine settings (such as build volume, nozzle size, etc.).",
- "api": 5,
+ "api": "6.0",
"i18n-catalog": "cura"
}
diff --git a/plugins/ModelChecker/ModelChecker.py b/plugins/ModelChecker/ModelChecker.py
index d2c2eefac2..0619c95d67 100644
--- a/plugins/ModelChecker/ModelChecker.py
+++ b/plugins/ModelChecker/ModelChecker.py
@@ -3,12 +3,13 @@
import os
-from PyQt5.QtCore import QObject, pyqtSlot, pyqtSignal, pyqtProperty
+from PyQt5.QtCore import QObject, pyqtSlot, pyqtSignal, pyqtProperty, QTimer
from UM.Application import Application
from UM.Extension import Extension
from UM.Logger import Logger
from UM.Message import Message
+from UM.Scene.Camera import Camera
from UM.i18n import i18nCatalog
from UM.PluginRegistry import PluginRegistry
from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator
@@ -29,13 +30,22 @@ class ModelChecker(QObject, Extension):
lifetime = 0,
title = catalog.i18nc("@info:title", "3D Model Assistant"))
+ self._change_timer = QTimer()
+ self._change_timer.setInterval(200)
+ self._change_timer.setSingleShot(True)
+ self._change_timer.timeout.connect(self.onChanged)
+
Application.getInstance().initializationFinished.connect(self._pluginsInitialized)
Application.getInstance().getController().getScene().sceneChanged.connect(self._onChanged)
Application.getInstance().globalContainerStackChanged.connect(self._onChanged)
- ## Pass-through to allow UM.Signal to connect with a pyqtSignal.
def _onChanged(self, *args, **kwargs):
- self.onChanged.emit()
+ # Ignore camera updates.
+ if len(args) == 0:
+ self._change_timer.start()
+ return
+ if not isinstance(args[0], Camera):
+ self._change_timer.start()
## Called when plug-ins are initialized.
#
diff --git a/plugins/ModelChecker/ModelChecker.qml b/plugins/ModelChecker/ModelChecker.qml
index 98db233bf8..ddeed063b1 100644
--- a/plugins/ModelChecker/ModelChecker.qml
+++ b/plugins/ModelChecker/ModelChecker.qml
@@ -4,19 +4,19 @@
import QtQuick 2.2
import QtQuick.Controls 1.1
import QtQuick.Controls.Styles 1.1
-import QtQuick.Layouts 1.1
-import QtQuick.Dialogs 1.1
-import QtQuick.Window 2.2
import UM 1.2 as UM
-import Cura 1.0 as Cura
Button
{
id: modelCheckerButton
- UM.I18nCatalog{id: catalog; name:"cura"}
+ UM.I18nCatalog
+ {
+ id: catalog
+ name: "cura"
+ }
visible: manager.hasWarnings
tooltip: catalog.i18nc("@info:tooltip", "Some things could be problematic in this print. Click to see tips for adjustment.")
@@ -25,6 +25,8 @@ Button
width: UM.Theme.getSize("save_button_specs_icons").width
height: UM.Theme.getSize("save_button_specs_icons").height
+ anchors.verticalCenter: parent ? parent.verticalCenter : undefined
+
style: ButtonStyle
{
background: Item
@@ -33,7 +35,6 @@ Button
{
width: UM.Theme.getSize("save_button_specs_icons").width;
height: UM.Theme.getSize("save_button_specs_icons").height;
- sourceSize.width: width;
sourceSize.height: width;
color: control.hovered ? UM.Theme.getColor("text_scene_hover") : UM.Theme.getColor("text_scene");
source: "model_checker.svg"
diff --git a/plugins/ModelChecker/plugin.json b/plugins/ModelChecker/plugin.json
index 3753c0cc88..59be5bbf0a 100644
--- a/plugins/ModelChecker/plugin.json
+++ b/plugins/ModelChecker/plugin.json
@@ -1,8 +1,8 @@
{
"name": "Model Checker",
"author": "Ultimaker B.V.",
- "version": "0.1",
- "api": 5,
+ "version": "1.0.1",
+ "api": "6.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
new file mode 100644
index 0000000000..7c0a20ef66
--- /dev/null
+++ b/plugins/MonitorStage/MonitorMain.qml
@@ -0,0 +1,169 @@
+// Copyright (c) 2018 Ultimaker B.V.
+// Cura is released under the terms of the LGPLv3 or higher.
+
+import QtQuick 2.10
+import QtQuick.Controls 2.0
+import UM 1.3 as UM
+import Cura 1.0 as Cura
+
+// We show a nice overlay on the 3D viewer when the current output device has no monitor view
+Rectangle
+{
+ id: viewportOverlay
+
+ property bool isConnected: Cura.MachineManager.activeMachineHasNetworkConnection || Cura.MachineManager.activeMachineHasCloudConnection
+ 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
+
+ // Check if configured connection types includes either 2 or 3 (LAN or cloud)
+ for (var i = 0; i < types.length; i++)
+ {
+ if (connectedTypes.indexOf(types[i]) >= 0)
+ {
+ return true
+ }
+ }
+ return false
+ }
+
+ color: UM.Theme.getColor("viewport_overlay")
+ anchors.fill: parent
+
+ UM.I18nCatalog
+ {
+ id: catalog
+ name: "cura"
+ }
+
+ // This mouse area is to prevent mouse clicks to be passed onto the scene.
+ MouseArea
+ {
+ anchors.fill: parent
+ acceptedButtons: Qt.AllButtons
+ onWheel: wheel.accepted = true
+ }
+
+ // Disable dropping files into Cura when the monitor page is active
+ DropArea
+ {
+ anchors.fill: parent
+ }
+
+ // CASE 1: CAN MONITOR & CONNECTED
+ Loader
+ {
+ id: monitorViewComponent
+
+ anchors.fill: parent
+
+ height: parent.height
+
+ property real maximumWidth: parent.width
+ property real maximumHeight: parent.height
+
+ sourceComponent: Cura.MachineManager.printerOutputDevices.length > 0 ? Cura.MachineManager.printerOutputDevices[0].monitorItem : null
+ }
+
+ // CASE 2 & 3: Empty states
+ Column
+ {
+ anchors
+ {
+ top: parent.top
+ topMargin: UM.Theme.getSize("monitor_empty_state_offset").height
+ horizontalCenter: parent.horizontalCenter
+ }
+ width: UM.Theme.getSize("monitor_empty_state_size").width
+ spacing: UM.Theme.getSize("default_margin").height
+ visible: monitorViewComponent.sourceComponent == null
+
+ // CASE 2: CAN MONITOR & NOT CONNECTED
+ Label
+ {
+ anchors
+ {
+ 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.\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
+ lineHeight: UM.Theme.getSize("monitor_text_line_large").height
+ lineHeightMode: Text.FixedHeight
+ width: contentWidth
+ }
+
+ Label
+ {
+ id: noNetworkLabel
+ anchors
+ {
+ horizontalCenter: parent.horizontalCenter
+ }
+ visible: !isNetworkConfigured && isNetworkConfigurable
+ 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
+ width: contentWidth
+ lineHeight: UM.Theme.getSize("monitor_text_line_large").height
+ lineHeightMode: Text.FixedHeight
+ }
+ Item
+ {
+ anchors
+ {
+ left: noNetworkLabel.left
+ }
+ visible: !isNetworkConfigured && isNetworkConfigurable
+ height: UM.Theme.getSize("monitor_text_line").height
+ width: childrenRect.width
+
+ UM.RecolorImage
+ {
+ id: externalLinkIcon
+ anchors.verticalCenter: parent.verticalCenter
+ color: UM.Theme.getColor("monitor_text_link")
+ source: UM.Theme.getIcon("external_link")
+ width: UM.Theme.getSize("monitor_external_link_icon").width
+ height: UM.Theme.getSize("monitor_external_link_icon").height
+ }
+ Label
+ {
+ id: manageQueueText
+ anchors
+ {
+ left: externalLinkIcon.right
+ leftMargin: UM.Theme.getSize("narrow_margin").width
+ verticalCenter: externalLinkIcon.verticalCenter
+ }
+ color: UM.Theme.getColor("monitor_text_link")
+ 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
+ }
+ MouseArea
+ {
+ 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
+ }
+ }
+ }
+}
diff --git a/plugins/MonitorStage/MonitorMainView.qml b/plugins/MonitorStage/MonitorMainView.qml
deleted file mode 100644
index c48f6d0aab..0000000000
--- a/plugins/MonitorStage/MonitorMainView.qml
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright (c) 2017 Ultimaker B.V.
-
-import QtQuick 2.2
-import QtQuick.Controls 1.1
-
-import UM 1.3 as UM
-import Cura 1.0 as Cura
-
-Item
-{
- // parent could be undefined as this component is not visible at all times
- width: parent ? parent.width : 0
- height: parent ? parent.height : 0
-
- // We show a nice overlay on the 3D viewer when the current output device has no monitor view
- Rectangle
- {
- id: viewportOverlay
-
- color: UM.Theme.getColor("viewport_overlay")
- width: parent.width
- height: parent.height
-
- MouseArea
- {
- anchors.fill: parent
- acceptedButtons: Qt.AllButtons
- onWheel: wheel.accepted = true
- }
- }
-
- Loader
- {
- id: monitorViewComponent
-
- width: parent.width
- height: parent.height
-
- property real maximumWidth: parent.width
- property real maximumHeight: parent.height
-
- sourceComponent: Cura.MachineManager.printerOutputDevices.length > 0 ? Cura.MachineManager.printerOutputDevices[0].monitorItem: null
- visible: sourceComponent != null
- }
-}
diff --git a/plugins/MonitorStage/MonitorMenu.qml b/plugins/MonitorStage/MonitorMenu.qml
new file mode 100644
index 0000000000..bc95c276e8
--- /dev/null
+++ b/plugins/MonitorStage/MonitorMenu.qml
@@ -0,0 +1,23 @@
+// 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.3
+
+import UM 1.3 as UM
+import Cura 1.1 as Cura
+
+Item
+{
+ signal showTooltip(Item item, point location, string text)
+ signal hideTooltip()
+
+ Cura.MachineSelector
+ {
+ id: machineSelection
+ headerCornerSide: Cura.RoundedRectangle.Direction.All
+ width: UM.Theme.getSize("machine_selector_widget").width
+ height: parent.height
+ anchors.centerIn: parent
+ }
+}
\ No newline at end of file
diff --git a/plugins/MonitorStage/MonitorStage.py b/plugins/MonitorStage/MonitorStage.py
index ace201e994..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
@@ -65,15 +63,10 @@ class MonitorStage(CuraStage):
# We can only connect now, as we need to be sure that everything is loaded (plugins get created quite early)
Application.getInstance().getMachineManager().outputDevicesChanged.connect(self._onOutputDevicesChanged)
self._onOutputDevicesChanged()
- self._updateMainOverlay()
- self._updateSidebar()
- def _updateMainOverlay(self):
- main_component_path = os.path.join(PluginRegistry.getInstance().getPluginPath("MonitorStage"),
- "MonitorMainView.qml")
- self.addDisplayComponent("main", main_component_path)
-
- def _updateSidebar(self):
- sidebar_component_path = os.path.join(Resources.getPath(Application.getInstance().ResourceTypes.QmlFiles),
- "MonitorSidebar.qml")
- self.addDisplayComponent("sidebar", sidebar_component_path)
+ plugin_path = Application.getInstance().getPluginRegistry().getPluginPath(self.getPluginId())
+ if plugin_path is not None:
+ menu_component_path = os.path.join(plugin_path, "MonitorMenu.qml")
+ main_component_path = os.path.join(plugin_path, "MonitorMain.qml")
+ self.addDisplayComponent("menu", menu_component_path)
+ self.addDisplayComponent("main", main_component_path)
diff --git a/plugins/MonitorStage/__init__.py b/plugins/MonitorStage/__init__.py
index bdaf53a36c..0468e6319b 100644
--- a/plugins/MonitorStage/__init__.py
+++ b/plugins/MonitorStage/__init__.py
@@ -7,14 +7,16 @@ from . import MonitorStage
from UM.i18n import i18nCatalog
i18n_catalog = i18nCatalog("cura")
+
def getMetaData():
return {
"stage": {
"name": i18n_catalog.i18nc("@item:inmenu", "Monitor"),
- "weight": 1
+ "weight": 2
}
}
+
def register(app):
return {
"stage": MonitorStage.MonitorStage()
diff --git a/plugins/MonitorStage/plugin.json b/plugins/MonitorStage/plugin.json
index 88b53840e0..95e4b86f36 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.0",
+ "version": "1.0.1",
"description": "Provides a monitor stage in Cura.",
- "api": 5,
+ "api": "6.0",
"i18n-catalog": "cura"
}
\ No newline at end of file
diff --git a/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml b/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml
index 4c9ba2169c..035d2e5299 100644
--- a/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml
+++ b/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml
@@ -160,7 +160,7 @@ Item {
model: UM.SettingDefinitionsModel
{
id: addedSettingsModel;
- containerId: Cura.MachineManager.activeDefinitionId
+ containerId: Cura.MachineManager.activeMachine != null ? Cura.MachineManager.activeMachine.definition.id: ""
expanded: [ "*" ]
filter:
{
@@ -265,7 +265,6 @@ Item {
anchors.verticalCenter: parent.verticalCenter
width: parent.width
height: width
- sourceSize.width: width
sourceSize.height: width
color: control.hovered ? UM.Theme.getColor("setting_control_button_hover") : UM.Theme.getColor("setting_control_button")
source: UM.Theme.getIcon("minus")
@@ -407,14 +406,9 @@ Item {
function updateFilter()
{
var new_filter = {};
- if (printSequencePropertyProvider.properties.value == "one_at_a_time")
- {
- new_filter["settable_per_meshgroup"] = true;
- }
- else
- {
- new_filter["settable_per_mesh"] = true;
- }
+ 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 != "")
{
@@ -473,7 +467,7 @@ Item {
model: UM.SettingDefinitionsModel
{
id: definitionsModel;
- containerId: Cura.MachineManager.activeDefinitionId
+ containerId: Cura.MachineManager.activeMachine != null ? Cura.MachineManager.activeMachine.definition.id: ""
visibilityHandler: UM.SettingPreferenceVisibilityHandler {}
expanded: [ "*" ]
exclude:
diff --git a/plugins/PerObjectSettingsTool/plugin.json b/plugins/PerObjectSettingsTool/plugin.json
index 15fde63387..f272abf06a 100644
--- a/plugins/PerObjectSettingsTool/plugin.json
+++ b/plugins/PerObjectSettingsTool/plugin.json
@@ -1,8 +1,8 @@
{
"name": "Per Model Settings Tool",
"author": "Ultimaker B.V.",
- "version": "1.0.0",
+ "version": "1.0.1",
"description": "Provides the Per Model Settings.",
- "api": 5,
+ "api": "6.0",
"i18n-catalog": "cura"
}
diff --git a/plugins/PostProcessingPlugin/PostProcessingPlugin.py b/plugins/PostProcessingPlugin/PostProcessingPlugin.py
index 1a1ea92d10..376ab291c4 100644
--- a/plugins/PostProcessingPlugin/PostProcessingPlugin.py
+++ b/plugins/PostProcessingPlugin/PostProcessingPlugin.py
@@ -32,7 +32,8 @@ class PostProcessingPlugin(QObject, Extension):
def __init__(self, parent = None) -> None:
QObject.__init__(self, parent)
Extension.__init__(self)
- self.addMenuItem(i18n_catalog.i18n("Modify G-Code"), self.showPopup)
+ self.setMenuName(i18n_catalog.i18nc("@item:inmenu", "Post Processing"))
+ self.addMenuItem(i18n_catalog.i18nc("@item:inmenu", "Modify G-Code"), self.showPopup)
self._view = None
# Loaded scripts are all scripts that can be used
@@ -54,14 +55,14 @@ class PostProcessingPlugin(QObject, Extension):
def selectedScriptDefinitionId(self) -> Optional[str]:
try:
return self._script_list[self._selected_script_index].getDefinitionId()
- except:
+ except IndexError:
return ""
@pyqtProperty(str, notify=selectedIndexChanged)
def selectedScriptStackId(self) -> Optional[str]:
try:
return self._script_list[self._selected_script_index].getStackId()
- except:
+ except IndexError:
return ""
## Execute all post-processing scripts on the gcode.
@@ -161,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)
@@ -218,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/PostProcessingPlugin.qml b/plugins/PostProcessingPlugin/PostProcessingPlugin.qml
index d492e06462..cd8303d1d3 100644
--- a/plugins/PostProcessingPlugin/PostProcessingPlugin.qml
+++ b/plugins/PostProcessingPlugin/PostProcessingPlugin.qml
@@ -25,13 +25,13 @@ UM.Dialog
{
if(!visible) //Whenever the window is closed (either via the "Close" button or the X on the window frame), we want to update it in the stack.
{
- manager.writeScriptsToStack();
+ manager.writeScriptsToStack()
}
}
Item
{
- UM.I18nCatalog{id: catalog; name:"cura"}
+ UM.I18nCatalog{id: catalog; name: "cura"}
id: base
property int columnWidth: Math.round((base.width / 2) - UM.Theme.getSize("default_margin").width)
property int textMargin: Math.round(UM.Theme.getSize("default_margin").width / 2)
@@ -61,18 +61,23 @@ UM.Dialog
anchors.leftMargin: base.textMargin
anchors.right: parent.right
anchors.rightMargin: base.textMargin
- font: UM.Theme.getFont("large")
+ font: UM.Theme.getFont("large_bold")
elide: Text.ElideRight
}
ListView
{
id: activeScriptsList
- anchors.top: activeScriptsHeader.bottom
- anchors.topMargin: base.textMargin
- anchors.left: parent.left
- anchors.leftMargin: UM.Theme.getSize("default_margin").width
- anchors.right: parent.right
- anchors.rightMargin: base.textMargin
+
+ anchors
+ {
+ top: activeScriptsHeader.bottom
+ left: parent.left
+ right: parent.right
+ rightMargin: base.textMargin
+ topMargin: base.textMargin
+ leftMargin: UM.Theme.getSize("default_margin").width
+ }
+
height: childrenRect.height
model: manager.scriptList
delegate: Item
@@ -84,8 +89,12 @@ UM.Dialog
id: activeScriptButton
text: manager.getScriptLabelByKey(modelData.toString())
exclusiveGroup: selectedScriptGroup
+ width: parent.width
+ height: UM.Theme.getSize("setting").height
checkable: true
- checked: {
+
+ checked:
+ {
if (manager.selectedScriptIndex == index)
{
base.activeScriptName = manager.getScriptLabelByKey(modelData.toString())
@@ -102,8 +111,7 @@ UM.Dialog
manager.setSelectedScriptIndex(index)
base.activeScriptName = manager.getScriptLabelByKey(modelData.toString())
}
- width: parent.width
- height: UM.Theme.getSize("setting").height
+
style: ButtonStyle
{
background: Rectangle
@@ -121,6 +129,7 @@ UM.Dialog
}
}
}
+
Button
{
id: removeButton
@@ -141,7 +150,6 @@ UM.Dialog
anchors.horizontalCenter: parent.horizontalCenter
width: Math.round(control.width / 2.7)
height: Math.round(control.height / 2.7)
- sourceSize.width: width
sourceSize.height: width
color: palette.text
source: UM.Theme.getIcon("cross1")
@@ -176,7 +184,6 @@ UM.Dialog
anchors.horizontalCenter: parent.horizontalCenter
width: Math.round(control.width / 2.5)
height: Math.round(control.height / 2.5)
- sourceSize.width: width
sourceSize.height: width
color: control.enabled ? palette.text : disabledPalette.text
source: UM.Theme.getIcon("arrow_bottom")
@@ -211,7 +218,6 @@ UM.Dialog
anchors.horizontalCenter: parent.horizontalCenter
width: Math.round(control.width / 2.5)
height: Math.round(control.height / 2.5)
- sourceSize.width: width
sourceSize.height: width
color: control.enabled ? palette.text : disabledPalette.text
source: UM.Theme.getIcon("arrow_top")
@@ -252,15 +258,15 @@ UM.Dialog
onTriggered: manager.addScriptToList(modelData.toString())
}
- onObjectAdded: scriptsMenu.insertItem(index, object);
- onObjectRemoved: scriptsMenu.removeItem(object);
+ onObjectAdded: scriptsMenu.insertItem(index, object)
+ onObjectRemoved: scriptsMenu.removeItem(object)
}
}
}
Rectangle
{
- color: UM.Theme.getColor("sidebar")
+ color: UM.Theme.getColor("main_background")
anchors.left: activeScripts.right
anchors.leftMargin: UM.Theme.getSize("default_margin").width
anchors.right: parent.right
@@ -271,26 +277,35 @@ UM.Dialog
{
id: scriptSpecsHeader
text: manager.selectedScriptIndex == -1 ? catalog.i18nc("@label", "Settings") : base.activeScriptName
- anchors.top: parent.top
- anchors.topMargin: base.textMargin
- anchors.left: parent.left
- anchors.leftMargin: base.textMargin
- anchors.right: parent.right
- anchors.rightMargin: base.textMargin
+ anchors
+ {
+ top: parent.top
+ topMargin: base.textMargin
+ left: parent.left
+ leftMargin: base.textMargin
+ right: parent.right
+ rightMargin: base.textMargin
+ }
+
elide: Text.ElideRight
height: 20 * screenScaleFactor
- font: UM.Theme.getFont("large")
+ font: UM.Theme.getFont("large_bold")
color: UM.Theme.getColor("text")
}
ScrollView
{
id: scrollView
- anchors.top: scriptSpecsHeader.bottom
- anchors.topMargin: settingsPanel.textMargin
- anchors.left: parent.left
- anchors.right: parent.right
- anchors.bottom: parent.bottom
+ anchors
+ {
+ top: scriptSpecsHeader.bottom
+ topMargin: settingsPanel.textMargin
+ left: parent.left
+ leftMargin: UM.Theme.getSize("default_margin").width
+ right: parent.right
+ bottom: parent.bottom
+ }
+
visible: manager.selectedScriptDefinitionId != ""
style: UM.Theme.styles.scrollview;
@@ -300,11 +315,12 @@ UM.Dialog
spacing: UM.Theme.getSize("default_lining").height
model: UM.SettingDefinitionsModel
{
- id: definitionsModel;
+ id: definitionsModel
containerId: manager.selectedScriptDefinitionId
showAll: true
}
- delegate:Loader
+
+ delegate: Loader
{
id: settingLoader
@@ -315,23 +331,24 @@ UM.Dialog
{
if(model.type != undefined)
{
- return UM.Theme.getSize("section").height;
+ return UM.Theme.getSize("section").height
}
else
{
- return 0;
+ return 0
}
}
else
{
- return 0;
+ return 0
}
-
}
Behavior on height { NumberAnimation { duration: 100 } }
opacity: provider.properties.enabled == "True" ? 1 : 0
+
Behavior on opacity { NumberAnimation { duration: 100 } }
enabled: opacity > 0
+
property var definition: model
property var settingDefinitionsModel: definitionsModel
property var propertyProvider: provider
@@ -342,11 +359,12 @@ UM.Dialog
//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
- settingLoader.item.doDepthIndentation = true
+ settingLoader.item.doDepthIndentation = false
settingLoader.item.doQualityUserSettingEmphasis = false
}
@@ -398,24 +416,20 @@ UM.Dialog
onShowTooltip:
{
- tooltip.text = text;
- var position = settingLoader.mapToItem(settingsPanel, settingsPanel.x, 0);
- tooltip.show(position);
+ tooltip.text = text
+ var position = settingLoader.mapToItem(settingsPanel, settingsPanel.x, 0)
+ tooltip.show(position)
tooltip.target.x = position.x + 1
}
- onHideTooltip:
- {
- tooltip.hide();
- }
+ onHideTooltip: tooltip.hide()
}
-
}
}
}
}
- Cura.SidebarTooltip
+ Cura.PrintSetupTooltip
{
id: tooltip
}
@@ -462,6 +476,7 @@ UM.Dialog
Cura.SettingUnknown { }
}
}
+
rightButtons: Button
{
text: catalog.i18nc("@action:button", "Close")
@@ -469,44 +484,15 @@ UM.Dialog
onClicked: dialog.accept()
}
- Button {
+ Cura.SecondaryButton
+ {
objectName: "postProcessingSaveAreaButton"
visible: activeScriptsList.count > 0
- height: UM.Theme.getSize("save_button_save_to_button").height
+ height: UM.Theme.getSize("action_button").height
width: height
tooltip: catalog.i18nc("@info:tooltip", "Change active post-processing scripts")
onClicked: dialog.show()
-
- style: ButtonStyle {
- background: Rectangle {
- id: deviceSelectionIcon
- border.width: UM.Theme.getSize("default_lining").width
- border.color: !control.enabled ? UM.Theme.getColor("action_button_disabled_border") :
- 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.enabled ? UM.Theme.getColor("action_button_disabled") :
- control.pressed ? UM.Theme.getColor("action_button_active") :
- control.hovered ? UM.Theme.getColor("action_button_hovered") : UM.Theme.getColor("action_button")
- Behavior on color { ColorAnimation { duration: 50; } }
- anchors.left: parent.left
- anchors.leftMargin: Math.round(UM.Theme.getSize("save_button_text_margin").width / 2);
- width: parent.height
- height: parent.height
-
- UM.RecolorImage {
- anchors.verticalCenter: parent.verticalCenter
- anchors.horizontalCenter: parent.horizontalCenter
- width: Math.round(parent.width / 2)
- height: Math.round(parent.height / 2)
- sourceSize.width: width
- sourceSize.height: height
- color: !control.enabled ? UM.Theme.getColor("action_button_disabled_text") :
- control.pressed ? UM.Theme.getColor("action_button_active_text") :
- control.hovered ? UM.Theme.getColor("action_button_hovered_text") : UM.Theme.getColor("action_button_text");
- source: "postprocessing.svg"
- }
- }
- label: Label{ }
- }
+ iconSource: "postprocessing.svg"
+ fixedWidthMode: true
}
}
\ No newline at end of file
diff --git a/plugins/PostProcessingPlugin/plugin.json b/plugins/PostProcessingPlugin/plugin.json
index fea061e93b..1e73133c53 100644
--- a/plugins/PostProcessingPlugin/plugin.json
+++ b/plugins/PostProcessingPlugin/plugin.json
@@ -1,8 +1,8 @@
{
"name": "Post Processing",
"author": "Ultimaker",
- "version": "2.2",
- "api": 5,
+ "version": "2.2.1",
+ "api": "6.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 54d6fdb155..ba7b06bb1b 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,
@@ -112,7 +112,7 @@ class ChangeAtZ(Script):
"e1_Change_speed":
{
"label": "Change Speed",
- "description": "Select if total speed (print and travel) has to be cahnged",
+ "description": "Select if total speed (print and travel) has to be changed",
"type": "bool",
"default_value": false
},
@@ -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":
@@ -407,13 +407,15 @@ class ChangeAtZ(Script):
if "M106" in line and state < 3: #looking for fan speed
old["fanSpeed"] = self.getValue(line, "S", old["fanSpeed"])
if "M221" in line and state < 3: #looking for flow rate
- tmp_extruder = self.getValue(line,"T",None)
+ 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
- old["flowrateOne"] = self.getValue(line, "S", old["flowrateOne"])
+ old["flowrateTwo"] = self.getValue(line, "S", old["flowrateTwo"])
if ("M84" in line or "M25" in line):
if state>0 and ChangeProp["speed"]: #"finish" commands for UM Original and UM2
modified_gcode += "M220 S100 ; speed reset to 100% at the end of print\n"
@@ -481,9 +483,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..25194568e7 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/ExampleScript.md b/plugins/PostProcessingPlugin/scripts/ExampleScript.md
new file mode 100644
index 0000000000..08652132aa
--- /dev/null
+++ b/plugins/PostProcessingPlugin/scripts/ExampleScript.md
@@ -0,0 +1,3 @@
+A good example script is SearchAndReplace.py.
+If you have any questions please ask them at:
+https://github.com/Ultimaker/Cura/issues
\ No newline at end of file
diff --git a/plugins/PostProcessingPlugin/scripts/ExampleScript.py b/plugins/PostProcessingPlugin/scripts/ExampleScript.py
deleted file mode 100644
index 416a5f5404..0000000000
--- a/plugins/PostProcessingPlugin/scripts/ExampleScript.py
+++ /dev/null
@@ -1,43 +0,0 @@
-# Copyright (c) 2015 Jaime van Kessel, Ultimaker B.V.
-# The PostProcessingPlugin is released under the terms of the AGPLv3 or higher.
-from ..Script import Script
-
-class ExampleScript(Script):
- def __init__(self):
- super().__init__()
-
- def getSettingDataString(self):
- return """{
- "name":"Example script",
- "key": "ExampleScript",
- "metadata": {},
- "version": 2,
- "settings":
- {
- "test":
- {
- "label": "Test",
- "description": "None",
- "unit": "mm",
- "type": "float",
- "default_value": 0.5,
- "minimum_value": "0",
- "minimum_value_warning": "0.1",
- "maximum_value_warning": "1"
- },
- "derp":
- {
- "label": "zomg",
- "description": "afgasgfgasfgasf",
- "unit": "mm",
- "type": "float",
- "default_value": 0.5,
- "minimum_value": "0",
- "minimum_value_warning": "0.1",
- "maximum_value_warning": "1"
- }
- }
- }"""
-
- def execute(self, data):
- return data
\ No newline at end of file
diff --git a/plugins/PostProcessingPlugin/scripts/FilamentChange.py b/plugins/PostProcessingPlugin/scripts/FilamentChange.py
index 0fa52de4f1..943ca30f2e 100644
--- a/plugins/PostProcessingPlugin/scripts/FilamentChange.py
+++ b/plugins/PostProcessingPlugin/scripts/FilamentChange.py
@@ -1,8 +1,7 @@
-# This PostProcessing Plugin script is released
-# under the terms of the AGPLv3 or higher
-from typing import Optional, Tuple
+# Copyright (c) 2019 Ultimaker B.V.
+# The PostProcessingPlugin is released under the terms of the AGPLv3 or higher.
-from UM.Logger import Logger
+from typing import List
from ..Script import Script
class FilamentChange(Script):
@@ -44,51 +43,60 @@ class FilamentChange(Script):
"unit": "mm",
"type": "float",
"default_value": 300.0
+ },
+ "x_position":
+ {
+ "label": "X Position",
+ "description": "Extruder X position. The print head will move here for filament change.",
+ "unit": "mm",
+ "type": "float",
+ "default_value": 0
+ },
+ "y_position":
+ {
+ "label": "Y Position",
+ "description": "Extruder Y position. The print head will move here for filament change.",
+ "unit": "mm",
+ "type": "float",
+ "default_value": 0
}
}
}"""
- 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")
-
+ x_pos = self.getSettingValueByKey("x_position")
+ y_pos = self.getSettingValueByKey("y_position")
+
color_change = "M600"
-
+
if initial_retract is not None and initial_retract > 0.:
- color_change = color_change + (" E-%.2f" % initial_retract)
-
+ color_change = color_change + (" E%.2f" % initial_retract)
+
if later_retract is not None and later_retract > 0.:
- color_change = color_change + (" L-%.2f" % later_retract)
-
- color_change = color_change + " ; Generated by FilamentChange plugin"
-
+ color_change = color_change + (" L%.2f" % later_retract)
+
+ if x_pos is not None:
+ color_change = color_change + (" X%.2f" % x_pos)
+
+ if y_pos is not None:
+ color_change = color_change + (" Y%.2f" % y_pos)
+
+ 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
new file mode 100644
index 0000000000..c21993aad1
--- /dev/null
+++ b/plugins/PostProcessingPlugin/scripts/InsertAtLayerChange.py
@@ -0,0 +1,50 @@
+# Created by Wayne Porter
+
+from ..Script import Script
+
+class InsertAtLayerChange(Script):
+ def __init__(self):
+ super().__init__()
+
+ def getSettingDataString(self):
+ return """{
+ "name": "Insert at layer change",
+ "key": "InsertAtLayerChange",
+ "metadata": {},
+ "version": 2,
+ "settings":
+ {
+ "insert_location":
+ {
+ "label": "When to insert",
+ "description": "Whether to insert code before or after layer change.",
+ "type": "enum",
+ "options": {"before": "Before", "after": "After"},
+ "default_value": "before"
+ },
+ "gcode_to_add":
+ {
+ "label": "GCODE to insert.",
+ "description": "GCODE to add before or after layer change.",
+ "type": "str",
+ "default_value": ""
+ }
+ }
+ }"""
+
+ def execute(self, data):
+ gcode_to_add = self.getSettingValueByKey("gcode_to_add") + "\n"
+ for layer in data:
+ # Check that a layer is being printed
+ lines = layer.split("\n")
+ 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/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
new file mode 100644
index 0000000000..36d0f6a058
--- /dev/null
+++ b/plugins/PostProcessingPlugin/scripts/TimeLapse.py
@@ -0,0 +1,95 @@
+# Created by Wayne Porter
+
+from ..Script import Script
+
+class TimeLapse(Script):
+ def __init__(self):
+ super().__init__()
+
+ def getSettingDataString(self):
+ return """{
+ "name": "Time Lapse",
+ "key": "TimeLapse",
+ "metadata": {},
+ "version": 2,
+ "settings":
+ {
+ "trigger_command":
+ {
+ "label": "Trigger camera command",
+ "description": "Gcode command used to trigger camera.",
+ "type": "str",
+ "default_value": "M240"
+ },
+ "pause_length":
+ {
+ "label": "Pause length",
+ "description": "How long to wait (in ms) after camera was triggered.",
+ "type": "int",
+ "default_value": 700,
+ "minimum_value": 0,
+ "unit": "ms"
+ },
+ "park_print_head":
+ {
+ "label": "Park Print Head",
+ "description": "Park the print head out of the way. Assumes absolute positioning.",
+ "type": "bool",
+ "default_value": true
+ },
+ "head_park_x":
+ {
+ "label": "Park Print Head X",
+ "description": "What X location does the head move to for photo.",
+ "unit": "mm",
+ "type": "float",
+ "default_value": 0,
+ "enabled": "park_print_head"
+ },
+ "head_park_y":
+ {
+ "label": "Park Print Head Y",
+ "description": "What Y location does the head move to for photo.",
+ "unit": "mm",
+ "type": "float",
+ "default_value": 190,
+ "enabled": "park_print_head"
+ },
+ "park_feed_rate":
+ {
+ "label": "Park Feed Rate",
+ "description": "How fast does the head move to the park coordinates.",
+ "unit": "mm/s",
+ "type": "float",
+ "default_value": 9000,
+ "enabled": "park_print_head"
+ }
+ }
+ }"""
+
+ def execute(self, data):
+ feed_rate = self.getSettingValueByKey("park_feed_rate")
+ park_print_head = self.getSettingValueByKey("park_print_head")
+ x_park = self.getSettingValueByKey("head_park_x")
+ y_park = self.getSettingValueByKey("head_park_y")
+ trigger_command = self.getSettingValueByKey("trigger_command")
+ pause_length = self.getSettingValueByKey("pause_length")
+ 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 += ";TimeLapse End\n"
+ for layer in data:
+ # Check that a layer is being printed
+ lines = layer.split("\n")
+ 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/PrepareMain.qml b/plugins/PrepareStage/PrepareMain.qml
new file mode 100644
index 0000000000..bfeb62f0e8
--- /dev/null
+++ b/plugins/PrepareStage/PrepareMain.qml
@@ -0,0 +1,24 @@
+//Copyright (c) 2019 Ultimaker B.V.
+//Cura is released under the terms of the LGPLv3 or higher.
+
+import QtQuick 2.4
+import QtQuick.Controls 1.2
+import QtQuick.Layouts 1.1
+import QtQuick.Controls.Styles 1.1
+
+import UM 1.0 as UM
+import Cura 1.0 as Cura
+
+Item
+{
+ id: prepareMain
+
+ Cura.ActionPanelWidget
+ {
+ id: actionPanelWidget
+ anchors.right: parent.right
+ anchors.bottom: parent.bottom
+ anchors.rightMargin: UM.Theme.getSize("thick_margin").width
+ anchors.bottomMargin: UM.Theme.getSize("thick_margin").height
+ }
+}
\ No newline at end of file
diff --git a/plugins/PrepareStage/PrepareMenu.qml b/plugins/PrepareStage/PrepareMenu.qml
new file mode 100644
index 0000000000..87d7c5f35c
--- /dev/null
+++ b/plugins/PrepareStage/PrepareMenu.qml
@@ -0,0 +1,143 @@
+// Copyright (c) 2018 Ultimaker B.V.
+// Cura is released under the terms of the LGPLv3 or higher.
+
+import QtQuick 2.7
+import QtQuick.Layouts 1.1
+import QtQuick.Controls 2.3
+
+import UM 1.3 as UM
+import Cura 1.1 as Cura
+
+import QtGraphicalEffects 1.0 // For the dropshadow
+
+Item
+{
+ id: prepareMenu
+
+ UM.I18nCatalog
+ {
+ id: catalog
+ 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: parent.width - 2 * UM.Theme.getSize("wide_margin").width
+ height: parent.height
+
+ RowLayout
+ {
+ id: itemRow
+
+ anchors.left: openFileButton.right
+ anchors.right: parent.right
+ anchors.leftMargin: UM.Theme.getSize("default_margin").width
+
+ height: parent.height
+ spacing: 0
+
+ Cura.MachineSelector
+ {
+ id: machineSelection
+ headerCornerSide: Cura.RoundedRectangle.Direction.Left
+ Layout.minimumWidth: UM.Theme.getSize("machine_selector_widget").width
+ Layout.maximumWidth: UM.Theme.getSize("machine_selector_widget").width
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+ }
+
+ // Separator line
+ Rectangle
+ {
+ height: parent.height
+ width: UM.Theme.getSize("default_lining").width
+ color: UM.Theme.getColor("lining")
+ }
+
+ Cura.ConfigurationMenu
+ {
+ id: printerSetup
+ Layout.fillHeight: true
+ Layout.fillWidth: true
+ Layout.preferredWidth: itemRow.width - machineSelection.width - printSetupSelectorItem.width - 2 * UM.Theme.getSize("default_lining").width
+ }
+
+ // Separator line
+ Rectangle
+ {
+ height: parent.height
+ width: UM.Theme.getSize("default_lining").width
+ color: UM.Theme.getColor("lining")
+ }
+
+ Item
+ {
+ id: printSetupSelectorItem
+ // This is a work around to prevent the printSetupSelector from having to be re-loaded every time
+ // a stage switch is done.
+ children: [printSetupSelector]
+ height: childrenRect.height
+ width: childrenRect.width
+ }
+ }
+
+ Button
+ {
+ id: openFileButton
+ height: UM.Theme.getSize("stage_menu").height
+ width: UM.Theme.getSize("stage_menu").height
+ onClicked: Cura.Actions.open.trigger()
+ hoverEnabled: true
+
+ contentItem: Item
+ {
+ anchors.fill: parent
+ UM.RecolorImage
+ {
+ id: buttonIcon
+ anchors.centerIn: parent
+ source: UM.Theme.getIcon("load")
+ width: UM.Theme.getSize("button_icon").width
+ height: UM.Theme.getSize("button_icon").height
+ color: UM.Theme.getColor("icon")
+
+ sourceSize.height: height
+ }
+ }
+
+ background: Rectangle
+ {
+ id: background
+ height: UM.Theme.getSize("stage_menu").height
+ width: UM.Theme.getSize("stage_menu").height
+
+ radius: UM.Theme.getSize("default_radius").width
+ color: openFileButton.hovered ? UM.Theme.getColor("action_button_hovered") : UM.Theme.getColor("action_button")
+ }
+
+ DropShadow
+ {
+ id: shadow
+ // Don't blur the shadow
+ radius: 0
+ anchors.fill: background
+ source: background
+ verticalOffset: 2
+ visible: true
+ color: UM.Theme.getColor("action_button_shadow")
+ // Should always be drawn behind the background.
+ z: background.z - 1
+ }
+ }
+ }
+}
diff --git a/plugins/PrepareStage/PrepareStage.py b/plugins/PrepareStage/PrepareStage.py
index c3c9f0a1f8..c2dee9693b 100644
--- a/plugins/PrepareStage/PrepareStage.py
+++ b/plugins/PrepareStage/PrepareStage.py
@@ -1,19 +1,19 @@
-# Copyright (c) 2017 Ultimaker B.V.
+# Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
+
import os.path
from UM.Application import Application
-from UM.Resources import Resources
+from UM.PluginRegistry import PluginRegistry
from cura.Stages.CuraStage import CuraStage
-
## Stage for preparing model (slicing).
class PrepareStage(CuraStage):
-
def __init__(self, parent = None):
super().__init__(parent)
Application.getInstance().engineCreatedSignal.connect(self._engineCreated)
def _engineCreated(self):
- sidebar_component_path = os.path.join(Resources.getPath(Application.getInstance().ResourceTypes.QmlFiles),
- "PrepareSidebar.qml")
- self.addDisplayComponent("sidebar", sidebar_component_path)
+ menu_component_path = os.path.join(PluginRegistry.getInstance().getPluginPath("PrepareStage"), "PrepareMenu.qml")
+ main_component_path = os.path.join(PluginRegistry.getInstance().getPluginPath("PrepareStage"), "PrepareMain.qml")
+ self.addDisplayComponent("menu", menu_component_path)
+ self.addDisplayComponent("main", main_component_path)
\ No newline at end of file
diff --git a/plugins/PrepareStage/plugin.json b/plugins/PrepareStage/plugin.json
index f0464313c7..dc5c68ce16 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.0",
+ "version": "1.0.1",
"description": "Provides a prepare stage in Cura.",
- "api": 5,
+ "api": "6.0",
"i18n-catalog": "cura"
}
\ No newline at end of file
diff --git a/plugins/PreviewStage/PreviewMain.qml b/plugins/PreviewStage/PreviewMain.qml
new file mode 100644
index 0000000000..6b5ce2436b
--- /dev/null
+++ b/plugins/PreviewStage/PreviewMain.qml
@@ -0,0 +1,31 @@
+// Copyright (c) 2019 Ultimaker B.V.
+// Cura is released under the terms of the LGPLv3 or higher.
+
+import QtQuick 2.4
+import QtQuick.Controls 1.2
+import QtQuick.Layouts 1.1
+import QtQuick.Controls.Styles 1.1
+
+import UM 1.0 as UM
+import Cura 1.0 as Cura
+
+Item
+{
+ Loader
+ {
+ id: previewMain
+ anchors.fill: parent
+
+ source: UM.Controller.activeView != null && UM.Controller.activeView.mainComponent != null ? UM.Controller.activeView.mainComponent : ""
+ }
+
+ Cura.ActionPanelWidget
+ {
+ id: actionPanelWidget
+ anchors.right: parent.right
+ anchors.bottom: parent.bottom
+ anchors.rightMargin: UM.Theme.getSize("thick_margin").width
+ anchors.bottomMargin: UM.Theme.getSize("thick_margin").height
+ hasPreviewButton: false
+ }
+}
\ No newline at end of file
diff --git a/plugins/PreviewStage/PreviewMenu.qml b/plugins/PreviewStage/PreviewMenu.qml
new file mode 100644
index 0000000000..ff1ccff75f
--- /dev/null
+++ b/plugins/PreviewStage/PreviewMenu.qml
@@ -0,0 +1,85 @@
+// Copyright (c) 2018 Ultimaker B.V.
+// Cura is released under the terms of the LGPLv3 or higher.
+
+import QtQuick 2.7
+import QtQuick.Layouts 1.1
+import QtQuick.Controls 2.3
+
+import UM 1.3 as UM
+import Cura 1.1 as Cura
+
+Item
+{
+ id: previewMenu
+
+ property real itemHeight: height - 2 * UM.Theme.getSize("default_lining").width
+
+ UM.I18nCatalog
+ {
+ id: catalog
+ 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.horizontalCenter: parent.horizontalCenter
+ width: parent.width - 2 * UM.Theme.getSize("wide_margin").width
+ height: parent.height
+
+ Cura.ViewsSelector
+ {
+ id: viewsSelector
+ height: parent.height
+ width: UM.Theme.getSize("views_selector").width
+ headerCornerSide: Cura.RoundedRectangle.Direction.Left
+ }
+
+ // Separator line
+ Rectangle
+ {
+ height: parent.height
+ // If there is no viewPanel, we only need a single spacer, so hide this one.
+ visible: viewPanel.source != ""
+ width: visible ? UM.Theme.getSize("default_lining").width : 0
+
+ color: UM.Theme.getColor("lining")
+ }
+
+ // This component will grow freely up to complete the width of the row.
+ Loader
+ {
+ id: viewPanel
+ height: parent.height
+ 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 : ""
+ }
+
+ // Separator line
+ Rectangle
+ {
+ height: parent.height
+ width: UM.Theme.getSize("default_lining").width
+ color: UM.Theme.getColor("lining")
+ }
+
+ Item
+ {
+ id: printSetupSelectorItem
+ // This is a work around to prevent the printSetupSelector from having to be re-loaded every time
+ // a stage switch is done.
+ children: [printSetupSelector]
+ height: childrenRect.height
+ width: childrenRect.width
+ }
+ }
+}
diff --git a/plugins/PreviewStage/PreviewStage.py b/plugins/PreviewStage/PreviewStage.py
new file mode 100644
index 0000000000..1c487c8340
--- /dev/null
+++ b/plugins/PreviewStage/PreviewStage.py
@@ -0,0 +1,51 @@
+# Copyright (c) 2018 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+
+import os.path
+
+from UM.Qt.QtApplication import QtApplication
+from cura.Stages.CuraStage import CuraStage
+
+from typing import TYPE_CHECKING, Optional
+
+if TYPE_CHECKING:
+ from UM.View.View import View
+
+
+## Displays a preview of what you're about to print.
+#
+# The Python component of this stage just loads PreviewMain.qml for display
+# when the stage is selected, and makes sure that it reverts to the previous
+# view when the previous stage is activated.
+class PreviewStage(CuraStage):
+ def __init__(self, application: QtApplication, parent = None) -> None:
+ super().__init__(parent)
+ self._application = application
+ self._application.engineCreatedSignal.connect(self._engineCreated)
+ self._previously_active_view = None # type: Optional[View]
+
+ ## When selecting the stage, remember which was the previous view so that
+ # we can revert to that view when we go out of the stage later.
+ def onStageSelected(self) -> None:
+ self._previously_active_view = self._application.getController().getActiveView()
+
+ ## Called when going to a different stage (away from the Preview Stage).
+ #
+ # When going to a different stage, the view should be reverted to what it
+ # was before. Normally, that just reverts it to solid view.
+ def onStageDeselected(self) -> None:
+ if self._previously_active_view is not None:
+ self._application.getController().setActiveView(self._previously_active_view.getPluginId())
+ self._previously_active_view = None
+
+ ## Delayed load of the QML files.
+ #
+ # We need to make sure that the QML engine is running before we can load
+ # these.
+ def _engineCreated(self) -> None:
+ plugin_path = self._application.getPluginRegistry().getPluginPath(self.getPluginId())
+ if plugin_path is not None:
+ menu_component_path = os.path.join(plugin_path, "PreviewMenu.qml")
+ main_component_path = os.path.join(plugin_path, "PreviewMain.qml")
+ self.addDisplayComponent("menu", menu_component_path)
+ self.addDisplayComponent("main", main_component_path)
diff --git a/plugins/PreviewStage/__init__.py b/plugins/PreviewStage/__init__.py
new file mode 100644
index 0000000000..424f573e4a
--- /dev/null
+++ b/plugins/PreviewStage/__init__.py
@@ -0,0 +1,22 @@
+# Copyright (c) 2018 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+
+from . import PreviewStage
+
+from UM.i18n import i18nCatalog
+i18n_catalog = i18nCatalog("cura")
+
+
+def getMetaData():
+ return {
+ "stage": {
+ "name": i18n_catalog.i18nc("@item:inmenu", "Preview"),
+ "weight": 1
+ }
+ }
+
+
+def register(app):
+ return {
+ "stage": PreviewStage.PreviewStage(app)
+ }
diff --git a/plugins/PreviewStage/plugin.json b/plugins/PreviewStage/plugin.json
new file mode 100644
index 0000000000..e1e4288bae
--- /dev/null
+++ b/plugins/PreviewStage/plugin.json
@@ -0,0 +1,8 @@
+{
+ "name": "Preview Stage",
+ "author": "Ultimaker B.V.",
+ "version": "1.0.1",
+ "description": "Provides a preview stage in Cura.",
+ "api": "6.0",
+ "i18n-catalog": "cura"
+}
\ No newline at end of file
diff --git a/plugins/RemovableDriveOutputDevice/plugin.json b/plugins/RemovableDriveOutputDevice/plugin.json
index 36bb9ae186..5523d6b1c1 100644
--- a/plugins/RemovableDriveOutputDevice/plugin.json
+++ b/plugins/RemovableDriveOutputDevice/plugin.json
@@ -2,7 +2,7 @@
"name": "Removable Drive Output Device Plugin",
"author": "Ultimaker B.V.",
"description": "Provides removable drive hotplugging and writing support.",
- "version": "1.0.0",
- "api": 5,
+ "version": "1.0.1",
+ "api": "6.0",
"i18n-catalog": "cura"
}
diff --git a/plugins/SimulationView/LayerSlider.qml b/plugins/SimulationView/LayerSlider.qml
index 1552506969..88f298d1f5 100644
--- a/plugins/SimulationView/LayerSlider.qml
+++ b/plugins/SimulationView/LayerSlider.qml
@@ -13,23 +13,20 @@ Item
{
id: sliderRoot
- // handle properties
- property real handleSize: 10
+ // Handle properties
+ property real handleSize: UM.Theme.getSize("slider_handle").width
property real handleRadius: handleSize / 2
property real minimumRangeHandleSize: handleSize / 2
- property color upperHandleColor: "black"
- property color lowerHandleColor: "black"
- property color rangeHandleColor: "black"
- property color handleActiveColor: "white"
- property real handleLabelWidth: width
+ property color upperHandleColor: UM.Theme.getColor("slider_handle")
+ property color lowerHandleColor: UM.Theme.getColor("slider_handle")
+ property color rangeHandleColor: UM.Theme.getColor("slider_groove_fill")
+ property color handleActiveColor: UM.Theme.getColor("slider_handle_active")
property var activeHandle: upperHandle
- // track properties
- property real trackThickness: 4 // width of the slider track
- property real trackRadius: trackThickness / 2
- property color trackColor: "white"
- property real trackBorderWidth: 1 // width of the slider track border
- property color trackBorderColor: "black"
+ // Track properties
+ property real trackThickness: UM.Theme.getSize("slider_groove").width // width of the slider track
+ property real trackRadius: UM.Theme.getSize("slider_groove_radius").width
+ property color trackColor: UM.Theme.getColor("slider_groove")
// value properties
property real maximumValue: 100
@@ -80,7 +77,7 @@ Item
return Math.min(Math.max(value, sliderRoot.minimumValue), sliderRoot.maximumValue)
}
- // slider track
+ // Slider track
Rectangle
{
id: track
@@ -90,8 +87,6 @@ Item
radius: sliderRoot.trackRadius
anchors.centerIn: sliderRoot
color: sliderRoot.trackColor
- border.width: sliderRoot.trackBorderWidth
- border.color: sliderRoot.trackBorderColor
visible: sliderRoot.layersVisible
}
@@ -106,7 +101,7 @@ Item
anchors.horizontalCenter: sliderRoot.horizontalCenter
visible: sliderRoot.layersVisible
- // set the new value when dragging
+ // Set the new value when dragging
function onHandleDragged()
{
sliderRoot.manuallyChanged = true
@@ -140,9 +135,10 @@ Item
Rectangle
{
- width: sliderRoot.trackThickness - 2 * sliderRoot.trackBorderWidth
+ width: sliderRoot.trackThickness
height: parent.height + sliderRoot.handleSize
anchors.centerIn: parent
+ radius: sliderRoot.trackRadius
color: sliderRoot.rangeHandleColor
}
@@ -275,7 +271,7 @@ Item
id: upperHandleLabel
height: sliderRoot.handleSize + UM.Theme.getSize("default_margin").height
- x: parent.x - width - UM.Theme.getSize("default_margin").width
+ x: parent.x - parent.width - width
anchors.verticalCenter: parent.verticalCenter
target: Qt.point(sliderRoot.width, y + height / 2)
visible: sliderRoot.activeHandle == parent
@@ -385,9 +381,9 @@ Item
id: lowerHandleLabel
height: sliderRoot.handleSize + UM.Theme.getSize("default_margin").height
- x: parent.x - width - UM.Theme.getSize("default_margin").width
+ x: parent.x - parent.width - width
anchors.verticalCenter: parent.verticalCenter
- target: Qt.point(sliderRoot.width, y + height / 2)
+ target: Qt.point(sliderRoot.width + width, y + height / 2)
visible: sliderRoot.activeHandle == parent
// custom properties
diff --git a/plugins/SimulationView/PathSlider.qml b/plugins/SimulationView/PathSlider.qml
index f3c28fb5f7..c7a43c6407 100644
--- a/plugins/SimulationView/PathSlider.qml
+++ b/plugins/SimulationView/PathSlider.qml
@@ -14,19 +14,17 @@ Item
id: sliderRoot
// handle properties
- property real handleSize: 10
+ property real handleSize: UM.Theme.getSize("slider_handle").width
property real handleRadius: handleSize / 2
- property color handleColor: "black"
- property color handleActiveColor: "white"
- property color rangeColor: "black"
+ property color handleColor: UM.Theme.getColor("slider_handle")
+ property color handleActiveColor: UM.Theme.getColor("slider_handle_active")
+ property color rangeColor: UM.Theme.getColor("slider_groove_fill")
property real handleLabelWidth: width
// track properties
- property real trackThickness: 4 // width of the slider track
- property real trackRadius: trackThickness / 2
- property color trackColor: "white"
- property real trackBorderWidth: 1 // width of the slider track border
- property color trackBorderColor: "black"
+ property real trackThickness: UM.Theme.getSize("slider_groove").width
+ property real trackRadius: UM.Theme.getSize("slider_groove_radius").width
+ property color trackColor: UM.Theme.getColor("slider_groove")
// value properties
property real maximumValue: 100
@@ -68,8 +66,6 @@ Item
radius: sliderRoot.trackRadius
anchors.centerIn: sliderRoot
color: sliderRoot.trackColor
- border.width: sliderRoot.trackBorderWidth
- border.color: sliderRoot.trackBorderColor
visible: sliderRoot.pathsVisible
}
@@ -86,9 +82,10 @@ Item
Rectangle
{
- height: sliderRoot.trackThickness - 2 * sliderRoot.trackBorderWidth
+ height: sliderRoot.trackThickness
width: parent.width + sliderRoot.handleSize
anchors.centerIn: parent
+ radius: sliderRoot.trackRadius
color: sliderRoot.rangeColor
}
}
diff --git a/plugins/SimulationView/SimulationSliderLabel.qml b/plugins/SimulationView/SimulationSliderLabel.qml
index b69fede243..06c6a51b44 100644
--- a/plugins/SimulationView/SimulationSliderLabel.qml
+++ b/plugins/SimulationView/SimulationSliderLabel.qml
@@ -48,7 +48,7 @@ UM.PointingRectangle {
horizontalCenter: parent.horizontalCenter
}
- width: (maximumValue.toString().length + 1) * 10 * screenScaleFactor
+ width: ((maximumValue + 1).toString().length + 1) * 10 * screenScaleFactor
text: sliderLabelRoot.value + startFrom // the current handle value, add 1 because layers is an array
horizontalAlignment: TextInput.AlignRight
diff --git a/plugins/SimulationView/SimulationView.py b/plugins/SimulationView/SimulationView.py
index 0ae8b4d9e4..20471f9763 100644
--- a/plugins/SimulationView/SimulationView.py
+++ b/plugins/SimulationView/SimulationView.py
@@ -16,6 +16,7 @@ from UM.Mesh.MeshBuilder import MeshBuilder
from UM.Message import Message
from UM.Platform import Platform
from UM.PluginRegistry import PluginRegistry
+from UM.Qt.QtApplication import QtApplication
from UM.Resources import Resources
from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator
@@ -26,8 +27,8 @@ from UM.View.GL.OpenGL import OpenGL
from UM.View.GL.OpenGLContext import OpenGLContext
from UM.View.GL.ShaderProgram import ShaderProgram
-from UM.View.View import View
from UM.i18n import i18nCatalog
+from cura.CuraView import CuraView
from cura.Scene.ConvexHullNode import ConvexHullNode
from cura.CuraApplication import CuraApplication
@@ -48,15 +49,15 @@ catalog = i18nCatalog("cura")
## View used to display g-code paths.
-class SimulationView(View):
- # Must match SimulationView.qml
+class SimulationView(CuraView):
+ # Must match SimulationViewMenuComponent.qml
LAYER_VIEW_TYPE_MATERIAL_TYPE = 0
LAYER_VIEW_TYPE_LINE_TYPE = 1
LAYER_VIEW_TYPE_FEEDRATE = 2
LAYER_VIEW_TYPE_THICKNESS = 3
- def __init__(self) -> None:
- super().__init__()
+ def __init__(self, parent = None) -> None:
+ super().__init__(parent)
self._max_layers = 0
self._current_layer_num = 0
@@ -113,6 +114,16 @@ class SimulationView(View):
self._wireprint_warning_message = Message(catalog.i18nc("@info:status", "Cura does not accurately display layers when Wire Printing is enabled"),
title = catalog.i18nc("@info:title", "Simulation View"))
+ QtApplication.getInstance().engineCreatedSignal.connect(self._onEngineCreated)
+
+ def _onEngineCreated(self) -> None:
+ plugin_path = PluginRegistry.getInstance().getPluginPath(self.getPluginId())
+ if plugin_path:
+ self.addDisplayComponent("main", os.path.join(plugin_path, "SimulationViewMainComponent.qml"))
+ self.addDisplayComponent("menu", os.path.join(plugin_path, "SimulationViewMenuComponent.qml"))
+ else:
+ Logger.log("e", "Unable to find the path for %s", self.getPluginId())
+
def _evaluateCompatibilityMode(self) -> bool:
return OpenGLContext.isLegacyOpenGL() or bool(Application.getInstance().getPreferences().getValue("view/force_layer_view_compatibility_mode"))
@@ -207,10 +218,10 @@ class SimulationView(View):
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):
@@ -331,12 +342,16 @@ class SimulationView(View):
return self._extruder_count
def getMinFeedrate(self) -> float:
+ if abs(self._min_feedrate - sys.float_info.max) < 10: # Some lenience due to floating point rounding.
+ return 0.0 # If it's still max-float, there are no measurements. Use 0 then.
return self._min_feedrate
def getMaxFeedrate(self) -> float:
return self._max_feedrate
def getMinThickness(self) -> float:
+ if abs(self._min_thickness - sys.float_info.max) < 10: # Some lenience due to floating point rounding.
+ return 0.0 # If it's still max-float, there are no measurements. Use 0 then.
return self._min_thickness
def getMaxThickness(self) -> float:
@@ -557,14 +572,14 @@ class SimulationView(View):
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/SimulationView.qml b/plugins/SimulationView/SimulationView.qml
deleted file mode 100644
index be124157fb..0000000000
--- a/plugins/SimulationView/SimulationView.qml
+++ /dev/null
@@ -1,808 +0,0 @@
-// Copyright (c) 2018 Ultimaker B.V.
-// Cura is released under the terms of the LGPLv3 or higher.
-
-import QtQuick 2.4
-import QtQuick.Controls 1.2
-import QtQuick.Layouts 1.1
-import QtQuick.Controls.Styles 1.1
-
-import UM 1.0 as UM
-import Cura 1.0 as Cura
-
-Item
-{
- id: base
- width:
- {
- if (UM.SimulationView.compatibilityMode)
- {
- return UM.Theme.getSize("layerview_menu_size_compatibility").width;
- }
- else
- {
- return UM.Theme.getSize("layerview_menu_size").width;
- }
- }
- height: {
- if (viewSettings.collapsed)
- {
- if (UM.SimulationView.compatibilityMode)
- {
- return UM.Theme.getSize("layerview_menu_size_compatibility_collapsed").height;
- }
- return UM.Theme.getSize("layerview_menu_size_collapsed").height;
- }
- else if (UM.SimulationView.compatibilityMode)
- {
- return UM.Theme.getSize("layerview_menu_size_compatibility").height;
- }
- else if (UM.Preferences.getValue("layerview/layer_view_type") == 0)
- {
- return UM.Theme.getSize("layerview_menu_size_material_color_mode").height + UM.SimulationView.extruderCount * (UM.Theme.getSize("layerview_row").height + UM.Theme.getSize("layerview_row_spacing").height)
- }
- else
- {
- return UM.Theme.getSize("layerview_menu_size").height + UM.SimulationView.extruderCount * (UM.Theme.getSize("layerview_row").height + UM.Theme.getSize("layerview_row_spacing").height)
- }
- }
- Behavior on height { NumberAnimation { duration: 100 } }
-
- property var buttonTarget:
- {
- if(parent != null)
- {
- var force_binding = parent.y; // ensure this gets reevaluated when the panel moves
- return base.mapFromItem(parent.parent, parent.buttonTarget.x, parent.buttonTarget.y)
- }
- return Qt.point(0,0)
- }
-
- Rectangle
- {
- id: layerViewMenu
- anchors.right: parent.right
- anchors.top: parent.top
- width: parent.width
- height: parent.height
- clip: true
- z: layerSlider.z - 1
- color: UM.Theme.getColor("tool_panel_background")
- border.width: UM.Theme.getSize("default_lining").width
- border.color: UM.Theme.getColor("lining")
-
- Button {
- id: collapseButton
- anchors.top: parent.top
- anchors.topMargin: Math.round(UM.Theme.getSize("default_margin").height + (UM.Theme.getSize("layerview_row").height - UM.Theme.getSize("default_margin").height) / 2)
- anchors.right: parent.right
- anchors.rightMargin: UM.Theme.getSize("default_margin").width
-
- width: UM.Theme.getSize("standard_arrow").width
- height: UM.Theme.getSize("standard_arrow").height
-
- onClicked: viewSettings.collapsed = !viewSettings.collapsed
-
- style: ButtonStyle
- {
- background: UM.RecolorImage
- {
- width: control.width
- height: control.height
- sourceSize.width: width
- sourceSize.height: width
- color: UM.Theme.getColor("setting_control_text")
- source: viewSettings.collapsed ? UM.Theme.getIcon("arrow_left") : UM.Theme.getIcon("arrow_bottom")
- }
- label: Label{ }
- }
- }
-
- ColumnLayout
- {
- id: viewSettings
-
- property bool collapsed: false
- property var extruder_opacities: UM.Preferences.getValue("layerview/extruder_opacities").split("|")
- property bool show_travel_moves: UM.Preferences.getValue("layerview/show_travel_moves")
- property bool show_helpers: UM.Preferences.getValue("layerview/show_helpers")
- property bool show_skin: UM.Preferences.getValue("layerview/show_skin")
- property bool show_infill: UM.Preferences.getValue("layerview/show_infill")
- // if we are in compatibility mode, we only show the "line type"
- property bool show_legend: UM.SimulationView.compatibilityMode ? true : UM.Preferences.getValue("layerview/layer_view_type") == 1
- property bool show_gradient: UM.SimulationView.compatibilityMode ? false : UM.Preferences.getValue("layerview/layer_view_type") == 2 || UM.Preferences.getValue("layerview/layer_view_type") == 3
- property bool show_feedrate_gradient: show_gradient && UM.Preferences.getValue("layerview/layer_view_type") == 2
- property bool show_thickness_gradient: show_gradient && UM.Preferences.getValue("layerview/layer_view_type") == 3
- property bool only_show_top_layers: UM.Preferences.getValue("view/only_show_top_layers")
- property int top_layer_count: UM.Preferences.getValue("view/top_layer_count")
-
- anchors.top: parent.top
- anchors.topMargin: UM.Theme.getSize("default_margin").height
- anchors.left: parent.left
- anchors.leftMargin: UM.Theme.getSize("default_margin").width
- anchors.right: parent.right
- anchors.rightMargin: UM.Theme.getSize("default_margin").width
- spacing: UM.Theme.getSize("layerview_row_spacing").height
-
- Label
- {
- id: layerViewTypesLabel
- anchors.left: parent.left
- text: catalog.i18nc("@label","Color scheme")
- font: UM.Theme.getFont("default");
- visible: !UM.SimulationView.compatibilityMode
- Layout.fillWidth: true
- color: UM.Theme.getColor("setting_control_text")
- }
-
- ListModel // matches SimulationView.py
- {
- id: layerViewTypes
- }
-
- Component.onCompleted:
- {
- layerViewTypes.append({
- text: catalog.i18nc("@label:listbox", "Material Color"),
- type_id: 0
- })
- layerViewTypes.append({
- text: catalog.i18nc("@label:listbox", "Line Type"),
- type_id: 1
- })
- layerViewTypes.append({
- text: catalog.i18nc("@label:listbox", "Feedrate"),
- type_id: 2
- })
- layerViewTypes.append({
- text: catalog.i18nc("@label:listbox", "Layer thickness"),
- type_id: 3 // these ids match the switching in the shader
- })
- }
-
- ComboBox
- {
- id: layerTypeCombobox
- anchors.left: parent.left
- Layout.fillWidth: true
- Layout.preferredWidth: UM.Theme.getSize("layerview_row").width
- model: layerViewTypes
- visible: !UM.SimulationView.compatibilityMode
- style: UM.Theme.styles.combobox
- anchors.right: parent.right
-
- onActivated:
- {
- UM.Preferences.setValue("layerview/layer_view_type", index);
- }
-
- Component.onCompleted:
- {
- currentIndex = UM.SimulationView.compatibilityMode ? 1 : UM.Preferences.getValue("layerview/layer_view_type");
- updateLegends(currentIndex);
- }
-
- function updateLegends(type_id)
- {
- // update visibility of legends
- viewSettings.show_legend = UM.SimulationView.compatibilityMode || (type_id == 1);
- viewSettings.show_gradient = !UM.SimulationView.compatibilityMode && (type_id == 2 || type_id == 3);
- viewSettings.show_feedrate_gradient = viewSettings.show_gradient && (type_id == 2);
- viewSettings.show_thickness_gradient = viewSettings.show_gradient && (type_id == 3);
- }
- }
-
- Label
- {
- id: compatibilityModeLabel
- anchors.left: parent.left
- text: catalog.i18nc("@label","Compatibility Mode")
- font: UM.Theme.getFont("default")
- color: UM.Theme.getColor("text")
- visible: UM.SimulationView.compatibilityMode
- Layout.fillWidth: true
- Layout.preferredHeight: UM.Theme.getSize("layerview_row").height
- Layout.preferredWidth: UM.Theme.getSize("layerview_row").width
- }
-
- Item
- {
- height: Math.round(UM.Theme.getSize("default_margin").width / 2)
- width: width
- }
-
- Connections
- {
- target: UM.Preferences
- onPreferenceChanged:
- {
- layerTypeCombobox.currentIndex = UM.SimulationView.compatibilityMode ? 1 : UM.Preferences.getValue("layerview/layer_view_type");
- layerTypeCombobox.updateLegends(layerTypeCombobox.currentIndex);
- playButton.pauseSimulation();
- viewSettings.extruder_opacities = UM.Preferences.getValue("layerview/extruder_opacities").split("|");
- viewSettings.show_travel_moves = UM.Preferences.getValue("layerview/show_travel_moves");
- viewSettings.show_helpers = UM.Preferences.getValue("layerview/show_helpers");
- viewSettings.show_skin = UM.Preferences.getValue("layerview/show_skin");
- viewSettings.show_infill = UM.Preferences.getValue("layerview/show_infill");
- viewSettings.only_show_top_layers = UM.Preferences.getValue("view/only_show_top_layers");
- viewSettings.top_layer_count = UM.Preferences.getValue("view/top_layer_count");
- }
- }
-
- Repeater
- {
- model: Cura.ExtrudersModel{}
- CheckBox
- {
- id: extrudersModelCheckBox
- checked: viewSettings.extruder_opacities[index] > 0.5 || viewSettings.extruder_opacities[index] == undefined || viewSettings.extruder_opacities[index] == ""
- onClicked:
- {
- viewSettings.extruder_opacities[index] = checked ? 1.0 : 0.0
- UM.Preferences.setValue("layerview/extruder_opacities", viewSettings.extruder_opacities.join("|"));
- }
- visible: !UM.SimulationView.compatibilityMode
- enabled: index + 1 <= 4
- Rectangle
- {
- anchors.verticalCenter: parent.verticalCenter
- anchors.right: extrudersModelCheckBox.right
- width: UM.Theme.getSize("layerview_legend_size").width
- height: UM.Theme.getSize("layerview_legend_size").height
- color: model.color
- radius: Math.round(width / 2)
- border.width: UM.Theme.getSize("default_lining").width
- border.color: UM.Theme.getColor("lining")
- visible: !viewSettings.show_legend & !viewSettings.show_gradient
- }
- Layout.fillWidth: true
- Layout.preferredHeight: UM.Theme.getSize("layerview_row").height + UM.Theme.getSize("default_lining").height
- Layout.preferredWidth: UM.Theme.getSize("layerview_row").width
- style: UM.Theme.styles.checkbox
- Label
- {
- text: model.name
- elide: Text.ElideRight
- color: UM.Theme.getColor("setting_control_text")
- font: UM.Theme.getFont("default")
- anchors.verticalCenter: parent.verticalCenter
- anchors.left: extrudersModelCheckBox.left;
- anchors.right: extrudersModelCheckBox.right;
- anchors.leftMargin: UM.Theme.getSize("checkbox").width + Math.round(UM.Theme.getSize("default_margin").width/2)
- anchors.rightMargin: UM.Theme.getSize("default_margin").width * 2
- }
- }
- }
-
- Repeater
- {
- model: ListModel
- {
- id: typesLegendModel
- Component.onCompleted:
- {
- typesLegendModel.append({
- label: catalog.i18nc("@label", "Show Travels"),
- initialValue: viewSettings.show_travel_moves,
- preference: "layerview/show_travel_moves",
- colorId: "layerview_move_combing"
- });
- typesLegendModel.append({
- label: catalog.i18nc("@label", "Show Helpers"),
- initialValue: viewSettings.show_helpers,
- preference: "layerview/show_helpers",
- colorId: "layerview_support"
- });
- typesLegendModel.append({
- label: catalog.i18nc("@label", "Show Shell"),
- initialValue: viewSettings.show_skin,
- preference: "layerview/show_skin",
- colorId: "layerview_inset_0"
- });
- typesLegendModel.append({
- label: catalog.i18nc("@label", "Show Infill"),
- initialValue: viewSettings.show_infill,
- preference: "layerview/show_infill",
- colorId: "layerview_infill"
- });
- }
- }
-
- CheckBox
- {
- id: legendModelCheckBox
- checked: model.initialValue
- onClicked:
- {
- UM.Preferences.setValue(model.preference, checked);
- }
- Rectangle
- {
- anchors.verticalCenter: parent.verticalCenter
- anchors.right: legendModelCheckBox.right
- width: UM.Theme.getSize("layerview_legend_size").width
- height: UM.Theme.getSize("layerview_legend_size").height
- color: UM.Theme.getColor(model.colorId)
- border.width: UM.Theme.getSize("default_lining").width
- border.color: UM.Theme.getColor("lining")
- visible: viewSettings.show_legend
- }
- Layout.fillWidth: true
- Layout.preferredHeight: UM.Theme.getSize("layerview_row").height + UM.Theme.getSize("default_lining").height
- Layout.preferredWidth: UM.Theme.getSize("layerview_row").width
- style: UM.Theme.styles.checkbox
- Label
- {
- text: label
- font: UM.Theme.getFont("default")
- elide: Text.ElideRight
- color: UM.Theme.getColor("setting_control_text")
- anchors.verticalCenter: parent.verticalCenter
- anchors.left: legendModelCheckBox.left;
- anchors.right: legendModelCheckBox.right;
- anchors.leftMargin: UM.Theme.getSize("checkbox").width + Math.round(UM.Theme.getSize("default_margin").width/2)
- anchors.rightMargin: UM.Theme.getSize("default_margin").width * 2
- }
- }
- }
-
- CheckBox
- {
- checked: viewSettings.only_show_top_layers
- onClicked:
- {
- UM.Preferences.setValue("view/only_show_top_layers", checked ? 1.0 : 0.0);
- }
- text: catalog.i18nc("@label", "Only Show Top Layers")
- visible: UM.SimulationView.compatibilityMode
- style: UM.Theme.styles.checkbox
- }
- CheckBox
- {
- checked: viewSettings.top_layer_count == 5
- onClicked:
- {
- UM.Preferences.setValue("view/top_layer_count", checked ? 5 : 1);
- }
- text: catalog.i18nc("@label", "Show 5 Detailed Layers On Top")
- visible: UM.SimulationView.compatibilityMode
- style: UM.Theme.styles.checkbox
- }
-
- Repeater
- {
- model: ListModel
- {
- id: typesLegendModelNoCheck
- Component.onCompleted:
- {
- typesLegendModelNoCheck.append({
- label: catalog.i18nc("@label", "Top / Bottom"),
- colorId: "layerview_skin",
- });
- typesLegendModelNoCheck.append({
- label: catalog.i18nc("@label", "Inner Wall"),
- colorId: "layerview_inset_x",
- });
- }
- }
-
- Label
- {
- text: label
- visible: viewSettings.show_legend
- id: typesLegendModelLabel
- Rectangle
- {
- anchors.verticalCenter: parent.verticalCenter
- anchors.right: typesLegendModelLabel.right
- width: UM.Theme.getSize("layerview_legend_size").width
- height: UM.Theme.getSize("layerview_legend_size").height
- color: UM.Theme.getColor(model.colorId)
- border.width: UM.Theme.getSize("default_lining").width
- border.color: UM.Theme.getColor("lining")
- visible: viewSettings.show_legend
- }
- Layout.fillWidth: true
- Layout.preferredHeight: UM.Theme.getSize("layerview_row").height + UM.Theme.getSize("default_lining").height
- Layout.preferredWidth: UM.Theme.getSize("layerview_row").width
- color: UM.Theme.getColor("setting_control_text")
- font: UM.Theme.getFont("default")
- }
- }
-
- // Text for the minimum, maximum and units for the feedrates and layer thickness
- Item
- {
- id: gradientLegend
- visible: viewSettings.show_gradient
- width: parent.width
- height: UM.Theme.getSize("layerview_row").height
- anchors
- {
- topMargin: UM.Theme.getSize("slider_layerview_margin").height
- horizontalCenter: parent.horizontalCenter
- }
-
- Label
- {
- text: minText()
- anchors.left: parent.left
- color: UM.Theme.getColor("setting_control_text")
- font: UM.Theme.getFont("default")
-
- function minText()
- {
- if (UM.SimulationView.layerActivity && CuraApplication.platformActivity)
- {
- // Feedrate selected
- if (UM.Preferences.getValue("layerview/layer_view_type") == 2)
- {
- return parseFloat(UM.SimulationView.getMinFeedrate()).toFixed(2)
- }
- // Layer thickness selected
- if (UM.Preferences.getValue("layerview/layer_view_type") == 3)
- {
- return parseFloat(UM.SimulationView.getMinThickness()).toFixed(2)
- }
- }
- return catalog.i18nc("@label","min")
- }
- }
-
- Label
- {
- text: unitsText()
- anchors.horizontalCenter: parent.horizontalCenter
- color: UM.Theme.getColor("setting_control_text")
- font: UM.Theme.getFont("default")
-
- function unitsText()
- {
- if (UM.SimulationView.layerActivity && CuraApplication.platformActivity)
- {
- // Feedrate selected
- if (UM.Preferences.getValue("layerview/layer_view_type") == 2)
- {
- return "mm/s"
- }
- // Layer thickness selected
- if (UM.Preferences.getValue("layerview/layer_view_type") == 3)
- {
- return "mm"
- }
- }
- return ""
- }
- }
-
- Label
- {
- text: maxText()
- anchors.right: parent.right
- color: UM.Theme.getColor("setting_control_text")
- font: UM.Theme.getFont("default")
-
- function maxText()
- {
- if (UM.SimulationView.layerActivity && CuraApplication.platformActivity)
- {
- // Feedrate selected
- if (UM.Preferences.getValue("layerview/layer_view_type") == 2)
- {
- return parseFloat(UM.SimulationView.getMaxFeedrate()).toFixed(2)
- }
- // Layer thickness selected
- if (UM.Preferences.getValue("layerview/layer_view_type") == 3)
- {
- return parseFloat(UM.SimulationView.getMaxThickness()).toFixed(2)
- }
- }
- return catalog.i18nc("@label","max")
- }
- }
- }
-
- // Gradient colors for feedrate
- Rectangle
- { // In QML 5.9 can be changed by LinearGradient
- // Invert values because then the bar is rotated 90 degrees
- id: feedrateGradient
- visible: viewSettings.show_feedrate_gradient
- anchors.left: parent.right
- height: parent.width
- width: Math.round(UM.Theme.getSize("layerview_row").height * 1.5)
- border.width: UM.Theme.getSize("default_lining").width
- border.color: UM.Theme.getColor("lining")
- transform: Rotation {origin.x: 0; origin.y: 0; angle: 90}
- gradient: Gradient
- {
- GradientStop
- {
- position: 0.000
- color: Qt.rgba(1, 0.5, 0, 1)
- }
- GradientStop
- {
- position: 0.625
- color: Qt.rgba(0.375, 0.5, 0, 1)
- }
- GradientStop
- {
- position: 0.75
- color: Qt.rgba(0.25, 1, 0, 1)
- }
- GradientStop
- {
- position: 1.0
- color: Qt.rgba(0, 0, 1, 1)
- }
- }
- }
-
- // Gradient colors for layer thickness (similar to parula colormap)
- Rectangle // In QML 5.9 can be changed by LinearGradient
- {
- // Invert values because then the bar is rotated 90 degrees
- id: thicknessGradient
- visible: viewSettings.show_thickness_gradient
- anchors.left: parent.right
- height: parent.width
- width: Math.round(UM.Theme.getSize("layerview_row").height * 1.5)
- border.width: UM.Theme.getSize("default_lining").width
- border.color: UM.Theme.getColor("lining")
- transform: Rotation {origin.x: 0; origin.y: 0; angle: 90}
- gradient: Gradient
- {
- GradientStop
- {
- position: 0.000
- color: Qt.rgba(1, 1, 0, 1)
- }
- GradientStop
- {
- position: 0.25
- color: Qt.rgba(1, 0.75, 0.25, 1)
- }
- GradientStop
- {
- position: 0.5
- color: Qt.rgba(0, 0.75, 0.5, 1)
- }
- GradientStop
- {
- position: 0.75
- color: Qt.rgba(0, 0.375, 0.75, 1)
- }
- GradientStop
- {
- position: 1.0
- color: Qt.rgba(0, 0, 0.5, 1)
- }
- }
- }
- }
- }
-
- Item
- {
- id: slidersBox
-
- width: parent.width
- visible: UM.SimulationView.layerActivity && CuraApplication.platformActivity
-
- anchors
- {
- top: parent.bottom
- topMargin: UM.Theme.getSize("slider_layerview_margin").height
- left: parent.left
- }
-
- PathSlider
- {
- id: pathSlider
-
- height: UM.Theme.getSize("slider_handle").width
- anchors.left: playButton.right
- anchors.leftMargin: UM.Theme.getSize("default_margin").width
- anchors.right: parent.right
- visible: !UM.SimulationView.compatibilityMode
-
- // custom properties
- handleValue: UM.SimulationView.currentPath
- maximumValue: UM.SimulationView.numPaths
- handleSize: UM.Theme.getSize("slider_handle").width
- trackThickness: UM.Theme.getSize("slider_groove").width
- trackColor: UM.Theme.getColor("slider_groove")
- trackBorderColor: UM.Theme.getColor("slider_groove_border")
- handleColor: UM.Theme.getColor("slider_handle")
- handleActiveColor: UM.Theme.getColor("slider_handle_active")
- rangeColor: UM.Theme.getColor("slider_groove_fill")
-
- // update values when layer data changes
- Connections
- {
- target: UM.SimulationView
- onMaxPathsChanged: pathSlider.setHandleValue(UM.SimulationView.currentPath)
- onCurrentPathChanged:
- {
- // Only pause the simulation when the layer was changed manually, not when the simulation is running
- if (pathSlider.manuallyChanged)
- {
- playButton.pauseSimulation()
- }
- pathSlider.setHandleValue(UM.SimulationView.currentPath)
- }
- }
-
- // make sure the slider handlers show the correct value after switching views
- Component.onCompleted:
- {
- pathSlider.setHandleValue(UM.SimulationView.currentPath)
- }
- }
-
- LayerSlider
- {
- id: layerSlider
-
- width: UM.Theme.getSize("slider_handle").width
- height: UM.Theme.getSize("layerview_menu_size").height
-
- anchors
- {
- top: !UM.SimulationView.compatibilityMode ? pathSlider.bottom : parent.top
- topMargin: !UM.SimulationView.compatibilityMode ? UM.Theme.getSize("default_margin").height : 0
- right: parent.right
- rightMargin: UM.Theme.getSize("slider_layerview_margin").width
- }
-
- // custom properties
- upperValue: UM.SimulationView.currentLayer
- lowerValue: UM.SimulationView.minimumLayer
- maximumValue: UM.SimulationView.numLayers
- handleSize: UM.Theme.getSize("slider_handle").width
- trackThickness: UM.Theme.getSize("slider_groove").width
- trackColor: UM.Theme.getColor("slider_groove")
- trackBorderColor: UM.Theme.getColor("slider_groove_border")
- upperHandleColor: UM.Theme.getColor("slider_handle")
- lowerHandleColor: UM.Theme.getColor("slider_handle")
- rangeHandleColor: UM.Theme.getColor("slider_groove_fill")
- handleActiveColor: UM.Theme.getColor("slider_handle_active")
- handleLabelWidth: UM.Theme.getSize("slider_layerview_background").width
-
- // update values when layer data changes
- Connections
- {
- target: UM.SimulationView
- onMaxLayersChanged: layerSlider.setUpperValue(UM.SimulationView.currentLayer)
- onMinimumLayerChanged: layerSlider.setLowerValue(UM.SimulationView.minimumLayer)
- onCurrentLayerChanged:
- {
- // Only pause the simulation when the layer was changed manually, not when the simulation is running
- if (layerSlider.manuallyChanged)
- {
- playButton.pauseSimulation()
- }
- layerSlider.setUpperValue(UM.SimulationView.currentLayer)
- }
- }
-
- // make sure the slider handlers show the correct value after switching views
- Component.onCompleted:
- {
- layerSlider.setLowerValue(UM.SimulationView.minimumLayer)
- layerSlider.setUpperValue(UM.SimulationView.currentLayer)
- }
- }
-
- // Play simulation button
- Button
- {
- id: playButton
- iconSource: "./resources/simulation_resume.svg"
- style: UM.Theme.styles.small_tool_button
- visible: !UM.SimulationView.compatibilityMode
- anchors
- {
- verticalCenter: pathSlider.verticalCenter
- }
-
- property var status: 0 // indicates if it's stopped (0) or playing (1)
-
- onClicked:
- {
- switch(status)
- {
- case 0:
- {
- resumeSimulation()
- break
- }
- case 1:
- {
- pauseSimulation()
- break
- }
- }
- }
-
- function pauseSimulation()
- {
- UM.SimulationView.setSimulationRunning(false)
- iconSource = "./resources/simulation_resume.svg"
- simulationTimer.stop()
- status = 0
- layerSlider.manuallyChanged = true
- pathSlider.manuallyChanged = true
- }
-
- function resumeSimulation()
- {
- UM.SimulationView.setSimulationRunning(true)
- iconSource = "./resources/simulation_pause.svg"
- simulationTimer.start()
- layerSlider.manuallyChanged = false
- pathSlider.manuallyChanged = false
- }
- }
-
- Timer
- {
- id: simulationTimer
- interval: 100
- running: false
- repeat: true
- onTriggered:
- {
- var currentPath = UM.SimulationView.currentPath
- var numPaths = UM.SimulationView.numPaths
- var currentLayer = UM.SimulationView.currentLayer
- var numLayers = UM.SimulationView.numLayers
- // 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 (playButton.status == 0)
- {
- if (currentPath >= numPaths)
- {
- UM.SimulationView.setCurrentPath(0)
- }
- else
- {
- UM.SimulationView.setCurrentPath(currentPath+1)
- }
- }
- // If the simulation is already playing and we reach the end of a layer, then it automatically
- // starts at the beginning of the next layer.
- else
- {
- if (currentPath >= numPaths)
- {
- // At the end of the model, the simulation stops
- if (currentLayer >= numLayers)
- {
- playButton.pauseSimulation()
- }
- else
- {
- UM.SimulationView.setCurrentLayer(currentLayer+1)
- UM.SimulationView.setCurrentPath(0)
- }
- }
- else
- {
- UM.SimulationView.setCurrentPath(currentPath+1)
- }
- }
- // 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.
- playButton.status = 1
- }
- }
- }
-
- FontMetrics
- {
- id: fontMetrics
- font: UM.Theme.getFont("default")
- }
-}
diff --git a/plugins/SimulationView/SimulationViewMainComponent.qml b/plugins/SimulationView/SimulationViewMainComponent.qml
new file mode 100644
index 0000000000..58901652d3
--- /dev/null
+++ b/plugins/SimulationView/SimulationViewMainComponent.qml
@@ -0,0 +1,216 @@
+// Copyright (c) 2018 Ultimaker B.V.
+// Cura is released under the terms of the LGPLv3 or higher.
+
+import QtQuick 2.4
+import QtQuick.Controls 1.2
+import QtQuick.Layouts 1.1
+import QtQuick.Controls.Styles 1.1
+
+import UM 1.4 as UM
+import Cura 1.0 as Cura
+
+Item
+{
+ property bool is_simulation_playing: false
+ visible: UM.SimulationView.layerActivity && CuraApplication.platformActivity
+
+ PathSlider
+ {
+ id: pathSlider
+ height: UM.Theme.getSize("slider_handle").width
+ width: UM.Theme.getSize("slider_layerview_size").height
+
+ anchors.bottom: parent.bottom
+ anchors.bottomMargin: UM.Theme.getSize("default_margin").height
+
+ anchors.horizontalCenter: parent.horizontalCenter
+
+ visible: !UM.SimulationView.compatibilityMode
+
+ // Custom properties
+ handleValue: UM.SimulationView.currentPath
+ maximumValue: UM.SimulationView.numPaths
+
+ // Update values when layer data changes.
+ Connections
+ {
+ target: UM.SimulationView
+ onMaxPathsChanged: pathSlider.setHandleValue(UM.SimulationView.currentPath)
+ onCurrentPathChanged:
+ {
+ // Only pause the simulation when the layer was changed manually, not when the simulation is running
+ if (pathSlider.manuallyChanged)
+ {
+ playButton.pauseSimulation()
+ }
+ pathSlider.setHandleValue(UM.SimulationView.currentPath)
+ }
+ }
+
+ // Ensure that the slider handlers show the correct value after switching views.
+ Component.onCompleted:
+ {
+ pathSlider.setHandleValue(UM.SimulationView.currentPath)
+ }
+
+ }
+
+ UM.SimpleButton
+ {
+ id: playButton
+ iconSource: !is_simulation_playing ? "./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")
+ color: UM.Theme.getColor("slider_handle")
+ iconMargin: UM.Theme.getSize("thick_lining").width
+ visible: !UM.SimulationView.compatibilityMode
+
+ Connections
+ {
+ target: UM.Preferences
+ onPreferenceChanged:
+ {
+ if (preference !== "view/only_show_top_layers" && preference !== "view/top_layer_count" && ! preference.match("layerview/"))
+ {
+ return;
+ }
+
+ playButton.pauseSimulation()
+ }
+ }
+
+ anchors
+ {
+ right: pathSlider.left
+ verticalCenter: pathSlider.verticalCenter
+ }
+
+ onClicked:
+ {
+ if(is_simulation_playing)
+ {
+ pauseSimulation()
+ }
+ else
+ {
+ resumeSimulation()
+ }
+ }
+
+ function pauseSimulation()
+ {
+ UM.SimulationView.setSimulationRunning(false)
+ simulationTimer.stop()
+ is_simulation_playing = false
+ layerSlider.manuallyChanged = true
+ pathSlider.manuallyChanged = true
+ }
+
+ function resumeSimulation()
+ {
+ UM.SimulationView.setSimulationRunning(true)
+ simulationTimer.start()
+ layerSlider.manuallyChanged = false
+ pathSlider.manuallyChanged = false
+ }
+ }
+
+ Timer
+ {
+ id: simulationTimer
+ interval: 100
+ running: false
+ repeat: true
+ onTriggered:
+ {
+ var currentPath = UM.SimulationView.currentPath
+ var numPaths = UM.SimulationView.numPaths
+ var currentLayer = UM.SimulationView.currentLayer
+ var numLayers = UM.SimulationView.numLayers
+
+ // 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 (currentPath >= numPaths)
+ {
+ UM.SimulationView.setCurrentPath(0)
+ }
+ else
+ {
+ UM.SimulationView.setCurrentPath(currentPath + 1)
+ }
+ }
+ // If the simulation is already playing and we reach the end of a layer, then it automatically
+ // starts at the beginning of the next layer.
+ else
+ {
+ if (currentPath >= numPaths)
+ {
+ // At the end of the model, the simulation stops
+ if (currentLayer >= numLayers)
+ {
+ playButton.pauseSimulation()
+ }
+ else
+ {
+ UM.SimulationView.setCurrentLayer(currentLayer + 1)
+ UM.SimulationView.setCurrentPath(0)
+ }
+ }
+ else
+ {
+ UM.SimulationView.setCurrentPath(currentPath + 1)
+ }
+ }
+ // 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
+ }
+ }
+
+ LayerSlider
+ {
+ id: layerSlider
+
+ width: UM.Theme.getSize("slider_handle").width
+ height: UM.Theme.getSize("slider_layerview_size").height
+
+ anchors
+ {
+ right: parent.right
+ verticalCenter: parent.verticalCenter
+ rightMargin: UM.Theme.getSize("default_margin").width
+ }
+
+ // Custom properties
+ upperValue: UM.SimulationView.currentLayer
+ lowerValue: UM.SimulationView.minimumLayer
+ maximumValue: UM.SimulationView.numLayers
+
+ // Update values when layer data changes
+ Connections
+ {
+ target: UM.SimulationView
+ onMaxLayersChanged: layerSlider.setUpperValue(UM.SimulationView.currentLayer)
+ onMinimumLayerChanged: layerSlider.setLowerValue(UM.SimulationView.minimumLayer)
+ onCurrentLayerChanged:
+ {
+ // Only pause the simulation when the layer was changed manually, not when the simulation is running
+ if (layerSlider.manuallyChanged)
+ {
+ playButton.pauseSimulation()
+ }
+ layerSlider.setUpperValue(UM.SimulationView.currentLayer)
+ }
+ }
+
+ // Make sure the slider handlers show the correct value after switching views
+ Component.onCompleted:
+ {
+ layerSlider.setLowerValue(UM.SimulationView.minimumLayer)
+ layerSlider.setUpperValue(UM.SimulationView.currentLayer)
+ }
+ }
+}
\ No newline at end of file
diff --git a/plugins/SimulationView/SimulationViewMenuComponent.qml b/plugins/SimulationView/SimulationViewMenuComponent.qml
new file mode 100644
index 0000000000..b94cf029f0
--- /dev/null
+++ b/plugins/SimulationView/SimulationViewMenuComponent.qml
@@ -0,0 +1,557 @@
+// Copyright (c) 2018 Ultimaker B.V.
+// Cura is released under the terms of the LGPLv3 or higher.
+
+import QtQuick 2.4
+import QtQuick.Controls 1.2
+import QtQuick.Layouts 1.1
+import QtQuick.Controls.Styles 1.1
+import QtGraphicalEffects 1.0
+
+import UM 1.0 as UM
+import Cura 1.0 as Cura
+
+
+Cura.ExpandableComponent
+{
+ id: base
+
+ dragPreferencesNamePrefix: "view/colorscheme"
+
+ contentHeaderTitle: catalog.i18nc("@label", "Color scheme")
+
+ Connections
+ {
+ target: UM.Preferences
+ onPreferenceChanged:
+ {
+ if (preference !== "view/only_show_top_layers" && preference !== "view/top_layer_count" && ! preference.match("layerview/"))
+ {
+ return;
+ }
+
+ layerTypeCombobox.currentIndex = UM.SimulationView.compatibilityMode ? 1 : UM.Preferences.getValue("layerview/layer_view_type")
+ layerTypeCombobox.updateLegends(layerTypeCombobox.currentIndex)
+ viewSettings.extruder_opacities = UM.Preferences.getValue("layerview/extruder_opacities").split("|")
+ viewSettings.show_travel_moves = UM.Preferences.getValue("layerview/show_travel_moves")
+ viewSettings.show_helpers = UM.Preferences.getValue("layerview/show_helpers")
+ viewSettings.show_skin = UM.Preferences.getValue("layerview/show_skin")
+ viewSettings.show_infill = UM.Preferences.getValue("layerview/show_infill")
+ viewSettings.only_show_top_layers = UM.Preferences.getValue("view/only_show_top_layers")
+ viewSettings.top_layer_count = UM.Preferences.getValue("view/top_layer_count")
+ }
+ }
+
+ headerItem: Item
+ {
+ Label
+ {
+ id: colorSchemeLabel
+ text: catalog.i18nc("@label", "Color scheme")
+ verticalAlignment: Text.AlignVCenter
+ height: parent.height
+ elide: Text.ElideRight
+ font: UM.Theme.getFont("medium")
+ color: UM.Theme.getColor("text_medium")
+ renderType: Text.NativeRendering
+ }
+
+ Label
+ {
+ text: layerTypeCombobox.currentText
+ verticalAlignment: Text.AlignVCenter
+ anchors
+ {
+ left: colorSchemeLabel.right
+ leftMargin: UM.Theme.getSize("default_margin").width
+ right: parent.right
+ }
+ height: parent.height
+ elide: Text.ElideRight
+ font: UM.Theme.getFont("medium")
+ color: UM.Theme.getColor("text")
+ renderType: Text.NativeRendering
+ }
+ }
+
+ contentItem: Column
+ {
+ id: viewSettings
+
+ property var extruder_opacities: UM.Preferences.getValue("layerview/extruder_opacities").split("|")
+ property bool show_travel_moves: UM.Preferences.getValue("layerview/show_travel_moves")
+ property bool show_helpers: UM.Preferences.getValue("layerview/show_helpers")
+ property bool show_skin: UM.Preferences.getValue("layerview/show_skin")
+ property bool show_infill: UM.Preferences.getValue("layerview/show_infill")
+
+ // If we are in compatibility mode, we only show the "line type"
+ property bool show_legend: UM.SimulationView.compatibilityMode ? true : UM.Preferences.getValue("layerview/layer_view_type") == 1
+ property bool show_gradient: UM.SimulationView.compatibilityMode ? false : UM.Preferences.getValue("layerview/layer_view_type") == 2 || UM.Preferences.getValue("layerview/layer_view_type") == 3
+ property bool show_feedrate_gradient: show_gradient && UM.Preferences.getValue("layerview/layer_view_type") == 2
+ property bool show_thickness_gradient: show_gradient && UM.Preferences.getValue("layerview/layer_view_type") == 3
+ property bool only_show_top_layers: UM.Preferences.getValue("view/only_show_top_layers")
+ property int top_layer_count: UM.Preferences.getValue("view/top_layer_count")
+
+ width: UM.Theme.getSize("layerview_menu_size").width - 2 * UM.Theme.getSize("default_margin").width
+ height: implicitHeight
+
+ spacing: UM.Theme.getSize("layerview_row_spacing").height
+
+ ListModel // matches SimulationView.py
+ {
+ id: layerViewTypes
+ }
+
+ Component.onCompleted:
+ {
+ layerViewTypes.append({
+ text: catalog.i18nc("@label:listbox", "Material Color"),
+ type_id: 0
+ })
+ layerViewTypes.append({
+ text: catalog.i18nc("@label:listbox", "Line Type"),
+ type_id: 1
+ })
+ layerViewTypes.append({
+ text: catalog.i18nc("@label:listbox", "Feedrate"),
+ type_id: 2
+ })
+ layerViewTypes.append({
+ text: catalog.i18nc("@label:listbox", "Layer thickness"),
+ type_id: 3 // these ids match the switching in the shader
+ })
+ }
+
+ ComboBox
+ {
+ id: layerTypeCombobox
+ width: parent.width
+ model: layerViewTypes
+ visible: !UM.SimulationView.compatibilityMode
+ style: UM.Theme.styles.combobox
+
+ onActivated:
+ {
+ UM.Preferences.setValue("layerview/layer_view_type", index);
+ }
+
+ Component.onCompleted:
+ {
+ currentIndex = UM.SimulationView.compatibilityMode ? 1 : UM.Preferences.getValue("layerview/layer_view_type");
+ updateLegends(currentIndex);
+ }
+
+ function updateLegends(type_id)
+ {
+ // Update the visibility of the legends.
+ viewSettings.show_legend = UM.SimulationView.compatibilityMode || (type_id == 1);
+ viewSettings.show_gradient = !UM.SimulationView.compatibilityMode && (type_id == 2 || type_id == 3);
+ viewSettings.show_feedrate_gradient = viewSettings.show_gradient && (type_id == 2);
+ viewSettings.show_thickness_gradient = viewSettings.show_gradient && (type_id == 3);
+ }
+ }
+
+ Label
+ {
+ id: compatibilityModeLabel
+ text: catalog.i18nc("@label", "Compatibility Mode")
+ font: UM.Theme.getFont("default")
+ color: UM.Theme.getColor("text")
+ visible: UM.SimulationView.compatibilityMode
+ height: UM.Theme.getSize("layerview_row").height
+ width: parent.width
+ renderType: Text.NativeRendering
+ }
+
+ Item // Spacer
+ {
+ height: UM.Theme.getSize("narrow_margin").width
+ width: width
+ }
+
+ Repeater
+ {
+ model: CuraApplication.getExtrudersModel()
+
+ CheckBox
+ {
+ id: extrudersModelCheckBox
+ checked: viewSettings.extruder_opacities[index] > 0.5 || viewSettings.extruder_opacities[index] == undefined || viewSettings.extruder_opacities[index] == ""
+ height: UM.Theme.getSize("layerview_row").height + UM.Theme.getSize("default_lining").height
+ width: parent.width
+ visible: !UM.SimulationView.compatibilityMode
+
+ onClicked:
+ {
+ viewSettings.extruder_opacities[index] = checked ? 1.0 : 0.0
+ UM.Preferences.setValue("layerview/extruder_opacities", viewSettings.extruder_opacities.join("|"));
+ }
+
+ style: UM.Theme.styles.checkbox
+
+
+ UM.RecolorImage
+ {
+ id: swatch
+ anchors.verticalCenter: parent.verticalCenter
+ anchors.right: extrudersModelCheckBox.right
+ width: UM.Theme.getSize("layerview_legend_size").width
+ height: UM.Theme.getSize("layerview_legend_size").height
+ source: UM.Theme.getIcon("extruder_button")
+ color: model.color
+ }
+
+ Label
+ {
+ text: model.name
+ elide: Text.ElideRight
+ color: UM.Theme.getColor("setting_control_text")
+ font: UM.Theme.getFont("default")
+ anchors
+ {
+ verticalCenter: parent.verticalCenter
+ left: extrudersModelCheckBox.left
+ right: extrudersModelCheckBox.right
+ leftMargin: UM.Theme.getSize("checkbox").width + Math.round(UM.Theme.getSize("default_margin").width / 2)
+ rightMargin: UM.Theme.getSize("default_margin").width * 2
+ }
+ renderType: Text.NativeRendering
+ }
+ }
+ }
+
+ Repeater
+ {
+ model: ListModel
+ {
+ id: typesLegendModel
+ Component.onCompleted:
+ {
+ typesLegendModel.append({
+ label: catalog.i18nc("@label", "Travels"),
+ initialValue: viewSettings.show_travel_moves,
+ preference: "layerview/show_travel_moves",
+ colorId: "layerview_move_combing"
+ });
+ typesLegendModel.append({
+ label: catalog.i18nc("@label", "Helpers"),
+ initialValue: viewSettings.show_helpers,
+ preference: "layerview/show_helpers",
+ colorId: "layerview_support"
+ });
+ typesLegendModel.append({
+ label: catalog.i18nc("@label", "Shell"),
+ initialValue: viewSettings.show_skin,
+ preference: "layerview/show_skin",
+ colorId: "layerview_inset_0"
+ });
+ typesLegendModel.append({
+ label: catalog.i18nc("@label", "Infill"),
+ initialValue: viewSettings.show_infill,
+ preference: "layerview/show_infill",
+ colorId: "layerview_infill"
+ });
+ }
+ }
+
+ CheckBox
+ {
+ id: legendModelCheckBox
+ checked: model.initialValue
+ onClicked: UM.Preferences.setValue(model.preference, checked)
+ height: UM.Theme.getSize("layerview_row").height + UM.Theme.getSize("default_lining").height
+ width: parent.width
+
+ style: UM.Theme.styles.checkbox
+
+ Rectangle
+ {
+ anchors.verticalCenter: parent.verticalCenter
+ anchors.right: legendModelCheckBox.right
+ width: UM.Theme.getSize("layerview_legend_size").width
+ height: UM.Theme.getSize("layerview_legend_size").height
+ color: UM.Theme.getColor(model.colorId)
+ border.width: UM.Theme.getSize("default_lining").width
+ border.color: UM.Theme.getColor("lining")
+ visible: viewSettings.show_legend
+ }
+
+ Label
+ {
+ text: label
+ font: UM.Theme.getFont("default")
+ elide: Text.ElideRight
+ renderType: Text.NativeRendering
+ color: UM.Theme.getColor("setting_control_text")
+ anchors.verticalCenter: parent.verticalCenter
+ anchors.left: legendModelCheckBox.left
+ anchors.right: legendModelCheckBox.right
+ anchors.leftMargin: UM.Theme.getSize("checkbox").width + Math.round(UM.Theme.getSize("default_margin").width / 2)
+ anchors.rightMargin: UM.Theme.getSize("default_margin").width * 2
+ }
+ }
+ }
+
+ CheckBox
+ {
+ checked: viewSettings.only_show_top_layers
+ onClicked: UM.Preferences.setValue("view/only_show_top_layers", checked ? 1.0 : 0.0)
+ text: catalog.i18nc("@label", "Only Show Top Layers")
+ visible: UM.SimulationView.compatibilityMode
+ style: UM.Theme.styles.checkbox
+ width: parent.width
+ }
+
+ CheckBox
+ {
+ checked: viewSettings.top_layer_count == 5
+ onClicked: UM.Preferences.setValue("view/top_layer_count", checked ? 5 : 1)
+ text: catalog.i18nc("@label", "Show 5 Detailed Layers On Top")
+ width: parent.width
+ visible: UM.SimulationView.compatibilityMode
+ style: UM.Theme.styles.checkbox
+ }
+
+ Repeater
+ {
+ model: ListModel
+ {
+ id: typesLegendModelNoCheck
+ Component.onCompleted:
+ {
+ typesLegendModelNoCheck.append({
+ label: catalog.i18nc("@label", "Top / Bottom"),
+ colorId: "layerview_skin",
+ });
+ typesLegendModelNoCheck.append({
+ label: catalog.i18nc("@label", "Inner Wall"),
+ colorId: "layerview_inset_x",
+ });
+ }
+ }
+
+ Label
+ {
+ text: label
+ visible: viewSettings.show_legend
+ id: typesLegendModelLabel
+
+ height: UM.Theme.getSize("layerview_row").height + UM.Theme.getSize("default_lining").height
+ width: parent.width
+ color: UM.Theme.getColor("setting_control_text")
+ font: UM.Theme.getFont("default")
+ renderType: Text.NativeRendering
+ Rectangle
+ {
+ anchors.verticalCenter: parent.verticalCenter
+ anchors.right: typesLegendModelLabel.right
+
+ width: UM.Theme.getSize("layerview_legend_size").width
+ height: UM.Theme.getSize("layerview_legend_size").height
+
+ color: UM.Theme.getColor(model.colorId)
+
+ border.width: UM.Theme.getSize("default_lining").width
+ border.color: UM.Theme.getColor("lining")
+ }
+ }
+ }
+
+ // Text for the minimum, maximum and units for the feedrates and layer thickness
+ Item
+ {
+ id: gradientLegend
+ visible: viewSettings.show_gradient
+ width: parent.width
+ height: UM.Theme.getSize("layerview_row").height
+
+ Label //Minimum value.
+ {
+ text:
+ {
+ if (UM.SimulationView.layerActivity && CuraApplication.platformActivity)
+ {
+ // Feedrate selected
+ if (UM.Preferences.getValue("layerview/layer_view_type") == 2)
+ {
+ return parseFloat(UM.SimulationView.getMinFeedrate()).toFixed(2)
+ }
+ // Layer thickness selected
+ if (UM.Preferences.getValue("layerview/layer_view_type") == 3)
+ {
+ return parseFloat(UM.SimulationView.getMinThickness()).toFixed(2)
+ }
+ }
+ return catalog.i18nc("@label","min")
+ }
+ anchors.left: parent.left
+ color: UM.Theme.getColor("setting_control_text")
+ font: UM.Theme.getFont("default")
+ renderType: Text.NativeRendering
+ }
+
+ Label //Unit in the middle.
+ {
+ text:
+ {
+ if (UM.SimulationView.layerActivity && CuraApplication.platformActivity)
+ {
+ // Feedrate selected
+ if (UM.Preferences.getValue("layerview/layer_view_type") == 2)
+ {
+ return "mm/s"
+ }
+ // Layer thickness selected
+ if (UM.Preferences.getValue("layerview/layer_view_type") == 3)
+ {
+ return "mm"
+ }
+ }
+ return ""
+ }
+
+ anchors.horizontalCenter: parent.horizontalCenter
+ color: UM.Theme.getColor("setting_control_text")
+ font: UM.Theme.getFont("default")
+ }
+
+ Label //Maximum value.
+ {
+ text: {
+ if (UM.SimulationView.layerActivity && CuraApplication.platformActivity)
+ {
+ // Feedrate selected
+ if (UM.Preferences.getValue("layerview/layer_view_type") == 2)
+ {
+ return parseFloat(UM.SimulationView.getMaxFeedrate()).toFixed(2)
+ }
+ // Layer thickness selected
+ if (UM.Preferences.getValue("layerview/layer_view_type") == 3)
+ {
+ return parseFloat(UM.SimulationView.getMaxThickness()).toFixed(2)
+ }
+ }
+ return catalog.i18nc("@label","max")
+ }
+
+ anchors.right: parent.right
+ color: UM.Theme.getColor("setting_control_text")
+ font: UM.Theme.getFont("default")
+ }
+ }
+
+ // Gradient colors for feedrate
+ Rectangle
+ {
+ id: feedrateGradient
+ visible: viewSettings.show_feedrate_gradient
+ anchors.left: parent.left
+ anchors.right: parent.right
+ height: Math.round(UM.Theme.getSize("layerview_row").height * 1.5)
+ border.width: UM.Theme.getSize("default_lining").width
+ border.color: UM.Theme.getColor("lining")
+
+ LinearGradient
+ {
+ anchors
+ {
+ left: parent.left
+ leftMargin: UM.Theme.getSize("default_lining").width
+ right: parent.right
+ rightMargin: UM.Theme.getSize("default_lining").width
+ top: parent.top
+ topMargin: UM.Theme.getSize("default_lining").width
+ bottom: parent.bottom
+ bottomMargin: UM.Theme.getSize("default_lining").width
+ }
+ start: Qt.point(0, 0)
+ end: Qt.point(parent.width, 0)
+ gradient: Gradient
+ {
+ GradientStop
+ {
+ position: 0.000
+ color: Qt.rgba(0, 0, 1, 1)
+ }
+ GradientStop
+ {
+ position: 0.25
+ color: Qt.rgba(0.25, 1, 0, 1)
+ }
+ GradientStop
+ {
+ position: 0.375
+ color: Qt.rgba(0.375, 0.5, 0, 1)
+ }
+ GradientStop
+ {
+ position: 1.0
+ color: Qt.rgba(1, 0.5, 0, 1)
+ }
+ }
+ }
+ }
+
+ // Gradient colors for layer thickness (similar to parula colormap)
+ Rectangle
+ {
+ id: thicknessGradient
+ visible: viewSettings.show_thickness_gradient
+ anchors.left: parent.left
+ anchors.right: parent.right
+ height: Math.round(UM.Theme.getSize("layerview_row").height * 1.5)
+ border.width: UM.Theme.getSize("default_lining").width
+ border.color: UM.Theme.getColor("lining")
+
+ LinearGradient
+ {
+ anchors
+ {
+ left: parent.left
+ leftMargin: UM.Theme.getSize("default_lining").width
+ right: parent.right
+ rightMargin: UM.Theme.getSize("default_lining").width
+ top: parent.top
+ topMargin: UM.Theme.getSize("default_lining").width
+ bottom: parent.bottom
+ bottomMargin: UM.Theme.getSize("default_lining").width
+ }
+ start: Qt.point(0, 0)
+ end: Qt.point(parent.width, 0)
+ gradient: Gradient
+ {
+ GradientStop
+ {
+ position: 0.000
+ color: Qt.rgba(0, 0, 0.5, 1)
+ }
+ GradientStop
+ {
+ position: 0.25
+ color: Qt.rgba(0, 0.375, 0.75, 1)
+ }
+ GradientStop
+ {
+ position: 0.5
+ color: Qt.rgba(0, 0.75, 0.5, 1)
+ }
+ GradientStop
+ {
+ position: 0.75
+ color: Qt.rgba(1, 0.75, 0.25, 1)
+ }
+ GradientStop
+ {
+ position: 1.0
+ color: Qt.rgba(1, 1, 0, 1)
+ }
+ }
+ }
+ }
+ }
+
+ FontMetrics
+ {
+ id: fontMetrics
+ font: UM.Theme.getFont("default")
+ }
+}
diff --git a/plugins/SimulationView/__init__.py b/plugins/SimulationView/__init__.py
index 360fdc1de9..420ee60660 100644
--- a/plugins/SimulationView/__init__.py
+++ b/plugins/SimulationView/__init__.py
@@ -8,19 +8,21 @@ from . import SimulationViewProxy, SimulationView
catalog = i18nCatalog("cura")
+
def getMetaData():
return {
"view": {
"name": catalog.i18nc("@item:inlistbox", "Layer view"),
- "view_panel": "SimulationView.qml",
- "weight": 2
+ "weight": 0
}
}
+
def createSimulationViewProxy(engine, script_engine):
return SimulationViewProxy.SimulationViewProxy()
+
def register(app):
simulation_view = SimulationView.SimulationView()
qmlRegisterSingletonType(SimulationViewProxy.SimulationViewProxy, "UM", 1, 0, "SimulationView", simulation_view.getProxy)
- return { "view": SimulationView.SimulationView()}
+ return { "view": simulation_view}
diff --git a/plugins/SimulationView/layers.shader b/plugins/SimulationView/layers.shader
index 30f23a3189..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
@@ -49,12 +52,13 @@ fragment =
// discard movements
discard;
}
- // support: 4, 5, 7, 10
+ // support: 4, 5, 7, 10, 11 (prime tower)
if ((u_show_helpers == 0) && (
((v_line_type >= 3.5) && (v_line_type <= 4.5)) ||
+ ((v_line_type >= 4.5) && (v_line_type <= 5.5)) ||
((v_line_type >= 6.5) && (v_line_type <= 7.5)) ||
((v_line_type >= 9.5) && (v_line_type <= 10.5)) ||
- ((v_line_type >= 4.5) && (v_line_type <= 5.5))
+ ((v_line_type >= 10.5) && (v_line_type <= 11.5))
)) {
discard;
}
@@ -75,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;
@@ -91,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);
@@ -153,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 de2b9335d8..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
@@ -154,7 +159,7 @@ geometry41core =
if ((u_show_travel_moves == 0) && ((v_line_type[0] == 8) || (v_line_type[0] == 9))) {
return;
}
- if ((u_show_helpers == 0) && ((v_line_type[0] == 4) || (v_line_type[0] == 5) || (v_line_type[0] == 7) || (v_line_type[0] == 10))) {
+ if ((u_show_helpers == 0) && ((v_line_type[0] == 4) || (v_line_type[0] == 5) || (v_line_type[0] == 7) || (v_line_type[0] == 10) || v_line_type[0] == 11)) {
return;
}
if ((u_show_skin == 0) && ((v_line_type[0] == 1) || (v_line_type[0] == 2) || (v_line_type[0] == 3))) {
@@ -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 7ceccff21e..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
@@ -45,19 +48,23 @@ fragment =
void main()
{
- if ((u_show_travel_moves == 0) && (v_line_type >= 7.5) && (v_line_type <= 9.5)) { // actually, 8 and 9
+ if ((u_show_travel_moves == 0) && (v_line_type >= 7.5) && (v_line_type <= 9.5))
+ { // actually, 8 and 9
// discard movements
discard;
}
- // support: 4, 5, 7, 10
+ // support: 4, 5, 7, 10, 11
if ((u_show_helpers == 0) && (
((v_line_type >= 3.5) && (v_line_type <= 4.5)) ||
((v_line_type >= 6.5) && (v_line_type <= 7.5)) ||
((v_line_type >= 9.5) && (v_line_type <= 10.5)) ||
- ((v_line_type >= 4.5) && (v_line_type <= 5.5))
- )) {
+ ((v_line_type >= 4.5) && (v_line_type <= 5.5)) ||
+ ((v_line_type >= 10.5) && (v_line_type <= 11.5))
+ ))
+ {
discard;
}
+
// skin: 1, 2, 3
if ((u_show_skin == 0) && (
(v_line_type >= 0.5) && (v_line_type <= 3.5)
@@ -65,7 +72,8 @@ fragment =
discard;
}
// infill:
- if ((u_show_infill == 0) && (v_line_type >= 5.5) && (v_line_type <= 6.5)) {
+ if ((u_show_infill == 0) && (v_line_type >= 5.5) && (v_line_type <= 6.5))
+ {
// discard movements
discard;
}
@@ -75,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;
@@ -91,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);
@@ -117,12 +128,13 @@ fragment41core =
// discard movements
discard;
}
- // helpers: 4, 5, 7, 10
+ // helpers: 4, 5, 7, 10, 11
if ((u_show_helpers == 0) && (
((v_line_type >= 3.5) && (v_line_type <= 4.5)) ||
((v_line_type >= 6.5) && (v_line_type <= 7.5)) ||
((v_line_type >= 9.5) && (v_line_type <= 10.5)) ||
- ((v_line_type >= 4.5) && (v_line_type <= 5.5))
+ ((v_line_type >= 4.5) && (v_line_type <= 5.5)) ||
+ ((v_line_type >= 10.5) && (v_line_type <= 11.5))
)) {
discard;
}
@@ -153,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 93df98068f..3ccf91b9e6 100644
--- a/plugins/SimulationView/plugin.json
+++ b/plugins/SimulationView/plugin.json
@@ -1,8 +1,8 @@
{
"name": "Simulation View",
"author": "Ultimaker B.V.",
- "version": "1.0.0",
+ "version": "1.0.1",
"description": "Provides the Simulation view.",
- "api": 5,
+ "api": "6.0",
"i18n-catalog": "cura"
}
diff --git a/plugins/SliceInfoPlugin/MoreInfoWindow.qml b/plugins/SliceInfoPlugin/MoreInfoWindow.qml
index 985ebe94a2..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 these 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 these 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..9308719227 100755
--- a/plugins/SliceInfoPlugin/SliceInfo.py
+++ b/plugins/SliceInfoPlugin/SliceInfo.py
@@ -48,20 +48,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 +62,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 +77,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()
@@ -140,6 +126,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":
@@ -195,6 +185,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/example_data.html b/plugins/SliceInfoPlugin/example_data.html
new file mode 100644
index 0000000000..4294b0af6d
--- /dev/null
+++ b/plugins/SliceInfoPlugin/example_data.html
@@ -0,0 +1,64 @@
+
+
+ Cura Version: 4.0
+ Operating System: Windows 10
+ Language: en_US
+ Machine Type: Ultimaker S5
+ 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 939e5ff235..8ff0e194fb 100644
--- a/plugins/SliceInfoPlugin/plugin.json
+++ b/plugins/SliceInfoPlugin/plugin.json
@@ -1,8 +1,8 @@
{
"name": "Slice info",
"author": "Ultimaker B.V.",
- "version": "1.0.0",
+ "version": "1.0.1",
"description": "Submits anonymous slice info. Can be disabled through preferences.",
- "api": 5,
+ "api": "6.0",
"i18n-catalog": "cura"
}
diff --git a/plugins/SolidView/SolidView.py b/plugins/SolidView/SolidView.py
index b9ad5c8829..4ce8ae7bc4 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,12 +7,10 @@ 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
from cura.Settings.ExtruderManager import ExtruderManager
-from cura.Settings.ExtrudersModel import ExtrudersModel
import math
@@ -21,21 +19,56 @@ 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
self._support_mesh_shader = None
- self._extruders_model = ExtrudersModel()
+ 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 = global_container_stack.getExtruderPositionValueWithDefault("support_extruder_nr")
+ support_angle_stack = global_container_stack.extruders.get(str(support_extruder_nr))
+ if support_angle_stack:
+ self._support_angle = support_angle_stack.getProperty("support_angle", "value")
def beginRendering(self):
scene = self.getController().getScene()
renderer = self.getRenderer()
+ if not self._extruders_model:
+ self._extruders_model = Application.getInstance().getExtrudersModel()
+
if not self._theme:
self._theme = Application.getInstance().getTheme()
@@ -61,15 +94,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
- # Note: if the overhang angle is set to its default value, it does not need to get validated (validationState = None)
- if angle is not None and global_container_stack.getProperty("support_angle", "validationState") in [None, ValidatorState.Valid]:
- 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:
diff --git a/plugins/SolidView/__init__.py b/plugins/SolidView/__init__.py
index db2e48f489..34148fcf05 100644
--- a/plugins/SolidView/__init__.py
+++ b/plugins/SolidView/__init__.py
@@ -10,7 +10,8 @@ def getMetaData():
return {
"view": {
"name": i18n_catalog.i18nc("@item:inmenu", "Solid view"),
- "weight": 0
+ "weight": 0,
+ "visible": False
}
}
diff --git a/plugins/SolidView/plugin.json b/plugins/SolidView/plugin.json
index e70ec224dd..b3f62221c5 100644
--- a/plugins/SolidView/plugin.json
+++ b/plugins/SolidView/plugin.json
@@ -1,8 +1,8 @@
{
"name": "Solid View",
"author": "Ultimaker B.V.",
- "version": "1.0.0",
+ "version": "1.0.1",
"description": "Provides a normal solid mesh view.",
- "api": 5,
+ "api": "6.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 7af35e0fb5..fa6d6d230e 100644
--- a/plugins/SupportEraser/plugin.json
+++ b/plugins/SupportEraser/plugin.json
@@ -1,8 +1,8 @@
{
"name": "Support Eraser",
"author": "Ultimaker B.V.",
- "version": "1.0.0",
+ "version": "1.0.1",
"description": "Creates an eraser mesh to block the printing of support in certain places",
- "api": 5,
+ "api": "6.0",
"i18n-catalog": "cura"
}
diff --git a/plugins/Toolbox/plugin.json b/plugins/Toolbox/plugin.json
index 2557185524..61dc0429f5 100644
--- a/plugins/Toolbox/plugin.json
+++ b/plugins/Toolbox/plugin.json
@@ -1,7 +1,7 @@
{
"name": "Toolbox",
"author": "Ultimaker B.V.",
- "version": "1.0.0",
- "api": 5,
+ "version": "1.0.1",
+ "api": "6.0",
"description": "Find, manage and install new Cura packages."
}
diff --git a/plugins/Toolbox/resources/images/loading.gif b/plugins/Toolbox/resources/images/loading.gif
deleted file mode 100644
index 43cc1ed6d7..0000000000
Binary files a/plugins/Toolbox/resources/images/loading.gif and /dev/null differ
diff --git a/plugins/Toolbox/resources/images/loading.svg b/plugins/Toolbox/resources/images/loading.svg
deleted file mode 100644
index 1ceb4a8d7f..0000000000
--- a/plugins/Toolbox/resources/images/loading.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/plugins/Toolbox/resources/qml/RatingWidget.qml b/plugins/Toolbox/resources/qml/RatingWidget.qml
new file mode 100644
index 0000000000..441cf238f7
--- /dev/null
+++ b/plugins/Toolbox/resources/qml/RatingWidget.qml
@@ -0,0 +1,106 @@
+import QtQuick 2.7
+import QtQuick.Controls 2.1
+import UM 1.0 as UM
+import Cura 1.1 as Cura
+Item
+{
+ id: ratingWidget
+
+ property real rating: 0
+ property int indexHovered: -1
+ property string packageId: ""
+
+ property int userRating: 0
+ property bool canRate: false
+
+ signal rated(int rating)
+
+ width: contentRow.width
+ height: contentRow.height
+ MouseArea
+ {
+ id: mouseArea
+ anchors.fill: parent
+ hoverEnabled: ratingWidget.canRate
+ acceptedButtons: Qt.NoButton
+ onExited:
+ {
+ if(ratingWidget.canRate)
+ {
+ ratingWidget.indexHovered = -1
+ }
+ }
+
+ Row
+ {
+ id: contentRow
+ height: childrenRect.height
+ Repeater
+ {
+ model: 5 // We need to get 5 stars
+ Button
+ {
+ id: control
+ hoverEnabled: true
+ onHoveredChanged:
+ {
+ if(hovered && ratingWidget.canRate)
+ {
+ indexHovered = index
+ }
+ }
+
+ ToolTip.visible: control.hovered && !ratingWidget.canRate
+ ToolTip.text: !Cura.API.account.isLoggedIn ? catalog.i18nc("@label", "You need to login first before you can rate"): catalog.i18nc("@label", "You need to install the package before you can rate")
+
+ property bool isStarFilled:
+ {
+ // If the entire widget is hovered, override the actual rating.
+ if(ratingWidget.indexHovered >= 0)
+ {
+ return indexHovered >= index
+ }
+
+ if(ratingWidget.userRating > 0)
+ {
+ return userRating >= index +1
+ }
+
+ return rating >= index + 1
+ }
+
+ contentItem: Item {}
+ height: UM.Theme.getSize("rating_star").height
+ width: UM.Theme.getSize("rating_star").width
+ background: UM.RecolorImage
+ {
+ source: UM.Theme.getIcon(control.isStarFilled ? "star_filled" : "star_empty")
+ sourceSize.width: width
+ sourceSize.height: height
+
+ // Unfilled stars should always have the default color. Only filled stars should change on hover
+ color:
+ {
+ if(!ratingWidget.canRate)
+ {
+ return UM.Theme.getColor("rating_star")
+ }
+ if((ratingWidget.indexHovered >= 0 || ratingWidget.userRating > 0) && isStarFilled)
+ {
+ return UM.Theme.getColor("primary")
+ }
+ return UM.Theme.getColor("rating_star")
+ }
+ }
+ onClicked:
+ {
+ if(ratingWidget.canRate)
+ {
+ rated(index + 1) // Notify anyone who cares about this.
+ }
+ }
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/plugins/Toolbox/resources/qml/SmallRatingWidget.qml b/plugins/Toolbox/resources/qml/SmallRatingWidget.qml
new file mode 100644
index 0000000000..965b81dc0f
--- /dev/null
+++ b/plugins/Toolbox/resources/qml/SmallRatingWidget.qml
@@ -0,0 +1,36 @@
+import QtQuick 2.3
+import QtQuick.Controls 1.4
+import UM 1.1 as UM
+import Cura 1.1 as Cura
+
+Row
+{
+ id: rating
+ height: UM.Theme.getSize("rating_star").height
+ visible: model.average_rating > 0 //Has a rating at all.
+ spacing: UM.Theme.getSize("thick_lining").width
+ width: starIcon.width + spacing + numRatingsLabel.width
+ UM.RecolorImage
+ {
+ id: starIcon
+ source: UM.Theme.getIcon("star_filled")
+ color: model.user_rating == 0 ? UM.Theme.getColor("rating_star") : UM.Theme.getColor("primary")
+ height: UM.Theme.getSize("rating_star").height
+ width: UM.Theme.getSize("rating_star").width
+ sourceSize.height: height
+ sourceSize.width: width
+ }
+
+ Label
+ {
+ id: numRatingsLabel
+ text: model.average_rating != undefined ? model.average_rating.toFixed(1) + " (" + model.num_ratings + " " + catalog.i18nc("@label", "ratings") + ")": ""
+ verticalAlignment: Text.AlignVCenter
+ height: starIcon.height
+ width: contentWidth
+ anchors.verticalCenter: starIcon.verticalCenter
+ color: starIcon.color
+ font: UM.Theme.getFont("default")
+ renderType: Text.NativeRendering
+ }
+}
\ No newline at end of file
diff --git a/plugins/Toolbox/resources/qml/Toolbox.qml b/plugins/Toolbox/resources/qml/Toolbox.qml
index 4fb8192d81..f70dab03d8 100644
--- a/plugins/Toolbox/resources/qml/Toolbox.qml
+++ b/plugins/Toolbox/resources/qml/Toolbox.qml
@@ -10,21 +10,21 @@ Window
{
id: base
property var selection: null
- title: catalog.i18nc("@title", "Toolbox")
+ title: catalog.i18nc("@title", "Marketplace")
modality: Qt.ApplicationModal
flags: Qt.Dialog | Qt.CustomizeWindowHint | Qt.WindowTitleHint | Qt.WindowCloseButtonHint
- width: 720 * screenScaleFactor
- height: 640 * screenScaleFactor
+ width: Math.floor(720 * screenScaleFactor)
+ height: Math.floor(640 * screenScaleFactor)
minimumWidth: width
maximumWidth: minimumWidth
minimumHeight: height
maximumHeight: minimumHeight
- color: UM.Theme.getColor("sidebar")
+ color: UM.Theme.getColor("main_background")
UM.I18nCatalog
{
id: catalog
- name:"cura"
+ name: "cura"
}
Item
{
@@ -38,7 +38,7 @@ Window
{
id: mainView
width: parent.width
- z: -1
+ z: parent.z - 1
anchors
{
top: header.bottom
@@ -48,32 +48,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"
}
}
@@ -95,6 +95,7 @@ Window
licenseDialog.show();
}
}
+
ToolboxLicenseDialog
{
id: licenseDialog
diff --git a/plugins/Toolbox/resources/qml/ToolboxAuthorPage.qml b/plugins/Toolbox/resources/qml/ToolboxAuthorPage.qml
index 4aaea20813..08ac1f83a5 100644
--- a/plugins/Toolbox/resources/qml/ToolboxAuthorPage.qml
+++ b/plugins/Toolbox/resources/qml/ToolboxAuthorPage.qml
@@ -1,7 +1,7 @@
// Copyright (c) 2018 Ultimaker B.V.
// Toolbox is released under the terms of the LGPLv3 or higher.
-import QtQuick 2.3
+import QtQuick 2.10
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
import UM 1.1 as UM
@@ -55,21 +55,24 @@ Item
bottomMargin: UM.Theme.getSize("default_margin").height
}
text: details.name || ""
- font: UM.Theme.getFont("large")
+ font: UM.Theme.getFont("large_bold")
wrapMode: Text.WordWrap
width: parent.width
height: UM.Theme.getSize("toolbox_property_label").height
+ renderType: Text.NativeRendering
}
Label
{
id: description
text: details.description || ""
+ font: UM.Theme.getFont("default")
anchors
{
top: title.bottom
left: title.left
topMargin: UM.Theme.getSize("default_margin").height
}
+ renderType: Text.NativeRendering
}
Column
{
@@ -86,14 +89,16 @@ Item
Label
{
text: catalog.i18nc("@label", "Website") + ":"
- font: UM.Theme.getFont("very_small")
+ font: UM.Theme.getFont("default")
color: UM.Theme.getColor("text_medium")
+ renderType: Text.NativeRendering
}
Label
{
text: catalog.i18nc("@label", "Email") + ":"
- font: UM.Theme.getFont("very_small")
+ font: UM.Theme.getFont("default")
color: UM.Theme.getColor("text_medium")
+ renderType: Text.NativeRendering
}
}
Column
@@ -104,6 +109,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)
@@ -118,10 +125,13 @@ Item
}
return ""
}
- font: UM.Theme.getFont("very_small")
+ width: parent.width
+ elide: Text.ElideRight
+ font: UM.Theme.getFont("default")
color: UM.Theme.getColor("text")
linkColor: UM.Theme.getColor("text_link")
onLinkActivated: Qt.openUrlExternally(link)
+ renderType: Text.NativeRendering
}
Label
@@ -134,10 +144,11 @@ Item
}
return ""
}
- font: UM.Theme.getFont("very_small")
+ font: UM.Theme.getFont("default")
color: UM.Theme.getColor("text")
linkColor: UM.Theme.getColor("text_link")
onLinkActivated: Qt.openUrlExternally(link)
+ renderType: Text.NativeRendering
}
}
Rectangle
diff --git a/plugins/Toolbox/resources/qml/ToolboxBackColumn.qml b/plugins/Toolbox/resources/qml/ToolboxBackColumn.qml
index 8524b7d1e5..dba9f19ccd 100644
--- a/plugins/Toolbox/resources/qml/ToolboxBackColumn.qml
+++ b/plugins/Toolbox/resources/qml/ToolboxBackColumn.qml
@@ -1,7 +1,7 @@
// 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 QtQuick.Controls.Styles 1.4
import UM 1.1 as UM
@@ -61,9 +61,15 @@ Item
id: labelStyle
text: control.text
color: control.enabled ? (control.hovered ? UM.Theme.getColor("primary") : UM.Theme.getColor("text")) : UM.Theme.getColor("text_inactive")
- font: UM.Theme.getFont("default_bold")
- horizontalAlignment: Text.AlignRight
+ font: UM.Theme.getFont("medium_bold")
+ horizontalAlignment: Text.AlignLeft
+ anchors
+ {
+ left: parent.left
+ leftMargin: UM.Theme.getSize("default_margin").width
+ }
width: control.width
+ renderType: Text.NativeRendering
}
}
}
diff --git a/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml b/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml
index 58fea079e9..1d1344fa9a 100644
--- a/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml
+++ b/plugins/Toolbox/resources/qml/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.7
+import QtQuick 2.10
import QtQuick.Controls 1.4
-import QtQuick.Controls.Styles 1.4
+
import UM 1.1 as UM
Item
@@ -11,157 +11,199 @@ Item
id: base
property var packageData
- property var technicalDataSheetUrl: {
- var link = undefined
- if ("Technical Data Sheet" in packageData.links)
- {
- link = packageData.links["Technical Data Sheet"]
- }
- return link
- }
+ property var technicalDataSheetUrl: packageData.links.technicalDataSheet
+ property var safetyDataSheetUrl: packageData.links.safetyDataSheet
+ property var printingGuidelinesUrl: packageData.links.printingGuidelines
+ property var materialWebsiteUrl: packageData.links.website
- anchors.topMargin: UM.Theme.getSize("default_margin").height
- height: visible ? childrenRect.height : 0
- visible: packageData.type == "material" && packageData.has_configs
- Label
+ height: childrenRect.height
+ onVisibleChanged: packageData.type === "material" && (compatibilityItem.visible || dataSheetLinks.visible)
+
+ Column
{
- id: heading
- anchors.topMargin: UM.Theme.getSize("default_margin").height
+ id: compatibilityItem
+ visible: packageData.has_configs
width: parent.width
- text: catalog.i18nc("@label", "Compatibility")
- wrapMode: Text.WordWrap
- color: UM.Theme.getColor("text_medium")
- font: UM.Theme.getFont("medium")
- }
- TableView
- {
- id: table
- anchors.top: heading.bottom
- anchors.topMargin: UM.Theme.getSize("default_margin").height
- width: parent.width
- frameVisible: false
+ // This is a bit of a hack, but the whole QML is pretty messy right now. This needs a big overhaul.
+ height: visible ? heading.height + table.height: 0
- // Workaround for scroll issues (QTBUG-49652)
- flickableItem.interactive: false
- Component.onCompleted:
+ Label
{
- for (var i = 0; i < flickableItem.children.length; ++i)
- {
- flickableItem.children[i].enabled = false
- }
- }
- selectionMode: 0
- model: packageData.supported_configs
- headerDelegate: Rectangle
- {
- color: UM.Theme.getColor("sidebar")
- height: UM.Theme.getSize("toolbox_chart_row").height
- Label
- {
- anchors.verticalCenter: parent.verticalCenter
- elide: Text.ElideRight
- text: styleData.value || ""
- color: UM.Theme.getColor("text")
- font: UM.Theme.getFont("default_bold")
- }
- Rectangle
- {
- anchors.bottom: parent.bottom
- height: UM.Theme.getSize("default_lining").height
- width: parent.width
- color: "black"
- }
- }
- rowDelegate: Item
- {
- height: UM.Theme.getSize("toolbox_chart_row").height
- Label
- {
- anchors.verticalCenter: parent.verticalCenter
- elide: Text.ElideRight
- text: styleData.value || ""
- color: UM.Theme.getColor("text_medium")
- font: UM.Theme.getFont("default")
- }
- }
- itemDelegate: Item
- {
- height: UM.Theme.getSize("toolbox_chart_row").height
- Label
- {
- anchors.verticalCenter: parent.verticalCenter
- elide: Text.ElideRight
- text: styleData.value || ""
- color: UM.Theme.getColor("text_medium")
- font: UM.Theme.getFont("default")
- }
+ id: heading
+ width: parent.width
+ text: catalog.i18nc("@label", "Compatibility")
+ wrapMode: Text.WordWrap
+ color: UM.Theme.getColor("text_medium")
+ font: UM.Theme.getFont("medium")
+ renderType: Text.NativeRendering
}
- Component
+ TableView
{
- id: columnTextDelegate
- Label
- {
- anchors.fill: parent
- verticalAlignment: Text.AlignVCenter
- text: styleData.value || ""
- elide: Text.ElideRight
- color: UM.Theme.getColor("text_medium")
- font: UM.Theme.getFont("default")
- }
- }
+ id: table
+ width: parent.width
+ frameVisible: false
- TableViewColumn
- {
- role: "machine"
- title: "Machine"
- width: Math.floor(table.width * 0.25)
- delegate: columnTextDelegate
- }
- TableViewColumn
- {
- role: "print_core"
- title: "Print Core"
- width: Math.floor(table.width * 0.2)
- }
- TableViewColumn
- {
- role: "build_plate"
- title: "Build Plate"
- width: Math.floor(table.width * 0.225)
- }
- TableViewColumn
- {
- role: "support_material"
- title: "Support"
- width: Math.floor(table.width * 0.225)
- }
- TableViewColumn
- {
- role: "quality"
- title: "Quality"
- width: Math.floor(table.width * 0.1)
+ // Workaround for scroll issues (QTBUG-49652)
+ flickableItem.interactive: false
+ Component.onCompleted:
+ {
+ for (var i = 0; i < flickableItem.children.length; ++i)
+ {
+ flickableItem.children[i].enabled = false
+ }
+ }
+ selectionMode: 0
+ model: packageData.supported_configs
+ headerDelegate: Rectangle
+ {
+ color: UM.Theme.getColor("main_background")
+ height: UM.Theme.getSize("toolbox_chart_row").height
+ Label
+ {
+ anchors.verticalCenter: parent.verticalCenter
+ elide: Text.ElideRight
+ text: styleData.value || ""
+ color: UM.Theme.getColor("text")
+ font: UM.Theme.getFont("default_bold")
+ renderType: Text.NativeRendering
+ }
+ Rectangle
+ {
+ anchors.bottom: parent.bottom
+ height: UM.Theme.getSize("default_lining").height
+ width: parent.width
+ color: "black"
+ }
+ }
+ rowDelegate: Item
+ {
+ height: UM.Theme.getSize("toolbox_chart_row").height
+ Label
+ {
+ anchors.verticalCenter: parent.verticalCenter
+ elide: Text.ElideRight
+ text: styleData.value || ""
+ color: UM.Theme.getColor("text_medium")
+ font: UM.Theme.getFont("default")
+ renderType: Text.NativeRendering
+ }
+ }
+ itemDelegate: Item
+ {
+ height: UM.Theme.getSize("toolbox_chart_row").height
+ Label
+ {
+ anchors.verticalCenter: parent.verticalCenter
+ elide: Text.ElideRight
+ text: styleData.value || ""
+ color: UM.Theme.getColor("text_medium")
+ font: UM.Theme.getFont("default")
+ renderType: Text.NativeRendering
+ }
+ }
+
+ Component
+ {
+ id: columnTextDelegate
+ Label
+ {
+ anchors.fill: parent
+ verticalAlignment: Text.AlignVCenter
+ text: styleData.value || ""
+ elide: Text.ElideRight
+ color: UM.Theme.getColor("text_medium")
+ font: UM.Theme.getFont("default")
+ renderType: Text.NativeRendering
+ }
+ }
+
+ TableViewColumn
+ {
+ role: "machine"
+ title: catalog.i18nc("@label:table_header", "Machine")
+ width: Math.floor(table.width * 0.25)
+ delegate: columnTextDelegate
+ }
+ TableViewColumn
+ {
+ role: "print_core"
+ title: catalog.i18nc("@label:table_header", "Print Core")
+ width: Math.floor(table.width * 0.2)
+ }
+ TableViewColumn
+ {
+ role: "build_plate"
+ title: catalog.i18nc("@label:table_header", "Build Plate")
+ width: Math.floor(table.width * 0.225)
+ }
+ TableViewColumn
+ {
+ role: "support_material"
+ title: catalog.i18nc("@label:table_header", "Support")
+ width: Math.floor(table.width * 0.225)
+ }
+ TableViewColumn
+ {
+ role: "quality"
+ title: catalog.i18nc("@label:table_header", "Quality")
+ width: Math.floor(table.width * 0.1)
+ }
}
}
Label
{
- id: technical_data_sheet
- anchors.top: table.bottom
- anchors.topMargin: UM.Theme.getSize("default_margin").height / 2
- visible: base.technicalDataSheetUrl !== undefined
+ 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
+
text:
{
+ var result = ""
if (base.technicalDataSheetUrl !== undefined)
{
- return "%2".arg(base.technicalDataSheetUrl).arg("Technical Data Sheet")
+ var tds_name = catalog.i18nc("@action:label", "Technical Data Sheet")
+ result += "%2".arg(base.technicalDataSheetUrl).arg(tds_name)
}
- return ""
+ if (base.safetyDataSheetUrl !== undefined)
+ {
+ if (result.length > 0)
+ {
+ result += " "
+ }
+ var sds_name = catalog.i18nc("@action:label", "Safety Data Sheet")
+ result += "%2".arg(base.safetyDataSheetUrl).arg(sds_name)
+ }
+ if (base.printingGuidelinesUrl !== undefined)
+ {
+ if (result.length > 0)
+ {
+ result += " "
+ }
+ var pg_name = catalog.i18nc("@action:label", "Printing Guidelines")
+ result += "%2".arg(base.printingGuidelinesUrl).arg(pg_name)
+ }
+ if (base.materialWebsiteUrl !== undefined)
+ {
+ if (result.length > 0)
+ {
+ result += " "
+ }
+ var pg_name = catalog.i18nc("@action:label", "Website")
+ result += "%2".arg(base.materialWebsiteUrl).arg(pg_name)
+ }
+
+ return result
}
- font: UM.Theme.getFont("very_small")
+ font: UM.Theme.getFont("default")
color: UM.Theme.getColor("text")
linkColor: UM.Theme.getColor("text_link")
onLinkActivated: Qt.openUrlExternally(link)
+ renderType: Text.NativeRendering
}
-
}
diff --git a/plugins/Toolbox/resources/qml/ToolboxConfirmUninstallResetDialog.qml b/plugins/Toolbox/resources/qml/ToolboxConfirmUninstallResetDialog.qml
index 2c5d08aa72..81649fdfef 100644
--- a/plugins/Toolbox/resources/qml/ToolboxConfirmUninstallResetDialog.qml
+++ b/plugins/Toolbox/resources/qml/ToolboxConfirmUninstallResetDialog.qml
@@ -1,7 +1,7 @@
// Copyright (c) 2018 Ultimaker B.V.
// Cura is released under the terms of the LGPLv3 or higher.
-import QtQuick 2.2
+import QtQuick 2.10
import QtQuick.Controls 1.1
import QtQuick.Controls.Styles 1.1
import QtQuick.Layouts 1.1
@@ -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
{
@@ -66,6 +66,7 @@ UM.Dialog
anchors.right: parent.right
font: UM.Theme.getFont("default")
wrapMode: Text.WordWrap
+ renderType: Text.NativeRendering
}
// Buttons
diff --git a/plugins/Toolbox/resources/qml/ToolboxDetailList.qml b/plugins/Toolbox/resources/qml/ToolboxDetailList.qml
index 2e5eae098c..22c6b6045f 100644
--- a/plugins/Toolbox/resources/qml/ToolboxDetailList.qml
+++ b/plugins/Toolbox/resources/qml/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
@@ -26,10 +24,19 @@ Item
}
height: childrenRect.height + 2 * UM.Theme.getSize("wide_margin").height
spacing: UM.Theme.getSize("default_margin").height
+
Repeater
{
model: toolbox.packagesModel
- delegate: ToolboxDetailTile {}
+ delegate: Loader
+ {
+ // FIXME: When using asynchronous loading, on Mac and Windows, the tile may fail to load complete,
+ // leaving an empty space below the title part. We turn it off for now to make it work on Mac and
+ // Windows.
+ // Can be related to this QT bug: https://bugreports.qt.io/browse/QTBUG-50992
+ asynchronous: false
+ source: "ToolboxDetailTile.qml"
+ }
}
}
}
diff --git a/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml b/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml
index cba55051f5..1773ef9053 100644
--- a/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml
+++ b/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml
@@ -1,11 +1,13 @@
// Copyright (c) 2018 Ultimaker B.V.
// Toolbox is released under the terms of the LGPLv3 or higher.
-import QtQuick 2.3
+import QtQuick 2.10
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
import UM 1.1 as UM
+import Cura 1.1 as Cura
+
Item
{
id: page
@@ -24,15 +26,12 @@ Item
right: parent.right
rightMargin: UM.Theme.getSize("wide_margin").width
}
- height: UM.Theme.getSize("toolbox_detail_header").height
- Image
+ height: childrenRect.height + 3 * UM.Theme.getSize("default_margin").width
+ Rectangle
{
id: thumbnail
width: UM.Theme.getSize("toolbox_thumbnail_medium").width
height: UM.Theme.getSize("toolbox_thumbnail_medium").height
- fillMode: Image.PreserveAspectFit
- source: details === null ? "" : (details.icon_url || "../images/logobot.svg")
- mipmap: true
anchors
{
top: parent.top
@@ -40,6 +39,14 @@ Item
leftMargin: UM.Theme.getSize("wide_margin").width
topMargin: UM.Theme.getSize("wide_margin").height
}
+ color: UM.Theme.getColor("main_background")
+ Image
+ {
+ anchors.fill: parent
+ fillMode: Image.PreserveAspectFit
+ source: details === null ? "" : (details.icon_url || "../images/logobot.svg")
+ mipmap: true
+ }
}
Label
@@ -50,16 +57,21 @@ Item
top: thumbnail.top
left: thumbnail.right
leftMargin: UM.Theme.getSize("default_margin").width
- right: parent.right
- rightMargin: UM.Theme.getSize("wide_margin").width
- bottomMargin: UM.Theme.getSize("default_margin").height
}
text: details === null ? "" : (details.name || "")
- font: UM.Theme.getFont("large")
+ font: UM.Theme.getFont("large_bold")
color: UM.Theme.getColor("text")
- wrapMode: Text.WordWrap
- width: parent.width
- height: UM.Theme.getSize("toolbox_property_label").height
+ width: contentWidth
+ height: contentHeight
+ renderType: Text.NativeRendering
+ }
+
+ SmallRatingWidget
+ {
+ anchors.left: title.right
+ anchors.leftMargin: UM.Theme.getSize("default_margin").width
+ anchors.verticalCenter: title.verticalCenter
+ property var model: details
}
Column
@@ -76,27 +88,39 @@ Item
height: childrenRect.height
Label
{
- text: catalog.i18nc("@label", "Version") + ":"
- font: UM.Theme.getFont("very_small")
+ text: catalog.i18nc("@label", "Your rating") + ":"
+ visible: details.type == "plugin"
+ font: UM.Theme.getFont("default")
color: UM.Theme.getColor("text_medium")
+ renderType: Text.NativeRendering
+ }
+ Label
+ {
+ text: catalog.i18nc("@label", "Version") + ":"
+ font: UM.Theme.getFont("default")
+ color: UM.Theme.getColor("text_medium")
+ renderType: Text.NativeRendering
}
Label
{
text: catalog.i18nc("@label", "Last updated") + ":"
- font: UM.Theme.getFont("very_small")
+ font: UM.Theme.getFont("default")
color: UM.Theme.getColor("text_medium")
+ renderType: Text.NativeRendering
}
Label
{
text: catalog.i18nc("@label", "Author") + ":"
- font: UM.Theme.getFont("very_small")
+ font: UM.Theme.getFont("default")
color: UM.Theme.getColor("text_medium")
+ renderType: Text.NativeRendering
}
Label
{
text: catalog.i18nc("@label", "Downloads") + ":"
- font: UM.Theme.getFont("very_small")
+ font: UM.Theme.getFont("default")
color: UM.Theme.getColor("text_medium")
+ renderType: Text.NativeRendering
}
}
Column
@@ -111,11 +135,54 @@ Item
}
spacing: Math.floor(UM.Theme.getSize("narrow_margin").height)
height: childrenRect.height
+ RatingWidget
+ {
+ id: rating
+ visible: details.type == "plugin"
+ packageId: details.id != undefined ? details.id: ""
+ userRating: details.user_rating != undefined ? details.user_rating: 0
+ canRate: toolbox.isInstalled(details.id) && Cura.API.account.isLoggedIn
+
+ onRated:
+ {
+ toolbox.ratePackage(details.id, rating)
+ // HACK: This is a far from optimal solution, but without major refactoring, this is the best we can
+ // do. Since a rework of this is scheduled, it shouldn't live that long...
+ var index = toolbox.pluginsAvailableModel.find("id", details.id)
+ if(index != -1)
+ {
+ if(details.user_rating == 0) // User never rated before.
+ {
+ toolbox.pluginsAvailableModel.setProperty(index, "num_ratings", details.num_ratings + 1)
+ }
+
+ toolbox.pluginsAvailableModel.setProperty(index, "user_rating", rating)
+
+
+ // Hack; This is because the current selection is an outdated copy, so we need to re-copy it.
+ base.selection = toolbox.pluginsAvailableModel.getItem(index)
+ return
+ }
+ index = toolbox.pluginsShowcaseModel.find("id", details.id)
+ if(index != -1)
+ {
+ if(details.user_rating == 0) // User never rated before.
+ {
+ toolbox.pluginsShowcaseModel.setProperty(index, "user_rating", rating)
+ }
+ toolbox.pluginsShowcaseModel.setProperty(index, "num_ratings", details.num_ratings + 1)
+
+ // Hack; This is because the current selection is an outdated copy, so we need to re-copy it.
+ base.selection = toolbox.pluginsShowcaseModel.getItem(index)
+ }
+ }
+ }
Label
{
text: details === null ? "" : (details.version || catalog.i18nc("@label", "Unknown"))
- font: UM.Theme.getFont("very_small")
+ font: UM.Theme.getFont("default")
color: UM.Theme.getColor("text")
+ renderType: Text.NativeRendering
}
Label
{
@@ -128,8 +195,9 @@ Item
var date = new Date(details.last_updated)
return date.toLocaleString(UM.Preferences.getValue("general/language"))
}
- font: UM.Theme.getFont("very_small")
+ font: UM.Theme.getFont("default")
color: UM.Theme.getColor("text")
+ renderType: Text.NativeRendering
}
Label
{
@@ -139,34 +207,25 @@ Item
{
return ""
}
- if (details.author_email)
- {
- return "" + details.author_name + ""
- }
else
{
return "" + details.author_name + ""
}
}
- font: UM.Theme.getFont("very_small")
+ font: UM.Theme.getFont("default")
color: UM.Theme.getColor("text")
linkColor: UM.Theme.getColor("text_link")
onLinkActivated: Qt.openUrlExternally(link)
+ renderType: Text.NativeRendering
}
Label
{
text: details === null ? "" : (details.download_count || catalog.i18nc("@label", "Unknown"))
- font: UM.Theme.getFont("very_small")
+ font: UM.Theme.getFont("default")
color: UM.Theme.getColor("text")
+ renderType: Text.NativeRendering
}
}
- Rectangle
- {
- color: UM.Theme.getColor("lining")
- width: parent.width
- height: UM.Theme.getSize("default_lining").height
- anchors.bottom: parent.bottom
- }
}
ToolboxDetailList
{
diff --git a/plugins/Toolbox/resources/qml/ToolboxDetailTile.qml b/plugins/Toolbox/resources/qml/ToolboxDetailTile.qml
index d544757d58..5badc6b66d 100644
--- a/plugins/Toolbox/resources/qml/ToolboxDetailTile.qml
+++ b/plugins/Toolbox/resources/qml/ToolboxDetailTile.qml
@@ -1,47 +1,55 @@
-// 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
{
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
wrapMode: Text.WordWrap
color: UM.Theme.getColor("text")
font: UM.Theme.getFont("medium_bold")
+ renderType: Text.NativeRendering
}
+
Label
{
- anchors.top: packageName.bottom
width: parent.width
text: model.description
- maximumLineCount: 3
+ maximumLineCount: 25
elide: Text.ElideRight
wrapMode: Text.WordWrap
color: UM.Theme.getColor("text")
font: UM.Theme.getFont("default")
+ renderType: Text.NativeRendering
+ }
+
+ ToolboxCompatibilityChart
+ {
+ width: parent.width
+ packageData: model
}
}
@@ -52,14 +60,6 @@ Item
anchors.top: tile.top
width: childrenRect.width
height: childrenRect.height
-
- }
-
- ToolboxCompatibilityChart
- {
- id: compatibilityChart
- anchors.top: normalData.bottom
- width: normalData.width
packageData: model
}
@@ -68,7 +68,7 @@ Item
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/ToolboxDetailTileActions.qml
index cd1e4cdbda..dfe91edbf6 100644
--- a/plugins/Toolbox/resources/qml/ToolboxDetailTileActions.qml
+++ b/plugins/Toolbox/resources/qml/ToolboxDetailTileActions.qml
@@ -1,40 +1,92 @@
// Copyright (c) 2018 Ultimaker B.V.
// Toolbox is released under the terms of the LGPLv3 or higher.
-import QtQuick 2.7
+import QtQuick 2.10
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
import UM 1.1 as UM
+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
+
width: UM.Theme.getSize("toolbox_action_button").width
spacing: UM.Theme.getSize("narrow_margin").height
- ToolboxProgressButton
+ Item
{
- id: installButton
- active: toolbox.isDownloading && toolbox.activePackage == model
- complete: installed
- readyAction: function()
+ width: installButton.width
+ height: installButton.height
+ ToolboxProgressButton
{
- toolbox.activePackage = model
- toolbox.startDownload(model.download_url)
+ id: installButton
+ active: toolbox.isDownloading && toolbox.activePackage == model
+ onReadyAction:
+ {
+ toolbox.activePackage = model
+ toolbox.startDownload(model.download_url)
+ }
+ onActiveAction: toolbox.cancelDownload()
+
+ // 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
}
- activeAction: function()
+
+ Cura.SecondaryButton
{
- toolbox.cancelDownload()
+ id: installedButton
+ visible: installed
+ onClicked: toolbox.viewCategory = "installed"
+ text: catalog.i18nc("@action:button", "Installed")
+ fixedWidthMode: true
+ width: installButton.width
+ height: installButton.height
}
- completeAction: function()
+ }
+
+ Label
+ {
+ wrapMode: Text.WordWrap
+ text: catalog.i18nc("@label:The string between and is the highlighted link", "Log in is required to install or update")
+ font: UM.Theme.getFont("default")
+ color: UM.Theme.getColor("text")
+ linkColor: UM.Theme.getColor("text_link")
+ visible: loginRequired
+ width: installButton.width
+ renderType: Text.NativeRendering
+
+ MouseArea
{
- toolbox.viewCategory = "installed"
+ anchors.fill: parent
+ onClicked: Cura.API.account.login()
+ }
+ }
+
+ Label
+ {
+ property var whereToBuyUrl:
+ {
+ var pg_name = "whereToBuy"
+ return (pg_name in packageData.links) ? packageData.links[pg_name] : undefined
+ }
+
+ renderType: Text.NativeRendering
+ text: catalog.i18nc("@label:The string between and is the highlighted link", "Buy material spools")
+ linkColor: UM.Theme.getColor("text_link")
+ visible: whereToBuyUrl != undefined
+ font: UM.Theme.getFont("default")
+ color: UM.Theme.getColor("text")
+ MouseArea
+ {
+ anchors.fill: parent
+ onClicked: Qt.openUrlExternally(parent.whereToBuyUrl)
}
- // Don't allow installing while another download is running
- enabled: installed || !(toolbox.isDownloading && toolbox.activePackage != model)
- opacity: enabled ? 1.0 : 0.5
- visible: !updateButton.visible // Don't show when the update button is visible
}
ToolboxProgressButton
@@ -44,24 +96,26 @@ Column
readyLabel: catalog.i18nc("@action:button", "Update")
activeLabel: catalog.i18nc("@action:button", "Updating")
completeLabel: catalog.i18nc("@action:button", "Updated")
- readyAction: function()
+
+ onReadyAction:
{
toolbox.activePackage = model
toolbox.update(model.id)
}
- activeAction: function()
- {
- toolbox.cancelDownload()
- }
+ onActiveAction: toolbox.cancelDownload()
// Don't allow installing while another download is running
- enabled: !(toolbox.isDownloading && toolbox.activePackage != model)
+ enabled: !(toolbox.isDownloading && toolbox.activePackage != model) && !loginRequired
opacity: enabled ? 1.0 : 0.5
visible: canUpdate
}
+
Connections
{
target: toolbox
onInstallChanged: installed = toolbox.isInstalled(model.id)
- onMetadataChanged: canUpdate = toolbox.canUpdate(model.id)
+ onFilterChanged:
+ {
+ installed = toolbox.isInstalled(model.id)
+ }
}
}
diff --git a/plugins/Toolbox/resources/qml/ToolboxDownloadsGrid.qml b/plugins/Toolbox/resources/qml/ToolboxDownloadsGrid.qml
index c586828969..6682281a31 100644
--- a/plugins/Toolbox/resources/qml/ToolboxDownloadsGrid.qml
+++ b/plugins/Toolbox/resources/qml/ToolboxDownloadsGrid.qml
@@ -1,10 +1,8 @@
// Copyright (c) 2018 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.Layouts 1.3
+import QtQuick 2.10
+import QtQuick.Controls 2.3
import UM 1.1 as UM
Column
@@ -22,9 +20,10 @@ Column
text: gridArea.heading
width: parent.width
color: UM.Theme.getColor("text_medium")
- font: UM.Theme.getFont("medium")
+ font: UM.Theme.getFont("large")
+ renderType: Text.NativeRendering
}
- GridLayout
+ Grid
{
id: grid
width: parent.width - 2 * parent.padding
@@ -34,10 +33,12 @@ Column
Repeater
{
model: gridArea.model
- delegate: ToolboxDownloadsGridTile
+ delegate: Loader
{
- Layout.preferredWidth: (grid.width - (grid.columns - 1) * grid.columnSpacing) / grid.columns
- Layout.preferredHeight: UM.Theme.getSize("toolbox_thumbnail_small").height
+ asynchronous: true
+ width: Math.round((grid.width - (grid.columns - 1) * grid.columnSpacing) / grid.columns)
+ height: UM.Theme.getSize("toolbox_thumbnail_small").height
+ source: "ToolboxDownloadsGridTile.qml"
}
}
}
diff --git a/plugins/Toolbox/resources/qml/ToolboxDownloadsGridTile.qml b/plugins/Toolbox/resources/qml/ToolboxDownloadsGridTile.qml
index 887140bbfa..73dd593336 100644
--- a/plugins/Toolbox/resources/qml/ToolboxDownloadsGridTile.qml
+++ b/plugins/Toolbox/resources/qml/ToolboxDownloadsGridTile.qml
@@ -1,11 +1,12 @@
// Copyright (c) 2018 Ultimaker B.V.
// Toolbox is released under the terms of the LGPLv3 or higher.
-import QtQuick 2.3
+import QtQuick 2.10
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
import QtQuick.Layouts 1.3
import UM 1.1 as UM
+import Cura 1.1 as Cura
Item
{
@@ -14,91 +15,13 @@ Item
property int installedPackages: (toolbox.viewCategory == "material" && model.type === undefined) ? toolbox.getNumberOfInstalledPackagesByAuthor(model.id) : (toolbox.isInstalled(model.id) ? 1 : 0)
height: childrenRect.height
Layout.alignment: Qt.AlignTop | Qt.AlignLeft
- Rectangle
- {
- id: highlight
- anchors.fill: parent
- opacity: 0.0
- color: UM.Theme.getColor("primary")
- }
- Row
- {
- width: parent.width
- height: childrenRect.height
- spacing: Math.floor(UM.Theme.getSize("narrow_margin").width)
- Rectangle
- {
- id: thumbnail
- width: UM.Theme.getSize("toolbox_thumbnail_small").width
- height: UM.Theme.getSize("toolbox_thumbnail_small").height
- color: "white"
- border.width: UM.Theme.getSize("default_lining").width
- border.color: UM.Theme.getColor("lining")
- Image
- {
- anchors.centerIn: parent
- 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"
- mipmap: true
- }
- UM.RecolorImage
- {
- width: (parent.width * 0.4) | 0
- height: (parent.height * 0.4) | 0
- anchors
- {
- bottom: parent.bottom
- right: parent.right
- }
- sourceSize.width: width
- sourceSize.height: height
- visible: installedPackages != 0
- color: (installedPackages == packageCount) ? UM.Theme.getColor("primary") : UM.Theme.getColor("border")
- source: "../images/installed_check.svg"
- }
- }
- Column
- {
- width: parent.width - thumbnail.width - parent.spacing
- spacing: Math.floor(UM.Theme.getSize("narrow_margin").width)
- Label
- {
- id: name
- text: model.name
- width: parent.width
- wrapMode: Text.WordWrap
- color: UM.Theme.getColor("text")
- font: UM.Theme.getFont("default_bold")
- }
- Label
- {
- id: info
- text: model.description
- maximumLineCount: 2
- elide: Text.ElideRight
- width: parent.width
- wrapMode: Text.WordWrap
- color: UM.Theme.getColor("text_medium")
- font: UM.Theme.getFont("very_small")
- }
- }
- }
+
MouseArea
{
anchors.fill: parent
hoverEnabled: true
- onEntered:
- {
- thumbnail.border.color = UM.Theme.getColor("primary")
- highlight.opacity = 0.1
- }
- onExited:
- {
- thumbnail.border.color = UM.Theme.getColor("lining")
- highlight.opacity = 0.0
- }
+ onEntered: thumbnail.border.color = UM.Theme.getColor("primary")
+ onExited: thumbnail.border.color = UM.Theme.getColor("lining")
onClicked:
{
base.selection = model
@@ -128,4 +51,83 @@ Item
}
}
}
+
+ Rectangle
+ {
+ id: thumbnail
+ width: UM.Theme.getSize("toolbox_thumbnail_small").width
+ height: UM.Theme.getSize("toolbox_thumbnail_small").height
+ color: UM.Theme.getColor("main_background")
+ border.width: UM.Theme.getSize("default_lining").width
+ border.color: UM.Theme.getColor("lining")
+
+ Image
+ {
+ anchors.centerIn: parent
+ 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"
+ mipmap: true
+ }
+ UM.RecolorImage
+ {
+ width: (parent.width * 0.4) | 0
+ height: (parent.height * 0.4) | 0
+ anchors
+ {
+ 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"
+ }
+ }
+ Item
+ {
+ anchors
+ {
+ left: thumbnail.right
+ leftMargin: Math.floor(UM.Theme.getSize("narrow_margin").width)
+ right: parent.right
+ top: parent.top
+ bottom: parent.bottom
+ }
+
+ Label
+ {
+ id: name
+ text: model.name
+ width: parent.width
+ elide: Text.ElideRight
+ color: UM.Theme.getColor("text")
+ font: UM.Theme.getFont("default_bold")
+ }
+ Label
+ {
+ id: info
+ text: model.description
+ elide: Text.ElideRight
+ width: parent.width
+ wrapMode: Text.WordWrap
+ color: UM.Theme.getColor("text")
+ font: UM.Theme.getFont("default")
+ anchors.top: name.bottom
+ anchors.bottom: rating.top
+ verticalAlignment: Text.AlignVCenter
+ maximumLineCount: 2
+ }
+ SmallRatingWidget
+ {
+ id: rating
+ anchors
+ {
+ bottom: parent.bottom
+ left: parent.left
+ right: parent.right
+ }
+ }
+ }
}
diff --git a/plugins/Toolbox/resources/qml/ToolboxDownloadsPage.qml b/plugins/Toolbox/resources/qml/ToolboxDownloadsPage.qml
index 3e0dda4f4a..5ea24d17ba 100644
--- a/plugins/Toolbox/resources/qml/ToolboxDownloadsPage.qml
+++ b/plugins/Toolbox/resources/qml/ToolboxDownloadsPage.qml
@@ -1,25 +1,20 @@
-// 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
ScrollView
{
- frameVisible: false
+ clip: true
width: parent.width
height: parent.height
- style: UM.Theme.styles.scrollview
-
- flickableItem.flickableDirection: Flickable.VerticalFlick
Column
{
width: base.width
spacing: UM.Theme.getSize("default_margin").height
- height: childrenRect.height
ToolboxDownloadsShowcase
{
@@ -31,14 +26,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/ToolboxDownloadsShowcase.qml b/plugins/Toolbox/resources/qml/ToolboxDownloadsShowcase.qml
index 46f5debfdd..72dd6f91a2 100644
--- a/plugins/Toolbox/resources/qml/ToolboxDownloadsShowcase.qml
+++ b/plugins/Toolbox/resources/qml/ToolboxDownloadsShowcase.qml
@@ -1,7 +1,7 @@
// Copyright (c) 2018 Ultimaker B.V.
// Toolbox is released under the terms of the LGPLv3 or higher.
-import QtQuick 2.7
+import QtQuick 2.10
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
import UM 1.1 as UM
@@ -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
@@ -23,30 +23,34 @@ Rectangle
text: catalog.i18nc("@label", "Featured")
width: parent.width
color: UM.Theme.getColor("text_medium")
- font: UM.Theme.getFont("medium")
+ font: UM.Theme.getFont("large")
+ renderType: Text.NativeRendering
}
Grid
{
height: childrenRect.height
spacing: UM.Theme.getSize("wide_margin").width
columns: 3
- anchors
- {
- horizontalCenter: parent.horizontalCenter
- }
+ anchors.horizontalCenter: parent.horizontalCenter
+
Repeater
{
- model: {
- if ( toolbox.viewCategory == "plugin" )
+ model:
+ {
+ if (toolbox.viewCategory == "plugin")
{
return toolbox.pluginsShowcaseModel
}
- if ( toolbox.viewCategory == "material" )
+ if (toolbox.viewCategory == "material")
{
return toolbox.materialsShowcaseModel
}
}
- delegate: ToolboxDownloadsShowcaseTile {}
+ delegate: Loader
+ {
+ asynchronous: true
+ source: "ToolboxDownloadsShowcaseTile.qml"
+ }
}
}
}
diff --git a/plugins/Toolbox/resources/qml/ToolboxDownloadsShowcaseTile.qml b/plugins/Toolbox/resources/qml/ToolboxDownloadsShowcaseTile.qml
index 845bbe8f91..89348b18de 100644
--- a/plugins/Toolbox/resources/qml/ToolboxDownloadsShowcaseTile.qml
+++ b/plugins/Toolbox/resources/qml/ToolboxDownloadsShowcaseTile.qml
@@ -1,7 +1,7 @@
// Copyright (c) 2018 Ultimaker B.V.
-// Toolbox is released under the terms of the LGPLv3 or higher.
+// Cura is released under the terms of the LGPLv3 or higher.
-import QtQuick 2.7
+import QtQuick 2.10
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
import QtGraphicalEffects 1.0
@@ -13,92 +13,80 @@ Rectangle
property int installedPackages: toolbox.viewCategory == "material" ? toolbox.getNumberOfInstalledPackagesByAuthor(model.id) : (toolbox.isInstalled(model.id) ? 1 : 0)
id: tileBase
width: UM.Theme.getSize("toolbox_thumbnail_large").width + (2 * UM.Theme.getSize("default_lining").width)
- height: thumbnail.height + packageNameBackground.height + (2 * UM.Theme.getSize("default_lining").width)
+ height: thumbnail.height + packageName.height + rating.height + UM.Theme.getSize("default_margin").width
border.width: UM.Theme.getSize("default_lining").width
border.color: UM.Theme.getColor("lining")
- color: "transparent"
- Rectangle
+ color: UM.Theme.getColor("main_background")
+ Image
{
id: thumbnail
- color: "white"
- width: UM.Theme.getSize("toolbox_thumbnail_large").width
- height: UM.Theme.getSize("toolbox_thumbnail_large").height
+ 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"
+ mipmap: true
anchors
{
top: parent.top
+ topMargin: UM.Theme.getSize("default_margin").height
horizontalCenter: parent.horizontalCenter
- topMargin: UM.Theme.getSize("default_lining").width
}
- Image
+ }
+ Label
+ {
+ id: packageName
+ text: model.name
+ anchors
{
- anchors.centerIn: parent
- width: UM.Theme.getSize("toolbox_thumbnail_large").width - 2 * UM.Theme.getSize("default_margin").width
- height: UM.Theme.getSize("toolbox_thumbnail_large").height - 2 * UM.Theme.getSize("default_margin").height
- fillMode: Image.PreserveAspectFit
- source: model.icon_url || "../images/logobot.svg"
- mipmap: true
+ horizontalCenter: parent.horizontalCenter
+ top: thumbnail.bottom
}
- UM.RecolorImage
+ verticalAlignment: Text.AlignVCenter
+ horizontalAlignment: Text.AlignHCenter
+ renderType: Text.NativeRendering
+ height: UM.Theme.getSize("toolbox_heading_label").height
+ width: parent.width - UM.Theme.getSize("default_margin").width
+ wrapMode: Text.WordWrap
+ elide: Text.ElideRight
+ font: UM.Theme.getFont("medium_bold")
+ color: UM.Theme.getColor("text")
+ }
+ UM.RecolorImage
+ {
+ width: (parent.width * 0.20) | 0
+ height: width
+ anchors
{
- width: (parent.width * 0.3) | 0
- height: (parent.height * 0.3) | 0
- anchors
- {
- bottom: parent.bottom
- right: parent.right
- bottomMargin: UM.Theme.getSize("default_lining").width
- }
- sourceSize.width: width
- sourceSize.height: height
- visible: installedPackages != 0
- color: (installedPackages == packageCount) ? UM.Theme.getColor("primary") : UM.Theme.getColor("border")
- source: "../images/installed_check.svg"
+ bottom: bottomBorder.top
+ right: parent.right
}
+ visible: installedPackages != 0
+ color: (installedPackages >= packageCount) ? UM.Theme.getColor("primary") : UM.Theme.getColor("border")
+ source: "../images/installed_check.svg"
+ }
+
+ SmallRatingWidget
+ {
+ id: rating
+ anchors.bottom: parent.bottom
+ anchors.bottomMargin: UM.Theme.getSize("narrow_margin").height
+ anchors.horizontalCenter: parent.horizontalCenter
}
Rectangle
{
- id: packageNameBackground
+ id: bottomBorder
color: UM.Theme.getColor("primary")
- anchors
- {
- top: thumbnail.bottom
- horizontalCenter: parent.horizontalCenter
- }
- height: UM.Theme.getSize("toolbox_heading_label").height
+ anchors.bottom: parent.bottom
width: parent.width
- Label
- {
- id: packageName
- text: model.name
- anchors
- {
- horizontalCenter: parent.horizontalCenter
- }
- verticalAlignment: Text.AlignVCenter
- horizontalAlignment: Text.AlignHCenter
- height: UM.Theme.getSize("toolbox_heading_label").height
- width: parent.width
- wrapMode: Text.WordWrap
- color: UM.Theme.getColor("button_text")
- font: UM.Theme.getFont("medium_bold")
- }
+ height: UM.Theme.getSize("toolbox_header_highlight").height
}
+
MouseArea
{
anchors.fill: parent
hoverEnabled: true
- onEntered:
- {
- packageName.color = UM.Theme.getColor("button_text_hover")
- packageNameBackground.color = UM.Theme.getColor("primary_hover")
- tileBase.border.color = UM.Theme.getColor("primary_hover")
- }
- onExited:
- {
- packageName.color = UM.Theme.getColor("button_text")
- packageNameBackground.color = UM.Theme.getColor("primary")
- tileBase.border.color = UM.Theme.getColor("lining")
- }
+ onEntered: tileBase.border.color = UM.Theme.getColor("primary")
+ onExited: tileBase.border.color = UM.Theme.getColor("lining")
onClicked:
{
base.selection = model
diff --git a/plugins/Toolbox/resources/qml/ToolboxErrorPage.qml b/plugins/Toolbox/resources/qml/ToolboxErrorPage.qml
index 600ae2b39f..e57e63dbb9 100644
--- a/plugins/Toolbox/resources/qml/ToolboxErrorPage.qml
+++ b/plugins/Toolbox/resources/qml/ToolboxErrorPage.qml
@@ -1,7 +1,7 @@
// Copyright (c) 2018 Ultimaker B.V.
// Toolbox is released under the terms of the LGPLv3 or higher.
-import QtQuick 2.7
+import QtQuick 2.10
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
@@ -18,5 +18,6 @@ Rectangle
{
centerIn: parent
}
+ renderType: Text.NativeRendering
}
}
diff --git a/plugins/Toolbox/resources/qml/ToolboxFooter.qml b/plugins/Toolbox/resources/qml/ToolboxFooter.qml
index 5c2a6577ad..6f46e939ff 100644
--- a/plugins/Toolbox/resources/qml/ToolboxFooter.qml
+++ b/plugins/Toolbox/resources/qml/ToolboxFooter.qml
@@ -1,22 +1,24 @@
// 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 QtQuick 2.10
+import QtQuick.Controls 2.3
+
import UM 1.1 as UM
+import Cura 1.0 as Cura
Item
{
id: footer
width: parent.width
anchors.bottom: parent.bottom
- height: visible ? Math.floor(UM.Theme.getSize("toolbox_footer").height) : 0
+ height: visible ? UM.Theme.getSize("toolbox_footer").height : 0
+
Label
{
text: catalog.i18nc("@info", "You will need to restart Cura before changes in packages have effect.")
color: UM.Theme.getColor("text")
- height: Math.floor(UM.Theme.getSize("toolbox_footer_button").height)
+ height: UM.Theme.getSize("toolbox_footer_button").height
verticalAlignment: Text.AlignVCenter
anchors
{
@@ -26,12 +28,12 @@ Item
right: restartButton.right
rightMargin: UM.Theme.getSize("default_margin").width
}
-
+ renderType: Text.NativeRendering
}
- Button
+
+ Cura.PrimaryButton
{
id: restartButton
- text: catalog.i18nc("@info:button", "Quit Cura")
anchors
{
top: parent.top
@@ -39,26 +41,11 @@ Item
right: parent.right
rightMargin: UM.Theme.getSize("wide_margin").width
}
- iconName: "dialog-restart"
+ height: UM.Theme.getSize("toolbox_footer_button").height
+ text: catalog.i18nc("@info:button", "Quit Cura")
onClicked: toolbox.restart()
- style: ButtonStyle
- {
- background: Rectangle
- {
- implicitWidth: UM.Theme.getSize("toolbox_footer_button").width
- implicitHeight: Math.floor(UM.Theme.getSize("toolbox_footer_button").height)
- color: control.hovered ? UM.Theme.getColor("primary_hover") : UM.Theme.getColor("primary")
- }
- label: Label
- {
- color: UM.Theme.getColor("button_text")
- font: UM.Theme.getFont("default_bold")
- text: control.text
- verticalAlignment: Text.AlignVCenter
- horizontalAlignment: Text.AlignHCenter
- }
- }
}
+
ToolboxShadow
{
visible: footer.visible
diff --git a/plugins/Toolbox/resources/qml/ToolboxHeader.qml b/plugins/Toolbox/resources/qml/ToolboxHeader.qml
index 087402d564..491567eb5f 100644
--- a/plugins/Toolbox/resources/qml/ToolboxHeader.qml
+++ b/plugins/Toolbox/resources/qml/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/ToolboxInstalledPage.qml b/plugins/Toolbox/resources/qml/ToolboxInstalledPage.qml
index e683f89823..f4a9e634c4 100644
--- a/plugins/Toolbox/resources/qml/ToolboxInstalledPage.qml
+++ b/plugins/Toolbox/resources/qml/ToolboxInstalledPage.qml
@@ -1,64 +1,61 @@
-// 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.Dialogs 1.1
-import QtQuick.Window 2.2
-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
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
- anchors
- {
- right: parent.right
- left: parent.left
- leftMargin: UM.Theme.getSize("wide_margin").width
- topMargin: UM.Theme.getSize("wide_margin").height
- bottomMargin: UM.Theme.getSize("wide_margin").height
- top: parent.top
- }
- height: childrenRect.height + 4 * UM.Theme.getSize("default_margin").height
+ padding: UM.Theme.getSize("wide_margin").width
+ visible: toolbox.pluginsInstalledModel.items.length > 0
+ height: childrenRect.height + 2 * UM.Theme.getSize("wide_margin").height
+
Label
{
- visible: toolbox.pluginsInstalledModel.items.length > 0
- width: parent.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("medium")
+ font: UM.Theme.getFont("large")
+ renderType: Text.NativeRendering
}
+
Rectangle
{
- visible: toolbox.pluginsInstalledModel.items.length > 0
+ anchors
+ {
+ left: parent.left
+ right: parent.right
+ margins: parent.padding
+ }
+ id: installedPlugins
color: "transparent"
- width: parent.width
- height: childrenRect.height + 1 * UM.Theme.getSize("default_lining").width
+ height: childrenRect.height + UM.Theme.getSize("default_margin").width
border.color: UM.Theme.getColor("lining")
border.width: UM.Theme.getSize("default_lining").width
Column
{
- height: childrenRect.height
anchors
{
top: parent.top
right: parent.right
left: parent.left
- leftMargin: UM.Theme.getSize("default_margin").width
- rightMargin: UM.Theme.getSize("default_margin").width
- topMargin: UM.Theme.getSize("default_lining").width
- bottomMargin: UM.Theme.getSize("default_lining").width
+ margins: UM.Theme.getSize("default_margin").width
}
Repeater
{
@@ -68,34 +65,42 @@ ScrollView
}
}
}
+
Label
{
- visible: toolbox.materialsInstalledModel.items.length > 0
- width: page.width
+ 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")
+ renderType: Text.NativeRendering
}
+
Rectangle
{
- visible: toolbox.materialsInstalledModel.items.length > 0
+ anchors
+ {
+ left: parent.left
+ right: parent.right
+ margins: parent.padding
+ }
+ id: installedMaterials
color: "transparent"
- width: parent.width
- height: childrenRect.height + 1 * UM.Theme.getSize("default_lining").width
+ height: childrenRect.height + UM.Theme.getSize("default_margin").width
border.color: UM.Theme.getColor("lining")
border.width: UM.Theme.getSize("default_lining").width
Column
{
- height: Math.max( UM.Theme.getSize("wide_margin").height, childrenRect.height)
anchors
{
top: parent.top
right: parent.right
left: parent.left
- leftMargin: UM.Theme.getSize("default_margin").width
- rightMargin: UM.Theme.getSize("default_margin").width
- topMargin: UM.Theme.getSize("default_lining").width
- bottomMargin: UM.Theme.getSize("default_lining").width
+ margins: UM.Theme.getSize("default_margin").width
}
Repeater
{
diff --git a/plugins/Toolbox/resources/qml/ToolboxInstalledTile.qml b/plugins/Toolbox/resources/qml/ToolboxInstalledTile.qml
index b16564fdd2..f85a1056b7 100644
--- a/plugins/Toolbox/resources/qml/ToolboxInstalledTile.qml
+++ b/plugins/Toolbox/resources/qml/ToolboxInstalledTile.qml
@@ -1,7 +1,7 @@
// Copyright (c) 2018 Ultimaker B.V.
// Toolbox is released under the terms of the LGPLv3 or higher.
-import QtQuick 2.7
+import QtQuick 2.10
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
import UM 1.1 as UM
@@ -30,6 +30,7 @@ Item
CheckBox
{
id: disableButton
+ anchors.verticalCenter: pluginInfo.verticalCenter
checked: isEnabled
visible: model.type == "plugin"
width: visible ? UM.Theme.getSize("checkbox").width : 0
@@ -40,26 +41,28 @@ 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("default_bold")
+ font: UM.Theme.getFont("large_bold")
color: pluginInfo.color
+ renderType: Text.NativeRendering
}
Label
{
text: model.description
+ font: UM.Theme.getFont("default")
maximumLineCount: 3
elide: Text.ElideRight
width: parent.width
wrapMode: Text.WordWrap
color: pluginInfo.color
+ renderType: Text.NativeRendering
}
}
Column
@@ -80,6 +83,7 @@ Item
return model.author_name
}
}
+ font: UM.Theme.getFont("medium")
width: parent.width
height: Math.floor(UM.Theme.getSize("toolbox_property_label").height)
wrapMode: Text.WordWrap
@@ -88,16 +92,19 @@ Item
onLinkActivated: Qt.openUrlExternally("mailto:" + model.author_email + "?Subject=Cura: " + model.name + " Plugin")
color: model.enabled ? UM.Theme.getColor("text") : UM.Theme.getColor("lining")
linkColor: UM.Theme.getColor("text_link")
+ renderType: Text.NativeRendering
}
Label
{
text: model.version
+ font: UM.Theme.getFont("default")
width: parent.width
height: UM.Theme.getSize("toolbox_property_label").height
color: UM.Theme.getColor("text")
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignLeft
+ renderType: Text.NativeRendering
}
}
ToolboxInstalledTileActions
diff --git a/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml b/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml
index 8fd88b1cfd..db30b1caf5 100644
--- a/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml
+++ b/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml
@@ -1,15 +1,18 @@
// Copyright (c) 2018 Ultimaker B.V.
// Toolbox is released under the terms of the LGPLv3 or higher.
-import QtQuick 2.7
+import QtQuick 2.10
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
import UM 1.1 as UM
+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
spacing: UM.Theme.getSize("narrow_margin").height
@@ -21,6 +24,7 @@ Column
font: UM.Theme.getFont("default")
wrapMode: Text.WordWrap
width: parent.width
+ renderType: Text.NativeRendering
}
ToolboxProgressButton
@@ -30,66 +34,55 @@ Column
readyLabel: catalog.i18nc("@action:button", "Update")
activeLabel: catalog.i18nc("@action:button", "Updating")
completeLabel: catalog.i18nc("@action:button", "Updated")
- readyAction: function()
+ onReadyAction:
{
toolbox.activePackage = model
toolbox.update(model.id)
}
- activeAction: function()
- {
- toolbox.cancelDownload()
- }
+ onActiveAction: toolbox.cancelDownload()
+
// Don't allow installing while another download is running
- enabled: !(toolbox.isDownloading && toolbox.activePackage != model)
+ enabled: !(toolbox.isDownloading && toolbox.activePackage != model) && !loginRequired
opacity: enabled ? 1.0 : 0.5
visible: canUpdate
}
- Button
+ Label
+ {
+ wrapMode: Text.WordWrap
+ text: catalog.i18nc("@label:The string between and is the highlighted link", "Log in is required to update")
+ font: UM.Theme.getFont("default")
+ color: UM.Theme.getColor("text")
+ linkColor: UM.Theme.getColor("text_link")
+ visible: loginRequired
+ width: updateButton.width
+ renderType: Text.NativeRendering
+
+ MouseArea
+ {
+ anchors.fill: parent
+ onClicked: Cura.API.account.login()
+ }
+ }
+
+ Cura.SecondaryButton
{
id: removeButton
text: canDowngrade ? catalog.i18nc("@action:button", "Downgrade") : catalog.i18nc("@action:button", "Uninstall")
visible: !model.is_bundled && model.is_installed
enabled: !toolbox.isDownloading
- style: ButtonStyle
- {
- background: Rectangle
- {
- implicitWidth: UM.Theme.getSize("toolbox_action_button").width
- implicitHeight: UM.Theme.getSize("toolbox_action_button").height
- color: "transparent"
- border
- {
- width: UM.Theme.getSize("default_lining").width
- color:
- {
- if (control.hovered)
- {
- return UM.Theme.getColor("primary_hover")
- }
- else
- {
- return UM.Theme.getColor("lining")
- }
- }
- }
- }
- label: Label
- {
- text: control.text
- color: UM.Theme.getColor("text")
- verticalAlignment: Text.AlignVCenter
- horizontalAlignment: Text.AlignHCenter
- font: UM.Theme.getFont("default")
- }
- }
+
+ width: UM.Theme.getSize("toolbox_action_button").width
+ height: UM.Theme.getSize("toolbox_action_button").height
+
+ fixedWidthMode: true
+
onClicked: toolbox.checkPackageUsageAndUninstall(model.id)
Connections
{
target: toolbox
onMetadataChanged:
{
- canUpdate = toolbox.canUpdate(model.id)
canDowngrade = toolbox.canDowngrade(model.id)
}
}
diff --git a/plugins/Toolbox/resources/qml/ToolboxLicenseDialog.qml b/plugins/Toolbox/resources/qml/ToolboxLicenseDialog.qml
index b8baf7bc83..40b22c268d 100644
--- a/plugins/Toolbox/resources/qml/ToolboxLicenseDialog.qml
+++ b/plugins/Toolbox/resources/qml/ToolboxLicenseDialog.qml
@@ -1,7 +1,7 @@
// 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.Dialogs 1.1
import QtQuick.Window 2.2
import QtQuick.Controls 1.4
@@ -32,6 +32,7 @@ UM.Dialog
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?")
wrapMode: Text.Wrap
+ renderType: Text.NativeRendering
}
TextArea
{
diff --git a/plugins/Toolbox/resources/qml/ToolboxLoadingPage.qml b/plugins/Toolbox/resources/qml/ToolboxLoadingPage.qml
index 1ba271dcab..025239bd43 100644
--- a/plugins/Toolbox/resources/qml/ToolboxLoadingPage.qml
+++ b/plugins/Toolbox/resources/qml/ToolboxLoadingPage.qml
@@ -1,7 +1,7 @@
// Copyright (c) 2018 Ultimaker B.V.
// Toolbox is released under the terms of the LGPLv3 or higher.
-import QtQuick 2.7
+import QtQuick 2.10
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
@@ -18,5 +18,6 @@ Rectangle
{
centerIn: parent
}
+ renderType: Text.NativeRendering
}
}
diff --git a/plugins/Toolbox/resources/qml/ToolboxProgressButton.qml b/plugins/Toolbox/resources/qml/ToolboxProgressButton.qml
index 2744e40ec9..40d6c1af47 100644
--- a/plugins/Toolbox/resources/qml/ToolboxProgressButton.qml
+++ b/plugins/Toolbox/resources/qml/ToolboxProgressButton.qml
@@ -1,15 +1,16 @@
-// 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.2
-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 Cura 1.0 as Cura
-Item
+Cura.PrimaryButton
{
- id: base
+ id: button
property var active: false
property var complete: false
@@ -18,143 +19,42 @@ Item
property var activeLabel: catalog.i18nc("@action:button", "Cancel")
property var completeLabel: catalog.i18nc("@action:button", "Installed")
- property var readyAction: null // Action when button is ready and clicked (likely install)
- property var activeAction: null // Action when button is active and clicked (likely cancel)
- property var completeAction: null // Action when button is complete and clicked (likely go to 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
-
- Button
+ fixedWidthMode: true
+ text:
{
- id: button
- text:
+ if (complete)
{
- if (complete)
- {
- return completeLabel
- }
- else if (active)
- {
- return activeLabel
- }
- else
- {
- return readyLabel
- }
+ return completeLabel
}
- onClicked:
+ else if (active)
{
- if (complete)
- {
- return completeAction()
- }
- else if (active)
- {
- return activeAction()
- }
- else
- {
- return readyAction()
- }
+ return activeLabel
}
- style: ButtonStyle
+ else
{
- background: Rectangle
- {
- implicitWidth: UM.Theme.getSize("toolbox_action_button").width
- implicitHeight: UM.Theme.getSize("toolbox_action_button").height
- color:
- {
- if (base.complete)
- {
- return "transparent"
- }
- else
- {
- if (control.hovered)
- {
- return UM.Theme.getColor("primary_hover")
- }
- else
- {
- return UM.Theme.getColor("primary")
- }
- }
- }
- border
- {
- width:
- {
- if (base.complete)
- {
- UM.Theme.getSize("default_lining").width
- }
- else
- {
- return 0
- }
- }
- color:
- {
- if (control.hovered)
- {
- return UM.Theme.getColor("primary_hover")
- }
- else
- {
- return UM.Theme.getColor("lining")
- }
- }
- }
- }
- label: Label
- {
- text: control.text
- color:
- {
- if (base.complete)
- {
- return UM.Theme.getColor("text")
- }
- else
- {
- if (control.hovered)
- {
- return UM.Theme.getColor("button_text_hover")
- }
- else
- {
- return UM.Theme.getColor("button_text")
- }
- }
- }
- verticalAlignment: Text.AlignVCenter
- horizontalAlignment: Text.AlignHCenter
- font:
- {
- if (base.complete)
- {
- return UM.Theme.getFont("default")
- }
- else
- {
- return UM.Theme.getFont("default_bold")
- }
- }
- }
+ return readyLabel
}
}
-
- AnimatedImage
+ onClicked:
{
- id: loader
- visible: active
- source: visible ? "../images/loading.gif" : ""
- width: UM.Theme.getSize("toolbox_loader").width
- height: UM.Theme.getSize("toolbox_loader").height
- anchors.right: button.left
- anchors.rightMargin: UM.Theme.getSize("default_margin").width
- anchors.verticalCenter: button.verticalCenter
+ if (complete)
+ {
+ completeAction()
+ }
+ else if (active)
+ {
+ activeAction()
+ }
+ else
+ {
+ readyAction()
+ }
}
+ busy: active
}
diff --git a/plugins/Toolbox/resources/qml/ToolboxTabButton.qml b/plugins/Toolbox/resources/qml/ToolboxTabButton.qml
index 22fb6d73ca..7a7d2be48a 100644
--- a/plugins/Toolbox/resources/qml/ToolboxTabButton.qml
+++ b/plugins/Toolbox/resources/qml/ToolboxTabButton.qml
@@ -1,51 +1,68 @@
// 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 QtQuick 2.10
+import QtQuick.Controls 2.3
import UM 1.1 as UM
Button
{
+ id: control
property bool active: false
- style: ButtonStyle
+
+ implicitWidth: UM.Theme.getSize("toolbox_header_tab").width
+ implicitHeight: UM.Theme.getSize("toolbox_header_tab").height
+
+ background: Item
{
- background: Rectangle
+ id: backgroundItem
+ Rectangle
{
- color: "transparent"
- implicitWidth: UM.Theme.getSize("toolbox_header_tab").width
- implicitHeight: UM.Theme.getSize("toolbox_header_tab").height
- Rectangle
- {
- visible: control.active
- color: UM.Theme.getColor("sidebar_header_highlight_hover")
- anchors.bottom: parent.bottom
- width: parent.width
- height: UM.Theme.getSize("sidebar_header_highlight").height
- }
- }
- label: Label
- {
- text: control.text
- color:
- {
- if(control.hovered)
- {
- return UM.Theme.getColor("topbar_button_text_hovered");
- }
- if(control.active)
- {
- return UM.Theme.getColor("topbar_button_text_active");
- }
- else
- {
- return UM.Theme.getColor("topbar_button_text_inactive");
- }
- }
- font: control.enabled ? (control.active ? UM.Theme.getFont("medium_bold") : UM.Theme.getFont("medium")) : UM.Theme.getFont("default_italic")
- verticalAlignment: Text.AlignVCenter
- horizontalAlignment: Text.AlignHCenter
+ id: highlight
+
+ visible: control.active
+ color: UM.Theme.getColor("primary")
+ anchors.bottom: parent.bottom
+ width: parent.width
+ height: UM.Theme.getSize("toolbox_header_highlight").height
}
}
-}
+
+ contentItem: Label
+ {
+ id: label
+ text: control.text
+ 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/src/AuthorsModel.py b/plugins/Toolbox/src/AuthorsModel.py
index bea3893504..7bfc58df04 100644
--- a/plugins/Toolbox/src/AuthorsModel.py
+++ b/plugins/Toolbox/src/AuthorsModel.py
@@ -2,18 +2,19 @@
# Cura is released under the terms of the LGPLv3 or higher.
import re
-from typing import Dict
+from typing import Dict, List, Optional, Union
from PyQt5.QtCore import Qt, pyqtProperty, pyqtSignal
from UM.Qt.ListModel import ListModel
+
## Model that holds cura packages. By setting the filter property the instances held by this model can be changed.
class AuthorsModel(ListModel):
- def __init__(self, parent = None):
+ def __init__(self, parent = None) -> None:
super().__init__(parent)
- self._metadata = None
+ self._metadata = None # type: Optional[List[Dict[str, Union[str, List[str], int]]]]
self.addRoleName(Qt.UserRole + 1, "id")
self.addRoleName(Qt.UserRole + 2, "name")
@@ -25,39 +26,40 @@ class AuthorsModel(ListModel):
self.addRoleName(Qt.UserRole + 8, "description")
# List of filters for queries. The result is the union of the each list of results.
- self._filter = {} # type: Dict[str,str]
+ self._filter = {} # type: Dict[str, str]
- def setMetadata(self, data):
- self._metadata = data
- self._update()
+ def setMetadata(self, data: List[Dict[str, Union[str, List[str], int]]]):
+ if self._metadata != data:
+ self._metadata = data
+ self._update()
- def _update(self):
- items = []
+ def _update(self) -> None:
+ items = [] # type: List[Dict[str, Union[str, List[str], int, None]]]
if not self._metadata:
- self.setItems([])
+ self.setItems(items)
return
for author in self._metadata:
items.append({
- "id": author["author_id"],
- "name": author["display_name"],
- "email": author["email"] if "email" in author else None,
- "website": author["website"],
- "package_count": author["package_count"] if "package_count" in author else 0,
- "package_types": author["package_types"] if "package_types" in author else [],
- "icon_url": author["icon_url"] if "icon_url" in author else None,
- "description": "Material and quality profiles from {author_name}".format(author_name = author["display_name"])
+ "id": author.get("author_id"),
+ "name": author.get("display_name"),
+ "email": author.get("email"),
+ "website": author.get("website"),
+ "package_count": author.get("package_count", 0),
+ "package_types": author.get("package_types", []),
+ "icon_url": author.get("icon_url"),
+ "description": "Material and quality profiles from {author_name}".format(author_name = author.get("display_name", ""))
})
# Filter on all the key-word arguments.
for key, value in self._filter.items():
- if key is "package_types":
- key_filter = lambda item, value = value: value in item["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)
+ key_filter = lambda item, key = key, value = value: self._matchRegExp(item, key, value) # type: ignore
else:
- key_filter = lambda item, key = key, value = value: self._matchString(item, key, value)
- items = filter(key_filter, items)
+ key_filter = lambda item, key = key, value = value: self._matchString(item, key, value) # type: ignore
+ items = filter(key_filter, items) # type: ignore
# Execute all filters.
filtered_items = list(items)
diff --git a/plugins/Toolbox/src/PackagesModel.py b/plugins/Toolbox/src/PackagesModel.py
index ae4cd7682d..1cf87790bc 100644
--- a/plugins/Toolbox/src/PackagesModel.py
+++ b/plugins/Toolbox/src/PackagesModel.py
@@ -12,7 +12,7 @@ from UM.Qt.ListModel import ListModel
from .ConfigsModel import ConfigsModel
-## Model that holds cura packages. By setting the filter property the instances held by this model can be changed.
+## Model that holds Cura packages. By setting the filter property the instances held by this model can be changed.
class PackagesModel(ListModel):
def __init__(self, parent = None):
super().__init__(parent)
@@ -33,26 +33,31 @@ class PackagesModel(ListModel):
self.addRoleName(Qt.UserRole + 12, "last_updated")
self.addRoleName(Qt.UserRole + 13, "is_bundled")
self.addRoleName(Qt.UserRole + 14, "is_active")
- self.addRoleName(Qt.UserRole + 15, "is_installed") # Scheduled pkgs are included in the model but should not be marked as actually installed
+ self.addRoleName(Qt.UserRole + 15, "is_installed") # Scheduled pkgs are included in the model but should not be marked as actually installed
self.addRoleName(Qt.UserRole + 16, "has_configs")
self.addRoleName(Qt.UserRole + 17, "supported_configs")
self.addRoleName(Qt.UserRole + 18, "download_count")
self.addRoleName(Qt.UserRole + 19, "tags")
self.addRoleName(Qt.UserRole + 20, "links")
self.addRoleName(Qt.UserRole + 21, "website")
+ self.addRoleName(Qt.UserRole + 22, "login_required")
+ self.addRoleName(Qt.UserRole + 23, "average_rating")
+ self.addRoleName(Qt.UserRole + 24, "num_ratings")
+ self.addRoleName(Qt.UserRole + 25, "user_rating")
# List of filters for queries. The result is the union of the each list of results.
self._filter = {} # type: Dict[str, str]
def setMetadata(self, data):
- self._metadata = data
- self._update()
+ if self._metadata != data:
+ self._metadata = data
+ self._update()
def _update(self):
items = []
if self._metadata is None:
- Logger.logException("w", "Failed to load packages for Toolbox")
+ Logger.logException("w", "Failed to load packages for Marketplace")
self.setItems(items)
return
@@ -70,7 +75,7 @@ class PackagesModel(ListModel):
# Links is a list of dictionaries with "title" and "url". Convert this list into a dict so it's easier
# to process.
- link_list = package['data']['links'] if 'links' in package['data'] else []
+ link_list = package["data"]["links"] if "links" in package["data"] else []
links_dict = {d["title"]: d["url"] for d in link_list}
if "author_id" not in package["author"] or "display_name" not in package["author"]:
@@ -99,11 +104,15 @@ class PackagesModel(ListModel):
"tags": package["tags"] if "tags" in package else [],
"links": links_dict,
"website": package["website"] if "website" in package else None,
+ "login_required": "login-required" in package.get("tags", []),
+ "average_rating": float(package.get("rating", {}).get("average", 0)),
+ "num_ratings": package.get("rating", {}).get("count", 0),
+ "user_rating": package.get("rating", {}).get("user_rating", 0)
})
# 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 3e2085277a..4dabba87a0 100644
--- a/plugins/Toolbox/src/Toolbox.py
+++ b/plugins/Toolbox/src/Toolbox.py
@@ -13,11 +13,11 @@ from PyQt5.QtNetwork import QNetworkAccessManager, QNetworkRequest, QNetworkRepl
from UM.Logger import Logger
from UM.PluginRegistry import PluginRegistry
from UM.Extension import Extension
-from UM.Qt.ListModel import ListModel
from UM.i18n import i18nCatalog
from UM.Version import Version
-import cura
+from cura import ApplicationMetadata
+from cura import UltimakerCloudAuthentication
from cura.CuraApplication import CuraApplication
from .AuthorsModel import AuthorsModel
@@ -31,17 +31,14 @@ i18n_catalog = i18nCatalog("cura")
## The Toolbox class is responsible of communicating with the server through the API
class Toolbox(QObject, Extension):
- DEFAULT_CLOUD_API_ROOT = "https://api.ultimaker.com" #type: str
- DEFAULT_CLOUD_API_VERSION = 1 #type: int
-
def __init__(self, application: CuraApplication) -> None:
super().__init__()
self._application = application # type: CuraApplication
- self._sdk_version = None # type: Optional[Union[str, int]]
- self._cloud_api_version = None # type: Optional[int]
- self._cloud_api_root = None # type: Optional[str]
+ self._sdk_version = ApplicationMetadata.CuraSDKVersion # type: Union[str, int]
+ self._cloud_api_version = UltimakerCloudAuthentication.CuraCloudAPIVersion # type: str
+ self._cloud_api_root = UltimakerCloudAuthentication.CuraCloudAPIRoot # type: str
self._api_url = None # type: Optional[str]
# Network:
@@ -50,47 +47,34 @@ 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_header = [
- b"User-Agent",
- str.encode(
- "%s/%s (%s %s)" % (
- self._application.getApplicationName(),
- self._application.getVersion(),
- platform.system(),
- platform.machine(),
- )
- )
- ]
+ 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]
self._old_plugin_metadata = dict() # type: Dict[str, Dict[str, Any]]
- # Data:
- self._metadata = {
+ # The responses as given by the server parsed to a list.
+ self._server_response_data = {
"authors": [],
- "packages": [],
- "plugins_showcase": [],
- "plugins_available": [],
- "plugins_installed": [],
- "materials_showcase": [],
- "materials_available": [],
- "materials_installed": [],
- "materials_generic": []
+ "packages": []
} # type: Dict[str, List[Any]]
# Models:
self._models = {
"authors": AuthorsModel(self),
"packages": PackagesModel(self),
- "plugins_showcase": PackagesModel(self),
- "plugins_available": PackagesModel(self),
- "plugins_installed": PackagesModel(self),
- "materials_showcase": AuthorsModel(self),
- "materials_available": AuthorsModel(self),
- "materials_installed": PackagesModel(self),
- "materials_generic": PackagesModel(self)
- } # type: Dict[str, ListModel]
+ } # type: Dict[str, Union[AuthorsModel, PackagesModel]]
+
+ self._plugins_showcase_model = PackagesModel(self)
+ self._plugins_available_model = PackagesModel(self)
+ self._plugins_installed_model = PackagesModel(self)
+
+ self._materials_showcase_model = AuthorsModel(self)
+ self._materials_available_model = AuthorsModel(self)
+ self._materials_installed_model = PackagesModel(self)
+ self._materials_generic_model = PackagesModel(self)
# These properties are for keeping track of the UI state:
# ----------------------------------------------------------------------
@@ -120,6 +104,8 @@ 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:
# --------------------------------------------------------------------------
@@ -139,12 +125,38 @@ class Toolbox(QObject, Extension):
showLicenseDialog = pyqtSignal()
uninstallVariablesChanged = pyqtSignal()
+ def _updateRequestHeader(self):
+ self._request_headers = [
+ (b"User-Agent",
+ str.encode(
+ "%s/%s (%s %s)" % (
+ self._application.getApplicationName(),
+ self._application.getVersion(),
+ platform.system(),
+ platform.machine(),
+ )
+ ))
+ ]
+ access_token = self._application.getCuraAPI().account.accessToken
+ if access_token:
+ self._request_headers.append((b"Authorization", "Bearer {}".format(access_token).encode()))
+
def _resetUninstallVariables(self) -> None:
self._package_id_to_uninstall = None # type: Optional[str]
self._package_name_to_uninstall = ""
self._package_used_materials = [] # type: List[Tuple[GlobalStack, str, str]]
self._package_used_qualities = [] # type: List[Tuple[GlobalStack, str, str]]
+ @pyqtSlot(str, int)
+ def ratePackage(self, package_id: str, rating: int) -> None:
+ url = QUrl("{base_url}/packages/{package_id}/ratings".format(base_url=self._api_url, package_id = package_id))
+
+ self._rate_request = QNetworkRequest(url)
+ for header_name, header_value in self._request_headers:
+ cast(QNetworkRequest, self._rate_request).setRawHeader(header_name, header_value)
+ data = "{\"data\": {\"cura_version\": \"%s\", \"rating\": %i}}" % (Version(self._application.getVersion()), rating)
+ self._rate_reply = cast(QNetworkAccessManager, self._network_manager).put(self._rate_request, data.encode())
+
@pyqtSlot(result = str)
def getLicenseDialogPluginName(self) -> str:
return self._license_dialog_plugin_name
@@ -168,56 +180,20 @@ class Toolbox(QObject, Extension):
def _onAppInitialized(self) -> None:
self._plugin_registry = self._application.getPluginRegistry()
self._package_manager = self._application.getPackageManager()
- self._sdk_version = self._getSDKVersion()
- self._cloud_api_version = self._getCloudAPIVersion()
- self._cloud_api_root = self._getCloudAPIRoot()
self._api_url = "{cloud_api_root}/cura-packages/v{cloud_api_version}/cura/v{sdk_version}".format(
- cloud_api_root=self._cloud_api_root,
- cloud_api_version=self._cloud_api_version,
- sdk_version=self._sdk_version
+ cloud_api_root = self._cloud_api_root,
+ cloud_api_version = self._cloud_api_version,
+ sdk_version = self._sdk_version
)
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)),
- "plugins_showcase": QUrl("{base_url}/showcase".format(base_url=self._api_url)),
- "plugins_available": QUrl("{base_url}/packages?package_type=plugin".format(base_url=self._api_url)),
- "materials_showcase": QUrl("{base_url}/showcase".format(base_url=self._api_url)),
- "materials_available": QUrl("{base_url}/packages?package_type=material".format(base_url=self._api_url)),
- "materials_generic": QUrl("{base_url}/packages?package_type=material&tags=generic".format(base_url=self._api_url))
+ "authors": QUrl("{base_url}/authors".format(base_url = self._api_url)),
+ "packages": QUrl("{base_url}/packages".format(base_url = self._api_url))
}
- # Get the API root for the packages API depending on Cura version settings.
- def _getCloudAPIRoot(self) -> str:
- if not hasattr(cura, "CuraVersion"):
- return self.DEFAULT_CLOUD_API_ROOT
- if not hasattr(cura.CuraVersion, "CuraCloudAPIRoot"): # type: ignore
- return self.DEFAULT_CLOUD_API_ROOT
- if not cura.CuraVersion.CuraCloudAPIRoot: # type: ignore
- return self.DEFAULT_CLOUD_API_ROOT
- return cura.CuraVersion.CuraCloudAPIRoot # type: ignore
+ # Request the latest and greatest!
+ self._fetchPackageData()
- # Get the cloud API version from CuraVersion
- def _getCloudAPIVersion(self) -> int:
- if not hasattr(cura, "CuraVersion"):
- return self.DEFAULT_CLOUD_API_VERSION
- if not hasattr(cura.CuraVersion, "CuraCloudAPIVersion"): # type: ignore
- return self.DEFAULT_CLOUD_API_VERSION
- if not cura.CuraVersion.CuraCloudAPIVersion: # type: ignore
- return self.DEFAULT_CLOUD_API_VERSION
- return cura.CuraVersion.CuraCloudAPIVersion # type: ignore
-
- # Get the packages version depending on Cura version settings.
- def _getSDKVersion(self) -> Union[int, str]:
- if not hasattr(cura, "CuraVersion"):
- return self._plugin_registry.APIVersion
- if not hasattr(cura.CuraVersion, "CuraSDKVersion"): # type: ignore
- return self._plugin_registry.APIVersion
- if not cura.CuraVersion.CuraSDKVersion: # type: ignore
- return self._plugin_registry.APIVersion
- return cura.CuraVersion.CuraSDKVersion # type: ignore
-
- @pyqtSlot()
- def browsePackages(self) -> None:
+ def _fetchPackageData(self):
# 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.
@@ -231,21 +207,19 @@ class Toolbox(QObject, Extension):
# Make remote requests:
self._makeRequestByType("packages")
self._makeRequestByType("authors")
- # TODO: Uncomment in the future when the tag-filtered api calls work in the cloud server
- # self._makeRequestByType("plugins_showcase")
- # self._makeRequestByType("plugins_available")
- # self._makeRequestByType("materials_showcase")
- # self._makeRequestByType("materials_available")
- # self._makeRequestByType("materials_generic")
# Gather installed packages:
self._updateInstalledModels()
+ @pyqtSlot()
+ def browsePackages(self) -> None:
+ self._fetchPackageData()
+
if not self._dialog:
self._dialog = self._createDialog("Toolbox.qml")
if not self._dialog:
- Logger.log("e", "Unexpected error trying to create the 'Toolbox' dialog.")
+ Logger.log("e", "Unexpected error trying to create the 'Marketplace' dialog.")
return
self._dialog.show()
@@ -254,7 +228,7 @@ class Toolbox(QObject, Extension):
self.enabledChanged.emit()
def _createDialog(self, qml_name: str) -> Optional[QObject]:
- Logger.log("d", "Toolbox: Creating dialog [%s].", qml_name)
+ Logger.log("d", "Marketplace: Creating dialog [%s].", qml_name)
plugin_path = PluginRegistry.getInstance().getPluginPath(self.getPluginId())
if not plugin_path:
return None
@@ -262,24 +236,33 @@ class Toolbox(QObject, Extension):
dialog = self._application.createQmlComponent(path, {"toolbox": self})
if not dialog:
- raise Exception("Failed to create toolbox dialog")
+ raise Exception("Failed to create Marketplace dialog")
return dialog
- def _convertPluginMetadata(self, plugin: Dict[str, Any]) -> Dict[str, Any]:
- formatted = {
- "package_id": plugin["id"],
- "package_type": "plugin",
- "display_name": plugin["plugin"]["name"],
- "package_version": plugin["plugin"]["version"],
- "sdk_version": plugin["plugin"]["api"],
- "author": {
- "author_id": plugin["plugin"]["author"],
- "display_name": plugin["plugin"]["author"]
- },
- "is_installed": True,
- "description": plugin["plugin"]["description"]
- }
- return formatted
+ def _convertPluginMetadata(self, plugin_data: Dict[str, Any]) -> Optional[Dict[str, Any]]:
+ try:
+ highest_sdk_version_supported = Version(0)
+ for supported_version in plugin_data["plugin"]["supported_sdk_versions"]:
+ if supported_version > highest_sdk_version_supported:
+ highest_sdk_version_supported = supported_version
+
+ formatted = {
+ "package_id": plugin_data["id"],
+ "package_type": "plugin",
+ "display_name": plugin_data["plugin"]["name"],
+ "package_version": plugin_data["plugin"]["version"],
+ "sdk_version": highest_sdk_version_supported,
+ "author": {
+ "author_id": plugin_data["plugin"]["author"],
+ "display_name": plugin_data["plugin"]["author"]
+ },
+ "is_installed": True,
+ "description": plugin_data["plugin"]["description"]
+ }
+ return formatted
+ except KeyError:
+ Logger.log("w", "Unable to convert plugin meta data %s", str(plugin_data))
+ return None
@pyqtSlot()
def _updateInstalledModels(self) -> None:
@@ -295,11 +278,13 @@ 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)
-
+ if new_metadata is None:
+ # Something went wrong converting it.
+ continue
self._old_plugin_ids.add(plugin_id)
self._old_plugin_metadata[new_metadata["package_id"]] = new_metadata
@@ -313,13 +298,10 @@ class Toolbox(QObject, Extension):
if plugin_id not in all_plugin_package_ids)
self._old_plugin_metadata = {k: v for k, v in self._old_plugin_metadata.items() if k in self._old_plugin_ids}
- self._metadata["plugins_installed"] = all_packages["plugin"] + list(self._old_plugin_metadata.values())
- self._models["plugins_installed"].setMetadata(self._metadata["plugins_installed"])
+ self._plugins_installed_model.setMetadata(all_packages["plugin"] + list(self._old_plugin_metadata.values()))
self.metadataChanged.emit()
if "material" in all_packages:
- self._metadata["materials_installed"] = all_packages["material"]
- # TODO: ADD MATERIALS HERE ONCE MATERIALS PORTION OF TOOLBOX IS LIVE
- self._models["materials_installed"].setMetadata(self._metadata["materials_installed"])
+ self._materials_installed_model.setMetadata(all_packages["material"])
self.metadataChanged.emit()
@pyqtSlot(str)
@@ -473,42 +455,12 @@ class Toolbox(QObject, Extension):
def getRemotePackage(self, package_id: str) -> Optional[Dict]:
# TODO: make the lookup in a dict, not a loop. canUpdate is called for every item.
remote_package = None
- for package in self._metadata["packages"]:
+ for package in self._server_response_data["packages"]:
if package["package_id"] == package_id:
remote_package = package
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:
- Logger.log("i", "Could not find package [%s] as installed in the package manager, fall back to check the old plugins",
- package_id)
- local_package = self.getOldPluginPackageMetadata(package_id)
- if local_package is None:
- Logger.log("i", "Could not find package [%s] in the old plugins", package_id)
- 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:
- can_upgrade = local_package.get("sdk_version", 0) < remote_package.get("sdk_version", 0)
-
- 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
@@ -536,8 +488,8 @@ class Toolbox(QObject, Extension):
@pyqtSlot(str, result = int)
def getNumberOfInstalledPackagesByAuthor(self, author_id: str) -> int:
count = 0
- for package in self._metadata["materials_installed"]:
- if package["author"]["author_id"] == author_id:
+ for package in self._materials_installed_model.items:
+ if package["author_id"] == author_id:
count += 1
return count
@@ -545,7 +497,7 @@ class Toolbox(QObject, Extension):
@pyqtSlot(str, result = int)
def getTotalNumberOfMaterialPackagesByAuthor(self, author_id: str) -> int:
count = 0
- for package in self._metadata["packages"]:
+ for package in self._server_response_data["packages"]:
if package["package_type"] == "material":
if package["author"]["author_id"] == author_id:
count += 1
@@ -559,34 +511,31 @@ class Toolbox(QObject, Extension):
# Check for plugins that were installed with the old plugin browser
def isOldPlugin(self, plugin_id: str) -> bool:
- if plugin_id in self._old_plugin_ids:
- return True
- return False
+ return plugin_id in self._old_plugin_ids
def getOldPluginPackageMetadata(self, plugin_id: str) -> Optional[Dict[str, Any]]:
return self._old_plugin_metadata.get(plugin_id)
- def loadingComplete(self) -> bool:
+ def isLoadingComplete(self) -> bool:
populated = 0
- for list in self._metadata.items():
- if len(list) > 0:
+ for metadata_list in self._server_response_data.items():
+ if metadata_list:
populated += 1
- if populated == len(self._metadata.items()):
- return True
- return False
+ return populated == len(self._server_response_data.items())
# Make API Calls
# --------------------------------------------------------------------------
- def _makeRequestByType(self, type: str) -> None:
- Logger.log("i", "Toolbox: Requesting %s metadata from server.", type)
- request = QNetworkRequest(self._request_urls[type])
- request.setRawHeader(*self._request_header)
+ def _makeRequestByType(self, request_type: str) -> None:
+ 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)
if self._network_manager:
self._network_manager.get(request)
@pyqtSlot(str)
def startDownload(self, url: str) -> None:
- Logger.log("i", "Toolbox: Attempting to download & install package from %s.", url)
+ Logger.log("i", "Attempting to download & install package from %s.", url)
url = QUrl(url)
self._download_request = QNetworkRequest(url)
if hasattr(QNetworkRequest, "FollowRedirectsAttribute"):
@@ -595,7 +544,8 @@ class Toolbox(QObject, Extension):
if hasattr(QNetworkRequest, "RedirectPolicyAttribute"):
# Patch for Qt 5.9+
cast(QNetworkRequest, self._download_request).setAttribute(QNetworkRequest.RedirectPolicyAttribute, True)
- cast(QNetworkRequest, self._download_request).setRawHeader(*self._request_header)
+ for header_name, header_value in self._request_headers:
+ cast(QNetworkRequest, self._download_request).setRawHeader(header_name, header_value)
self._download_reply = cast(QNetworkAccessManager, self._network_manager).get(self._download_request)
self.setDownloadProgress(0)
self.setIsDownloading(True)
@@ -603,16 +553,22 @@ class Toolbox(QObject, Extension):
@pyqtSlot()
def cancelDownload(self) -> None:
- Logger.log("i", "Toolbox: User cancelled the download of a package.")
+ Logger.log("i", "User cancelled the download of a package.")
self.resetDownload()
def resetDownload(self) -> None:
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.
- pass #Don't need to disconnect.
- self._download_reply.abort()
+ except (TypeError, RuntimeError): # Raised when the method is not connected to the signal yet.
+ pass # Don't need to disconnect.
+ 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)
@@ -637,22 +593,8 @@ class Toolbox(QObject, Extension):
self.resetDownload()
return
- # HACK: These request are not handled independently at this moment, but together from the "packages" call
- do_not_handle = [
- "materials_available",
- "materials_showcase",
- "materials_generic",
- "plugins_available",
- "plugins_showcase",
- ]
-
if reply.operation() == QNetworkAccessManager.GetOperation:
- for type, url in self._request_urls.items():
-
- # HACK: Do nothing because we'll handle these from the "packages" call
- if type in do_not_handle:
- continue
-
+ for response_type, url in self._request_urls.items():
if reply.url() == url:
if reply.attribute(QNetworkRequest.HttpStatusCodeAttribute) == 200:
try:
@@ -665,49 +607,60 @@ class Toolbox(QObject, Extension):
return
# Create model and apply metadata:
- if not self._models[type]:
- Logger.log("e", "Could not find the %s model.", type)
+ if not self._models[response_type]:
+ Logger.log("e", "Could not find the %s model.", response_type)
break
- self._metadata[type] = json_data["data"]
- self._models[type].setMetadata(self._metadata[type])
+ self._server_response_data[response_type] = json_data["data"]
+ self._models[response_type].setMetadata(self._server_response_data[response_type])
- # Do some auto filtering
- # TODO: Make multiple API calls in the future to handle this
- if type is "packages":
- self._models[type].setFilter({"type": "plugin"})
- self.buildMaterialsModels()
- self.buildPluginsModels()
- if type is "authors":
- self._models[type].setFilter({"package_types": "material"})
- if type is "materials_generic":
- self._models[type].setFilter({"tags": "generic"})
+ if response_type == "packages":
+ self._models[response_type].setFilter({"type": "plugin"})
+ self.reBuildMaterialsModels()
+ self.reBuildPluginsModels()
+ self._notifyPackageManager()
+ elif response_type == "authors":
+ self._models[response_type].setFilter({"package_types": "material"})
+ self._models[response_type].setFilter({"tags": "generic"})
self.metadataChanged.emit()
- if self.loadingComplete() is True:
+ if self.isLoadingComplete():
self.setViewPage("overview")
- return
except json.decoder.JSONDecodeError:
- Logger.log("w", "Toolbox: Received invalid JSON for %s.", type)
+ Logger.log("w", "Received invalid JSON for %s.", response_type)
break
else:
+ Logger.log("w", "Unable to connect with the server, we got a response code %s while trying to connect to %s", reply.attribute(QNetworkRequest.HttpStatusCodeAttribute), reply.url())
self.setViewPage("errored")
self.resetDownload()
- return
-
- else:
+ elif reply.operation() == QNetworkAccessManager.PutOperation:
# 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
self.setDownloadProgress(new_progress)
if bytes_sent == bytes_total:
self.setIsDownloading(False)
- cast(QNetworkReply, self._download_reply).downloadProgress.disconnect(self._onDownloadProgress)
+ 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:
+ 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
@@ -717,10 +670,10 @@ class Toolbox(QObject, Extension):
self._onDownloadComplete(file_path)
def _onDownloadComplete(self, file_path: str) -> None:
- Logger.log("i", "Toolbox: Download complete.")
+ Logger.log("i", "Download complete.")
package_info = self._package_manager.getPackageInfo(file_path)
if not package_info:
- Logger.log("w", "Toolbox: Package file [%s] was not a valid CuraPackage.", file_path)
+ Logger.log("w", "Package file [%s] was not a valid CuraPackage.", file_path)
return
license_content = self._package_manager.getPackageLicense(file_path)
@@ -729,7 +682,6 @@ class Toolbox(QObject, Extension):
return
self.install(file_path)
- return
# Getter & Setters for Properties:
# --------------------------------------------------------------------------
@@ -752,8 +704,9 @@ class Toolbox(QObject, Extension):
return self._is_downloading
def setActivePackage(self, package: Dict[str, Any]) -> None:
- self._active_package = package
- self.activePackageChanged.emit()
+ if self._active_package != package:
+ self._active_package = package
+ self.activePackageChanged.emit()
## The active package is the package that is currently being downloaded
@pyqtProperty(QObject, fset = setActivePackage, notify = activePackageChanged)
@@ -761,16 +714,18 @@ class Toolbox(QObject, Extension):
return self._active_package
def setViewCategory(self, category: str = "plugin") -> None:
- self._view_category = category
- self.viewChanged.emit()
+ if self._view_category != category:
+ self._view_category = category
+ self.viewChanged.emit()
@pyqtProperty(str, fset = setViewCategory, notify = viewChanged)
def viewCategory(self) -> str:
return self._view_category
def setViewPage(self, page: str = "overview") -> None:
- self._view_page = page
- self.viewChanged.emit()
+ if self._view_page != page:
+ self._view_page = page
+ self.viewChanged.emit()
@pyqtProperty(str, fset = setViewPage, notify = viewChanged)
def viewPage(self) -> str:
@@ -778,48 +733,48 @@ class Toolbox(QObject, Extension):
# Exposed Models:
# --------------------------------------------------------------------------
- @pyqtProperty(QObject, notify = metadataChanged)
+ @pyqtProperty(QObject, constant=True)
def authorsModel(self) -> AuthorsModel:
return cast(AuthorsModel, self._models["authors"])
- @pyqtProperty(QObject, notify = metadataChanged)
+ @pyqtProperty(QObject, constant=True)
def packagesModel(self) -> PackagesModel:
return cast(PackagesModel, self._models["packages"])
- @pyqtProperty(QObject, notify = metadataChanged)
+ @pyqtProperty(QObject, constant=True)
def pluginsShowcaseModel(self) -> PackagesModel:
- return cast(PackagesModel, self._models["plugins_showcase"])
+ return self._plugins_showcase_model
- @pyqtProperty(QObject, notify = metadataChanged)
+ @pyqtProperty(QObject, constant=True)
def pluginsAvailableModel(self) -> PackagesModel:
- return cast(PackagesModel, self._models["plugins_available"])
+ return self._plugins_available_model
- @pyqtProperty(QObject, notify = metadataChanged)
+ @pyqtProperty(QObject, constant=True)
def pluginsInstalledModel(self) -> PackagesModel:
- return cast(PackagesModel, self._models["plugins_installed"])
+ return self._plugins_installed_model
- @pyqtProperty(QObject, notify = metadataChanged)
+ @pyqtProperty(QObject, constant=True)
def materialsShowcaseModel(self) -> AuthorsModel:
- return cast(AuthorsModel, self._models["materials_showcase"])
+ return self._materials_showcase_model
- @pyqtProperty(QObject, notify = metadataChanged)
+ @pyqtProperty(QObject, constant=True)
def materialsAvailableModel(self) -> AuthorsModel:
- return cast(AuthorsModel, self._models["materials_available"])
+ return self._materials_available_model
- @pyqtProperty(QObject, notify = metadataChanged)
+ @pyqtProperty(QObject, constant=True)
def materialsInstalledModel(self) -> PackagesModel:
- return cast(PackagesModel, self._models["materials_installed"])
+ return self._materials_installed_model
- @pyqtProperty(QObject, notify=metadataChanged)
+ @pyqtProperty(QObject, constant=True)
def materialsGenericModel(self) -> PackagesModel:
- return cast(PackagesModel, self._models["materials_generic"])
+ return self._materials_generic_model
# Filter Models:
# --------------------------------------------------------------------------
@pyqtSlot(str, str, str)
def filterModelByProp(self, model_type: str, filter_type: str, parameter: str) -> None:
if not self._models[model_type]:
- Logger.log("w", "Toolbox: Couldn't filter %s model because it doesn't exist.", model_type)
+ Logger.log("w", "Couldn't filter %s model because it doesn't exist.", model_type)
return
self._models[model_type].setFilter({filter_type: parameter})
self.filterChanged.emit()
@@ -827,7 +782,7 @@ class Toolbox(QObject, Extension):
@pyqtSlot(str, "QVariantMap")
def setFilters(self, model_type: str, filter_dict: dict) -> None:
if not self._models[model_type]:
- Logger.log("w", "Toolbox: Couldn't filter %s model because it doesn't exist.", model_type)
+ Logger.log("w", "Couldn't filter %s model because it doesn't exist.", model_type)
return
self._models[model_type].setFilter(filter_dict)
self.filterChanged.emit()
@@ -835,20 +790,21 @@ class Toolbox(QObject, Extension):
@pyqtSlot(str)
def removeFilters(self, model_type: str) -> None:
if not self._models[model_type]:
- Logger.log("w", "Toolbox: Couldn't remove filters on %s model because it doesn't exist.", model_type)
+ Logger.log("w", "Couldn't remove filters on %s model because it doesn't exist.", model_type)
return
self._models[model_type].setFilter({})
self.filterChanged.emit()
# HACK(S):
# --------------------------------------------------------------------------
- def buildMaterialsModels(self) -> None:
- self._metadata["materials_showcase"] = []
- self._metadata["materials_available"] = []
+ def reBuildMaterialsModels(self) -> None:
+ materials_showcase_metadata = []
+ materials_available_metadata = []
+ materials_generic_metadata = []
- processed_authors = [] # type: List[str]
+ processed_authors = [] # type: List[str]
- for item in self._metadata["packages"]:
+ for item in self._server_response_data["packages"]:
if item["package_type"] == "material":
author = item["author"]
@@ -857,30 +813,29 @@ class Toolbox(QObject, Extension):
# Generic materials to be in the same section
if "generic" in item["tags"]:
- self._metadata["materials_generic"].append(item)
+ materials_generic_metadata.append(item)
else:
if "showcase" in item["tags"]:
- self._metadata["materials_showcase"].append(author)
+ materials_showcase_metadata.append(author)
else:
- self._metadata["materials_available"].append(author)
+ materials_available_metadata.append(author)
processed_authors.append(author["author_id"])
- self._models["materials_showcase"].setMetadata(self._metadata["materials_showcase"])
- self._models["materials_available"].setMetadata(self._metadata["materials_available"])
- self._models["materials_generic"].setMetadata(self._metadata["materials_generic"])
+ self._materials_showcase_model.setMetadata(materials_showcase_metadata)
+ self._materials_available_model.setMetadata(materials_available_metadata)
+ self._materials_generic_model.setMetadata(materials_generic_metadata)
- def buildPluginsModels(self) -> None:
- self._metadata["plugins_showcase"] = []
- self._metadata["plugins_available"] = []
+ def reBuildPluginsModels(self) -> None:
+ plugins_showcase_metadata = []
+ plugins_available_metadata = []
- for item in self._metadata["packages"]:
+ for item in self._server_response_data["packages"]:
if item["package_type"] == "plugin":
-
if "showcase" in item["tags"]:
- self._metadata["plugins_showcase"].append(item)
+ plugins_showcase_metadata.append(item)
else:
- self._metadata["plugins_available"].append(item)
+ plugins_available_metadata.append(item)
- self._models["plugins_showcase"].setMetadata(self._metadata["plugins_showcase"])
- self._models["plugins_available"].setMetadata(self._metadata["plugins_available"])
+ self._plugins_showcase_model.setMetadata(plugins_showcase_metadata)
+ self._plugins_available_model.setMetadata(plugins_available_metadata)
diff --git a/plugins/UFPReader/UFPReader.py b/plugins/UFPReader/UFPReader.py
new file mode 100644
index 0000000000..18527e6450
--- /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) # 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..b56b555b36
--- /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": ["6.0.0"],
+ "i18n-catalog": "cura"
+}
\ No newline at end of file
diff --git a/plugins/UFPWriter/UFPWriter.py b/plugins/UFPWriter/UFPWriter.py
index b3088fc863..2aece1092a 100644
--- a/plugins/UFPWriter/UFPWriter.py
+++ b/plugins/UFPWriter/UFPWriter.py
@@ -28,7 +28,7 @@ class UFPWriter(MeshWriter):
MimeTypeDatabase.addMimeType(
MimeType(
name = "application/x-ufp",
- comment = "Cura UFP File",
+ comment = "Ultimaker Format Package",
suffixes = ["ufp"]
)
)
@@ -95,10 +95,14 @@ class UFPWriter(MeshWriter):
added_materials = []
for extruder_stack in global_stack.extruders.values():
material = extruder_stack.material
- material_file_name = material.getMetaData()["base_file"] + ".xml.fdm_material"
+ try:
+ material_file_name = material.getMetaData()["base_file"] + ".xml.fdm_material"
+ except KeyError:
+ Logger.log("w", "Unable to get base_file for the material %s", material.getId())
+ continue
material_file_name = "/Materials/" + material_file_name
- #Same material cannot be added
+ # The same material should not be added again.
if material_file_name in added_materials:
continue
diff --git a/plugins/UFPWriter/plugin.json b/plugins/UFPWriter/plugin.json
index ab590353e0..288d6acf77 100644
--- a/plugins/UFPWriter/plugin.json
+++ b/plugins/UFPWriter/plugin.json
@@ -1,8 +1,8 @@
{
"name": "UFP Writer",
"author": "Ultimaker B.V.",
- "version": "1.0.0",
+ "version": "1.0.1",
"description": "Provides support for writing Ultimaker Format Packages.",
- "api": 5,
+ "api": "6.0",
"i18n-catalog": "cura"
}
\ No newline at end of file
diff --git a/plugins/UM3NetworkPrinting/__init__.py b/plugins/UM3NetworkPrinting/__init__.py
index e2ad5a2b12..3da7795589 100644
--- a/plugins/UM3NetworkPrinting/__init__.py
+++ b/plugins/UM3NetworkPrinting/__init__.py
@@ -1,11 +1,15 @@
# Copyright (c) 2017 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
-
from .src import DiscoverUM3Action
from .src import UM3OutputDevicePlugin
+
def getMetaData():
return {}
+
def register(app):
- return { "output_device": UM3OutputDevicePlugin.UM3OutputDevicePlugin(), "machine_action": DiscoverUM3Action.DiscoverUM3Action()}
\ No newline at end of file
+ return {
+ "output_device": UM3OutputDevicePlugin.UM3OutputDevicePlugin(),
+ "machine_action": DiscoverUM3Action.DiscoverUM3Action()
+ }
diff --git a/plugins/UM3NetworkPrinting/plugin.json b/plugins/UM3NetworkPrinting/plugin.json
index d415338374..088b4dae6a 100644
--- a/plugins/UM3NetworkPrinting/plugin.json
+++ b/plugins/UM3NetworkPrinting/plugin.json
@@ -2,7 +2,7 @@
"name": "UM3 Network Connection",
"author": "Ultimaker B.V.",
"description": "Manages network connections to Ultimaker 3 printers.",
- "version": "1.0.0",
- "api": 5,
+ "version": "1.0.1",
+ "api": "6.0",
"i18n-catalog": "cura"
}
diff --git a/plugins/UM3NetworkPrinting/resources/png/Ultimaker 3 Extended.png b/plugins/UM3NetworkPrinting/resources/png/Ultimaker 3 Extended.png
new file mode 100644
index 0000000000..1ce19c2933
Binary files /dev/null and b/plugins/UM3NetworkPrinting/resources/png/Ultimaker 3 Extended.png differ
diff --git a/plugins/UM3NetworkPrinting/resources/png/Ultimaker 3.png b/plugins/UM3NetworkPrinting/resources/png/Ultimaker 3.png
new file mode 100644
index 0000000000..4639cb3fde
Binary files /dev/null and b/plugins/UM3NetworkPrinting/resources/png/Ultimaker 3.png differ
diff --git a/plugins/UM3NetworkPrinting/resources/png/Ultimaker S5.png b/plugins/UM3NetworkPrinting/resources/png/Ultimaker S5.png
new file mode 100644
index 0000000000..29ba428e38
Binary files /dev/null and b/plugins/UM3NetworkPrinting/resources/png/Ultimaker S5.png differ
diff --git a/plugins/UM3NetworkPrinting/resources/qml/CameraButton.qml b/plugins/UM3NetworkPrinting/resources/qml/CameraButton.qml
index 1ceebccf89..c0369cac0b 100644
--- a/plugins/UM3NetworkPrinting/resources/qml/CameraButton.qml
+++ b/plugins/UM3NetworkPrinting/resources/qml/CameraButton.qml
@@ -1,46 +1,55 @@
+// Copyright (c) 2018 Ultimaker B.V.
+// Cura is released under the terms of the LGPLv3 or higher.
+
import QtQuick 2.3
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.3
-import QtQuick.Controls 2.0 as Controls2
-import QtGraphicalEffects 1.0
-
import UM 1.3 as UM
import Cura 1.0 as Cura
Rectangle
{
- property var iconSource: null
+ id: base
- width: 36 * screenScaleFactor
+ property var enabled: true
+
+ property var iconSource: null
+ color: enabled ? UM.Theme.getColor("monitor_icon_primary") : UM.Theme.getColor("monitor_icon_disabled")
height: width
- radius: 0.5 * width
- color: clickArea.containsMouse ? UM.Theme.getColor("primary_hover") : UM.Theme.getColor("primary")
+ radius: Math.round(0.5 * width)
+ width: 24 * screenScaleFactor
UM.RecolorImage
{
id: icon
- width: parent.width / 2
+ anchors
+ {
+ horizontalCenter: parent.horizontalCenter
+ verticalCenter: parent.verticalCenter
+ }
+ color: UM.Theme.getColor("monitor_icon_accent")
height: width
- anchors.verticalCenter: parent.verticalCenter
- anchors.horizontalCenter: parent.horizontalCenter
- color: UM.Theme.getColor("primary_text")
source: iconSource
+ width: Math.round(parent.width / 2)
}
MouseArea
{
id: clickArea
- anchors.fill:parent
- hoverEnabled: true
+ anchors.fill: parent
+ hoverEnabled: base.enabled
onClicked:
{
- if (OutputDevice.activeCamera !== null)
+ if (base.enabled)
{
- OutputDevice.setActiveCamera(null)
- }
- else
- {
- OutputDevice.setActiveCamera(modelData.camera)
+ if (OutputDevice.activeCameraUrl != "")
+ {
+ OutputDevice.setActiveCameraUrl("")
+ }
+ else
+ {
+ OutputDevice.setActiveCameraUrl(modelData.cameraUrl)
+ }
}
}
}
diff --git a/plugins/UM3NetworkPrinting/resources/qml/ClusterControlItem.qml b/plugins/UM3NetworkPrinting/resources/qml/ClusterControlItem.qml
deleted file mode 100644
index f8ad0e763e..0000000000
--- a/plugins/UM3NetworkPrinting/resources/qml/ClusterControlItem.qml
+++ /dev/null
@@ -1,804 +0,0 @@
-import QtQuick 2.3
-import QtQuick.Dialogs 1.1
-import QtQuick.Controls 1.4
-import QtQuick.Controls.Styles 1.3
-import QtGraphicalEffects 1.0
-
-import QtQuick.Controls 2.0 as Controls2
-
-import UM 1.3 as UM
-import Cura 1.0 as Cura
-
-
-Component
-{
- Rectangle
- {
- id: base
- property var lineColor: "#DCDCDC" // TODO: Should be linked to theme.
- property var shadowRadius: 5 * screenScaleFactor
- property var cornerRadius: 4 * screenScaleFactor // TODO: Should be linked to theme.
- visible: OutputDevice != null
- anchors.fill: parent
- color: "white"
-
- UM.I18nCatalog
- {
- id: catalog
- name: "cura"
- }
-
- Label
- {
- id: printingLabel
- font: UM.Theme.getFont("large")
- anchors
- {
- margins: 2 * UM.Theme.getSize("default_margin").width
- leftMargin: 4 * UM.Theme.getSize("default_margin").width
- top: parent.top
- left: parent.left
- right: parent.right
- }
-
- text: catalog.i18nc("@label", "Printing")
- elide: Text.ElideRight
- }
-
- Label
- {
- id: managePrintersLabel
- anchors.rightMargin: 4 * UM.Theme.getSize("default_margin").width
- anchors.right: printerScrollView.right
- anchors.bottom: printingLabel.bottom
- text: catalog.i18nc("@label link to connect manager", "Manage printers")
- font: UM.Theme.getFont("default")
- color: UM.Theme.getColor("primary")
- linkColor: UM.Theme.getColor("primary")
- }
-
- MouseArea
- {
- anchors.fill: managePrintersLabel
- hoverEnabled: true
- onClicked: Cura.MachineManager.printerOutputDevices[0].openPrinterControlPanel()
- onEntered: managePrintersLabel.font.underline = true
- onExited: managePrintersLabel.font.underline = false
- }
-
- ScrollView
- {
- id: printerScrollView
- anchors
- {
- top: printingLabel.bottom
- left: parent.left
- right: parent.right
- topMargin: UM.Theme.getSize("default_margin").height
- bottom: parent.bottom
- bottomMargin: UM.Theme.getSize("default_margin").height
- }
-
- style: UM.Theme.styles.scrollview
-
- ListView
- {
- id: printer_list
- property var current_index: -1
- anchors
- {
- top: parent.top
- bottom: parent.bottom
- left: parent.left
- right: parent.right
- leftMargin: 2 * UM.Theme.getSize("default_margin").width
- rightMargin: 2 * UM.Theme.getSize("default_margin").width
- }
- spacing: UM.Theme.getSize("default_margin").height -10
- model: OutputDevice.printers
-
- delegate: Item
- {
- width: parent.width
- height: base.height + 2 * base.shadowRadius // To ensure that the shadow doesn't get cut off.
- Rectangle
- {
- width: parent.width - 2 * shadowRadius
- height: childrenRect.height + UM.Theme.getSize("default_margin").height
- anchors.horizontalCenter: parent.horizontalCenter
- anchors.verticalCenter: parent.verticalCenter
- color:
- {
- if(modelData.state == "disabled")
- {
- return UM.Theme.getColor("monitor_background_inactive")
- }
- else
- {
- return UM.Theme.getColor("monitor_background_active")
- }
- }
- id: base
- property var shadowRadius: 5 * screenScaleFactor
- property var collapsed: true
-
- layer.enabled: true
- layer.effect: DropShadow
- {
- radius: 5 * screenScaleFactor
- verticalOffset: 2
- color: "#3F000000" // 25% shadow
- }
-
- Connections
- {
- target: printer_list
- onCurrent_indexChanged: { base.collapsed = printer_list.current_index != model.index }
- }
-
- Item
- {
- id: printerInfo
- height: machineIcon.height
- anchors
- {
- top: parent.top
- left: parent.left
- right: parent.right
- margins: UM.Theme.getSize("default_margin").width
- }
-
- MouseArea
- {
- anchors.fill: parent
- onClicked:
- {
- if (base.collapsed) {
- printer_list.current_index = model.index
- }
- else
- {
- printer_list.current_index = -1
- }
- }
- }
-
- Item
- {
- id: machineIcon
- // Yeah, this is hardcoded now, but I can't think of a good way to fix this.
- // The UI is going to get another update soon, so it's probably not worth the effort...
- width: 58
- height: 58
- anchors.top: parent.top
- anchors.leftMargin: UM.Theme.getSize("default_margin").width
- anchors.left: parent.left
-
- UM.RecolorImage
- {
- anchors.centerIn: parent
- source:
- {
- switch(modelData.type)
- {
- case "Ultimaker 3":
- return "../svg/UM3-icon.svg"
- case "Ultimaker 3 Extended":
- return "../svg/UM3x-icon.svg"
- case "Ultimaker S5":
- return "../svg/UMs5-icon.svg"
- }
- }
- width: sourceSize.width
- height: sourceSize.height
-
- color:
- {
- if(modelData.state == "disabled")
- {
- return UM.Theme.getColor("monitor_text_inactive")
- }
-
- if(modelData.activePrintJob != undefined)
- {
- return UM.Theme.getColor("primary")
- }
-
- return UM.Theme.getColor("monitor_text_inactive")
- }
- }
- }
- Item
- {
- height: childrenRect.height
- anchors
- {
- right: collapseIcon.left
- rightMargin: UM.Theme.getSize("default_margin").width
- left: machineIcon.right
- leftMargin: UM.Theme.getSize("default_margin").width
-
- verticalCenter: machineIcon.verticalCenter
- }
-
- Label
- {
- id: machineNameLabel
- text: modelData.name
- width: parent.width
- elide: Text.ElideRight
- font: UM.Theme.getFont("default_bold")
- }
-
- Label
- {
- id: activeJobLabel
- text:
- {
- if (modelData.state == "disabled")
- {
- return catalog.i18nc("@label", "Not available")
- } else if (modelData.state == "unreachable")
- {
- return catalog.i18nc("@label", "Unreachable")
- }
- if (modelData.activePrintJob != null)
- {
- return modelData.activePrintJob.name
- }
- return catalog.i18nc("@label", "Available")
- }
- anchors.top: machineNameLabel.bottom
- width: parent.width
- elide: Text.ElideRight
- font: UM.Theme.getFont("default")
- color: UM.Theme.getColor("monitor_text_inactive")
- }
- }
-
- UM.RecolorImage
- {
- id: collapseIcon
- width: 15
- height: 15
- sourceSize.width: width
- sourceSize.height: height
- source: base.collapsed ? UM.Theme.getIcon("arrow_left") : UM.Theme.getIcon("arrow_bottom")
- anchors.verticalCenter: parent.verticalCenter
- anchors.right: parent.right
- anchors.rightMargin: UM.Theme.getSize("default_margin").width
- color: "black"
- }
- }
-
- Item
- {
- id: detailedInfo
- property var printJob: modelData.activePrintJob
- visible: height == childrenRect.height
- anchors.top: printerInfo.bottom
- width: parent.width
- height: !base.collapsed ? childrenRect.height : 0
- opacity: visible ? 1 : 0
- Behavior on height { NumberAnimation { duration: 100 } }
- Behavior on opacity { NumberAnimation { duration: 100 } }
- Rectangle
- {
- id: topSpacer
- color:
- {
- if(modelData.state == "disabled")
- {
- return UM.Theme.getColor("monitor_lining_inactive")
- }
- return UM.Theme.getColor("viewport_background")
- }
- // UM.Theme.getColor("viewport_background")
- height: 1
- anchors
- {
- left: parent.left
- right: parent.right
- margins: UM.Theme.getSize("default_margin").width
- top: parent.top
- topMargin: UM.Theme.getSize("default_margin").width
- }
- }
- PrinterFamilyPill
- {
- id: printerFamilyPill
- color:
- {
- if(modelData.state == "disabled")
- {
- return "transparent"
- }
- return UM.Theme.getColor("viewport_background")
- }
- anchors.top: topSpacer.bottom
- anchors.topMargin: 2 * UM.Theme.getSize("default_margin").height
- text: modelData.type
- anchors.left: parent.left
- anchors.leftMargin: UM.Theme.getSize("default_margin").width
- padding: 3
- }
- Row
- {
- id: extrudersInfo
- anchors.top: printerFamilyPill.bottom
- anchors.topMargin: 2 * UM.Theme.getSize("default_margin").height
- anchors.left: parent.left
- anchors.leftMargin: 2 * UM.Theme.getSize("default_margin").width
- anchors.right: parent.right
- anchors.rightMargin: 2 * UM.Theme.getSize("default_margin").width
- height: childrenRect.height
- spacing: UM.Theme.getSize("default_margin").width
-
- PrintCoreConfiguration
- {
- id: leftExtruderInfo
- width: Math.round(parent.width / 2)
- printCoreConfiguration: modelData.printerConfiguration.extruderConfigurations[0]
- }
-
- PrintCoreConfiguration
- {
- id: rightExtruderInfo
- width: Math.round(parent.width / 2)
- printCoreConfiguration: modelData.printerConfiguration.extruderConfigurations[1]
- }
- }
-
- Rectangle
- {
- id: jobSpacer
- color: UM.Theme.getColor("viewport_background")
- height: 2
- anchors
- {
- left: parent.left
- right: parent.right
- margins: UM.Theme.getSize("default_margin").width
- top: extrudersInfo.bottom
- topMargin: 2 * UM.Theme.getSize("default_margin").height
- }
- }
-
- Item
- {
- id: jobInfo
- property var showJobInfo: modelData.activePrintJob != null && modelData.activePrintJob.state != "queued"
-
- anchors.top: jobSpacer.bottom
- anchors.topMargin: 2 * UM.Theme.getSize("default_margin").height
- anchors.left: parent.left
- anchors.right: parent.right
- anchors.margins: UM.Theme.getSize("default_margin").width
- anchors.leftMargin: 2 * UM.Theme.getSize("default_margin").width
- height: showJobInfo ? childrenRect.height + 2 * UM.Theme.getSize("default_margin").height: 0
- visible: showJobInfo
- Label
- {
- id: printJobName
- text: modelData.activePrintJob != null ? modelData.activePrintJob.name : ""
- font: UM.Theme.getFont("default_bold")
- anchors.left: parent.left
- anchors.right: contextButton.left
- anchors.rightMargin: UM.Theme.getSize("default_margin").width
- elide: Text.ElideRight
- }
- Label
- {
- id: ownerName
- anchors.top: printJobName.bottom
- text: modelData.activePrintJob != null ? modelData.activePrintJob.owner : ""
- font: UM.Theme.getFont("default")
- opacity: 0.6
- width: parent.width
- elide: Text.ElideRight
- }
-
- function switchPopupState()
- {
- popup.visible ? popup.close() : popup.open()
- }
-
- Controls2.Button
- {
- id: contextButton
- text: "\u22EE" //Unicode; Three stacked points.
- width: 35
- height: width
- anchors
- {
- right: parent.right
- top: parent.top
- }
- hoverEnabled: true
-
- background: Rectangle
- {
- opacity: contextButton.down || contextButton.hovered ? 1 : 0
- width: contextButton.width
- height: contextButton.height
- radius: 0.5 * width
- color: UM.Theme.getColor("viewport_background")
- }
- contentItem: Label
- {
- text: contextButton.text
- color: UM.Theme.getColor("monitor_text_inactive")
- font.pixelSize: 25
- verticalAlignment: Text.AlignVCenter
- horizontalAlignment: Text.AlignHCenter
- }
-
- onClicked: parent.switchPopupState()
- }
-
- Controls2.Popup
- {
- // TODO Change once updating to Qt5.10 - The 'opened' property is in 5.10 but the behavior is now implemented with the visible property
- id: popup
- clip: true
- closePolicy: Popup.CloseOnPressOutside
- x: (parent.width - width) + 26 * screenScaleFactor
- y: contextButton.height - 5 * screenScaleFactor // Because shadow
- width: 182 * screenScaleFactor
- height: contentItem.height + 2 * padding
- visible: false
- padding: 5 * screenScaleFactor // Because shadow
-
- transformOrigin: Popup.Top
- contentItem: Item
- {
- width: popup.width
- height: childrenRect.height + 36 * screenScaleFactor
- anchors.topMargin: 10 * screenScaleFactor
- anchors.bottomMargin: 10 * screenScaleFactor
- Controls2.Button
- {
- id: pauseButton
- text: modelData.activePrintJob != null && modelData.activePrintJob.state == "paused" ? catalog.i18nc("@label", "Resume") : catalog.i18nc("@label", "Pause")
- onClicked:
- {
- if(modelData.activePrintJob.state == "paused")
- {
- modelData.activePrintJob.setState("print")
- }
- else if(modelData.activePrintJob.state == "printing")
- {
- modelData.activePrintJob.setState("pause")
- }
- popup.close()
- }
- width: parent.width
- enabled: modelData.activePrintJob != null && ["paused", "printing"].indexOf(modelData.activePrintJob.state) >= 0
- visible: enabled
- anchors.top: parent.top
- anchors.topMargin: 18 * screenScaleFactor
- height: visible ? 39 * screenScaleFactor : 0 * screenScaleFactor
- hoverEnabled: true
- background: Rectangle
- {
- opacity: pauseButton.down || pauseButton.hovered ? 1 : 0
- color: UM.Theme.getColor("viewport_background")
- }
- contentItem: Label
- {
- text: pauseButton.text
- horizontalAlignment: Text.AlignLeft
- verticalAlignment: Text.AlignVCenter
- }
- }
-
- Controls2.Button
- {
- id: abortButton
- text: catalog.i18nc("@label", "Abort")
- onClicked:
- {
- abortConfirmationDialog.visible = true;
- popup.close();
- }
- width: parent.width
- height: 39 * screenScaleFactor
- anchors.top: pauseButton.bottom
- hoverEnabled: true
- enabled: modelData.activePrintJob != null && ["paused", "printing", "pre_print"].indexOf(modelData.activePrintJob.state) >= 0
- background: Rectangle
- {
- opacity: abortButton.down || abortButton.hovered ? 1 : 0
- color: UM.Theme.getColor("viewport_background")
- }
- contentItem: Label
- {
- text: abortButton.text
- horizontalAlignment: Text.AlignLeft
- verticalAlignment: Text.AlignVCenter
- }
- }
-
- MessageDialog
- {
- id: abortConfirmationDialog
- title: catalog.i18nc("@window:title", "Abort print")
- icon: StandardIcon.Warning
- text: catalog.i18nc("@label %1 is the name of a print job.", "Are you sure you want to abort %1?").arg(modelData.activePrintJob.name)
- standardButtons: StandardButton.Yes | StandardButton.No
- Component.onCompleted: visible = false
- onYes: modelData.activePrintJob.setState("abort")
- }
- }
-
- background: Item
- {
- width: popup.width
- height: popup.height
-
- DropShadow
- {
- anchors.fill: pointedRectangle
- radius: 5
- color: "#3F000000" // 25% shadow
- source: pointedRectangle
- transparentBorder: true
- verticalOffset: 2
- }
-
- Item
- {
- id: pointedRectangle
- width: parent.width - 10 * screenScaleFactor // Because of the shadow
- height: parent.height - 10 * screenScaleFactor // Because of the shadow
- anchors.horizontalCenter: parent.horizontalCenter
- anchors.verticalCenter: parent.verticalCenter
-
- Rectangle
- {
- id: point
- height: 14 * screenScaleFactor
- width: 14 * screenScaleFactor
- color: UM.Theme.getColor("setting_control")
- transform: Rotation { angle: 45}
- anchors.right: bloop.right
- anchors.rightMargin: 24
- y: 1
- }
-
- Rectangle
- {
- id: bloop
- color: UM.Theme.getColor("setting_control")
- width: parent.width
- anchors.top: parent.top
- anchors.topMargin: 8 * screenScaleFactor // Because of the shadow + point
- anchors.bottom: parent.bottom
- anchors.bottomMargin: 8 * screenScaleFactor // Because of the shadow
- }
- }
- }
-
- exit: Transition
- {
- // This applies a default NumberAnimation to any changes a state change makes to x or y properties
- NumberAnimation { property: "visible"; duration: 75; }
- }
- enter: Transition
- {
- // This applies a default NumberAnimation to any changes a state change makes to x or y properties
- NumberAnimation { property: "visible"; duration: 75; }
- }
-
- onClosed: visible = false
- onOpened: visible = true
- }
-
- Image
- {
- id: printJobPreview
- source: modelData.activePrintJob != null ? modelData.activePrintJob.previewImageUrl : ""
- anchors.top: ownerName.bottom
- anchors.horizontalCenter: parent.horizontalCenter
- width: parent.width / 2
- height: width
- opacity:
- {
- if(modelData.activePrintJob == null)
- {
- return 1.0
- }
-
- switch(modelData.activePrintJob.state)
- {
- case "wait_cleanup":
- case "wait_user_action":
- case "paused":
- return 0.5
- default:
- return 1.0
- }
- }
-
-
- }
-
- UM.RecolorImage
- {
- id: statusImage
- anchors.centerIn: printJobPreview
- source:
- {
- if(modelData.activePrintJob == null)
- {
- return ""
- }
- switch(modelData.activePrintJob.state)
- {
- case "paused":
- return "../svg/paused-icon.svg"
- case "wait_cleanup":
- if(modelData.activePrintJob.timeElapsed < modelData.activePrintJob.timeTotal)
- {
- return "../svg/aborted-icon.svg"
- }
- return "../svg/approved-icon.svg"
- case "wait_user_action":
- return "../svg/aborted-icon.svg"
- default:
- return ""
- }
- }
- visible: source != ""
- width: 0.5 * printJobPreview.width
- height: 0.5 * printJobPreview.height
- sourceSize.width: width
- sourceSize.height: height
- color: "black"
- }
-
- CameraButton
- {
- id: showCameraButton
- iconSource: "../svg/camera-icon.svg"
- anchors
- {
- left: parent.left
- bottom: printJobPreview.bottom
- }
- }
- }
- }
-
- ProgressBar
- {
- property var progress:
- {
- if(modelData.activePrintJob == null)
- {
- return 0
- }
- var result = modelData.activePrintJob.timeElapsed / modelData.activePrintJob.timeTotal
- if(result > 1.0)
- {
- result = 1.0
- }
- return result
- }
-
- id: jobProgressBar
- width: parent.width
- value: progress
- anchors.top: detailedInfo.bottom
- anchors.topMargin: UM.Theme.getSize("default_margin").height
-
- visible: modelData.activePrintJob != null && modelData.activePrintJob != undefined
-
- style: ProgressBarStyle
- {
- property var remainingTime:
- {
- if(modelData.activePrintJob == null)
- {
- return 0
- }
- /* Sometimes total minus elapsed is less than 0. Use Math.max() to prevent remaining
- time from ever being less than 0. Negative durations cause strange behavior such
- as displaying "-1h -1m". */
- var activeJob = modelData.activePrintJob
- return Math.max(activeJob.timeTotal - activeJob.timeElapsed, 0);
- }
- property var progressText:
- {
- if(modelData.activePrintJob == null)
- {
- return ""
- }
- switch(modelData.activePrintJob.state)
- {
- case "wait_cleanup":
- if(modelData.activePrintJob.timeTotal > modelData.activePrintJob.timeElapsed)
- {
- return catalog.i18nc("@label:status", "Aborted")
- }
- return catalog.i18nc("@label:status", "Finished")
- case "pre_print":
- case "sent_to_printer":
- return catalog.i18nc("@label:status", "Preparing")
- case "aborted":
- return catalog.i18nc("@label:status", "Aborted")
- case "wait_user_action":
- return catalog.i18nc("@label:status", "Aborted")
- case "pausing":
- return catalog.i18nc("@label:status", "Pausing")
- case "paused":
- return OutputDevice.formatDuration( remainingTime )
- case "resuming":
- return catalog.i18nc("@label:status", "Resuming")
- case "queued":
- return catalog.i18nc("@label:status", "Action required")
- default:
- return OutputDevice.formatDuration( remainingTime )
- }
- }
-
- background: Rectangle
- {
- implicitWidth: 100
- implicitHeight: visible ? 24 : 0
- color: UM.Theme.getColor("viewport_background")
- }
-
- progress: Rectangle
- {
- color:
- {
- var state = modelData.activePrintJob.state
- var inactiveStates = [
- "pausing",
- "paused",
- "resuming",
- "wait_cleanup"
- ]
- if(inactiveStates.indexOf(state) > -1 && remainingTime > 0)
- {
- return UM.Theme.getColor("monitor_text_inactive")
- }
- else
- {
- return UM.Theme.getColor("primary")
- }
- }
- id: progressItem
- function getTextOffset()
- {
- if(progressItem.width + progressLabel.width + 16 < control.width)
- {
- return progressItem.width + UM.Theme.getSize("default_margin").width
- }
- else
- {
- return progressItem.width - progressLabel.width - UM.Theme.getSize("default_margin").width
- }
- }
-
- Label
- {
- id: progressLabel
- anchors.left: parent.left
- anchors.leftMargin: getTextOffset()
- text: progressText
- anchors.verticalCenter: parent.verticalCenter
- color: progressItem.width + progressLabel.width < control.width ? "black" : "white"
- width: contentWidth
- font: UM.Theme.getFont("default")
- }
- }
- }
- }
- }
- }
- }
- }
- }
-}
diff --git a/plugins/UM3NetworkPrinting/resources/qml/ClusterMonitorItem.qml b/plugins/UM3NetworkPrinting/resources/qml/ClusterMonitorItem.qml
deleted file mode 100644
index f6cf6607c7..0000000000
--- a/plugins/UM3NetworkPrinting/resources/qml/ClusterMonitorItem.qml
+++ /dev/null
@@ -1,108 +0,0 @@
-import QtQuick 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
-
-Component
-{
- Rectangle
- {
- id: monitorFrame
- width: maximumWidth
- height: maximumHeight
- color: UM.Theme.getColor("viewport_background")
- property var emphasisColor: UM.Theme.getColor("setting_control_border_highlight")
- property var lineColor: "#DCDCDC" // TODO: Should be linked to theme.
- property var cornerRadius: 4 * screenScaleFactor // TODO: Should be linked to theme.
-
- UM.I18nCatalog
- {
- id: catalog
- name: "cura"
- }
-
- Label
- {
- id: manageQueueLabel
- anchors.rightMargin: 3 * UM.Theme.getSize("default_margin").width
- anchors.right: queuedPrintJobs.right
- anchors.bottom: queuedLabel.bottom
- text: catalog.i18nc("@label link to connect manager", "Manage queue")
- font: UM.Theme.getFont("default")
- color: UM.Theme.getColor("primary")
- linkColor: UM.Theme.getColor("primary")
- }
-
- MouseArea
- {
- anchors.fill: manageQueueLabel
- hoverEnabled: true
- onClicked: Cura.MachineManager.printerOutputDevices[0].openPrintJobControlPanel()
- onEntered: manageQueueLabel.font.underline = true
- onExited: manageQueueLabel.font.underline = false
- }
-
- Label
- {
- id: queuedLabel
- anchors.left: queuedPrintJobs.left
- anchors.top: parent.top
- anchors.topMargin: 2 * UM.Theme.getSize("default_margin").height
- anchors.leftMargin: 3 * UM.Theme.getSize("default_margin").width + 5
- text: catalog.i18nc("@label", "Queued")
- font: UM.Theme.getFont("large")
- color: UM.Theme.getColor("text")
- }
-
- ScrollView
- {
- id: queuedPrintJobs
-
- anchors
- {
- top: queuedLabel.bottom
- topMargin: UM.Theme.getSize("default_margin").height
- horizontalCenter: parent.horizontalCenter
- bottomMargin: 0
- bottom: parent.bottom
- }
- style: UM.Theme.styles.scrollview
- width: Math.min(800 * screenScaleFactor, maximumWidth)
- ListView
- {
- anchors.fill: parent
- //anchors.margins: UM.Theme.getSize("default_margin").height
- spacing: UM.Theme.getSize("default_margin").height - 10 // 2x the shadow radius
-
- model: OutputDevice.queuedPrintJobs
-
- delegate: PrintJobInfoBlock
- {
- printJob: modelData
- anchors.left: parent.left
- anchors.right: parent.right
- anchors.rightMargin: UM.Theme.getSize("default_margin").height
- anchors.leftMargin: UM.Theme.getSize("default_margin").height
- height: 175 * screenScaleFactor
- }
- }
- }
-
- PrinterVideoStream
- {
- visible: OutputDevice.activeCamera != null
- anchors.fill: parent
- camera: OutputDevice.activeCamera
- }
-
- onVisibleChanged:
- {
- if (monitorFrame != null && !monitorFrame.visible)
- {
- OutputDevice.setActiveCamera(null)
- }
- }
- }
-}
diff --git a/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml b/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml
index b5b80a3010..1a843ba200 100644
--- a/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml
+++ b/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml
@@ -1,5 +1,8 @@
+// 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
@@ -11,9 +14,13 @@ 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)
@@ -25,7 +32,7 @@ Cura.MachineAction
// Check if there is another instance with the same key
if (!manager.existsKey(printerKey))
{
- manager.setKey(printerKey)
+ manager.associateActiveMachineWithPrinterDevice(base.selectedDevice)
manager.setGroupName(printerName) // TODO To change when the groups have a name
completed()
}
@@ -61,6 +68,7 @@ Cura.MachineAction
width: parent.width
text: catalog.i18nc("@title:window", "Connect to Networked Printer")
wrapMode: Text.WordWrap
+ renderType: Text.NativeRendering
font.pointSize: 18
}
@@ -69,7 +77,8 @@ Cura.MachineAction
id: pageDescription
width: parent.width
wrapMode: Text.WordWrap
- 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:")
+ 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\n" + catalog.i18nc("@label", "Select your printer from the list below:")
}
Row
@@ -179,6 +188,7 @@ Cura.MachineAction
text: listview.model[index].name
color: parent.ListView.isCurrentItem ? palette.highlightedText : palette.text
elide: Text.ElideRight
+ renderType: Text.NativeRendering
}
MouseArea
@@ -201,6 +211,7 @@ Cura.MachineAction
anchors.left: parent.left
anchors.right: parent.right
wrapMode: Text.WordWrap
+ renderType: Text.NativeRendering
text: catalog.i18nc("@label", "If your printer is not listed, read the network printing troubleshooting guide").arg("https://ultimaker.com/en/troubleshooting");
onLinkActivated: Qt.openUrlExternally(link)
}
@@ -216,8 +227,9 @@ Cura.MachineAction
width: parent.width
wrapMode: Text.WordWrap
text: base.selectedDevice ? base.selectedDevice.name : ""
- font: UM.Theme.getFont("large")
+ font: UM.Theme.getFont("large_bold")
elide: Text.ElideRight
+ renderType: Text.NativeRendering
}
Grid
{
@@ -228,61 +240,51 @@ Cura.MachineAction
{
width: Math.round(parent.width * 0.5)
wrapMode: Text.WordWrap
+ renderType: Text.NativeRendering
text: catalog.i18nc("@label", "Type")
}
Label
{
width: Math.round(parent.width * 0.5)
wrapMode: Text.WordWrap
+ 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) {
+ // It would be great to use a more readable machine type here,
+ // but the new discoveredPrintersModel is not used yet in the UM networking actions.
+ // TODO: remove actions or replace 'connect via network' button with new flow?
+ return base.selectedDevice.printerType
}
+ return ""
}
}
Label
{
width: Math.round(parent.width * 0.5)
wrapMode: Text.WordWrap
+ renderType: Text.NativeRendering
text: catalog.i18nc("@label", "Firmware version")
}
Label
{
width: Math.round(parent.width * 0.5)
wrapMode: Text.WordWrap
+ renderType: Text.NativeRendering
text: base.selectedDevice ? base.selectedDevice.firmwareVersion : ""
}
Label
{
width: Math.round(parent.width * 0.5)
wrapMode: Text.WordWrap
+ renderType: Text.NativeRendering
text: catalog.i18nc("@label", "Address")
}
Label
{
width: Math.round(parent.width * 0.5)
wrapMode: Text.WordWrap
+ renderType: Text.NativeRendering
text: base.selectedDevice ? base.selectedDevice.ipAddress : ""
}
}
@@ -291,6 +293,7 @@ Cura.MachineAction
{
width: parent.width
wrapMode: Text.WordWrap
+ renderType: Text.NativeRendering
text:{
// The property cluster size does not exist for older UM3 devices.
if(!base.selectedDevice || base.selectedDevice.clusterSize == null || base.selectedDevice.clusterSize == 1)
@@ -312,6 +315,7 @@ Cura.MachineAction
{
width: parent.width
wrapMode: Text.WordWrap
+ renderType: Text.NativeRendering
visible: base.selectedDevice != null && !base.completeProperties
text: catalog.i18nc("@label", "The printer at this address has not yet responded." )
}
@@ -326,6 +330,17 @@ Cura.MachineAction
}
}
+ MessageDialog
+ {
+ id: invalidIPAddressMessageDialog
+ x: (parent.x + (parent.width) / 2) | 0
+ y: (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
@@ -355,9 +370,10 @@ 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 or hostname of your printer on the network.")
width: parent.width
wrapMode: Text.WordWrap
+ renderType: Text.NativeRendering
}
TextField
@@ -387,6 +403,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
new file mode 100644
index 0000000000..fae8280488
--- /dev/null
+++ b/plugins/UM3NetworkPrinting/resources/qml/ExpandableCard.qml
@@ -0,0 +1,90 @@
+// Copyright (c) 2018 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
+import Cura 1.0 as Cura
+
+/**
+ * The expandable component has 3 major sub components:
+ * - The headerItem Always visible and should hold some info about what happens if the component is expanded
+ * - The popupItem The content that needs to be shown if the component is expanded.
+ */
+Item
+{
+ id: base
+
+ property bool expanded: false
+ property bool enabled: true
+ property var borderWidth: 1
+ property color borderColor: UM.Theme.getColor("monitor_card_border")
+ property color headerBackgroundColor: UM.Theme.getColor("monitor_icon_accent")
+ property color headerHoverColor: UM.Theme.getColor("monitor_card_hover")
+ property color drawerBackgroundColor: UM.Theme.getColor("monitor_icon_accent")
+ property alias headerItem: header.children
+ property alias drawerItem: drawer.children
+
+ width: parent.width
+ height: childrenRect.height
+
+ Rectangle
+ {
+ id: header
+ border
+ {
+ color: borderColor
+ width: borderWidth
+ }
+ color: base.enabled && headerMouseArea.containsMouse ? headerHoverColor : headerBackgroundColor
+ height: childrenRect.height
+ width: parent.width
+ radius: 2 * screenScaleFactor // TODO: Theme!
+ Behavior on color
+ {
+ ColorAnimation
+ {
+ duration: 100
+ }
+ }
+ }
+
+ MouseArea
+ {
+ id: headerMouseArea
+ anchors.fill: header
+ onClicked:
+ {
+ if (!base.enabled) return
+ base.expanded = !base.expanded
+ }
+ hoverEnabled: base.enabled
+ }
+
+ Rectangle
+ {
+ id: drawer
+ anchors
+ {
+ top: header.bottom
+ topMargin: -1
+ }
+ border
+ {
+ color: borderColor
+ width: borderWidth
+ }
+ clip: true
+ color: headerBackgroundColor
+ height: base.expanded ? childrenRect.height : 0
+ width: parent.width
+ radius: 2 * screenScaleFactor // TODO: Theme!
+ Behavior on height
+ {
+ NumberAnimation
+ {
+ duration: 100
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/plugins/UM3NetworkPrinting/resources/qml/GenericPopUp.qml b/plugins/UM3NetworkPrinting/resources/qml/GenericPopUp.qml
new file mode 100644
index 0000000000..74d9377f3e
--- /dev/null
+++ b/plugins/UM3NetworkPrinting/resources/qml/GenericPopUp.qml
@@ -0,0 +1,227 @@
+// Copyright (c) 2018 Ultimaker B.V.
+// Cura is released under the terms of the LGPLv3 or higher.
+
+import QtQuick 2.2
+import QtQuick.Controls 2.0
+import QtQuick.Controls.Styles 1.4
+import QtQuick.Dialogs 1.1
+import QtGraphicalEffects 1.0
+import UM 1.3 as UM
+
+/**
+ * This is a generic pop-up element which can be supplied with a target and a content item. The
+ * content item will appear to the left, right, above, or below the target depending on the value of
+ * the direction property
+ */
+Popup
+{
+ id: base
+
+ /**
+ * The target item is what the pop-up is "tied" to, usually a button
+ */
+ property var target
+
+ /**
+ * Which direction should the pop-up "point"?
+ * Possible values include:
+ * - "up"
+ * - "down"
+ * - "left"
+ * - "right"
+ */
+ property string direction: "down"
+
+ /**
+ * We save the default direction so that if a pop-up was flipped but later has space (i.e. it
+ * moved), we can unflip it back to the default direction.
+ */
+ property string originalDirection: ""
+
+ /**
+ * Should the popup close when you click outside it? For example, this is
+ * disabled by the InfoBlurb component since it's opened and closed using mouse
+ * hovers, not clicks.
+ */
+ property bool closeOnClick: true
+
+ /**
+ * Use white for context menus, dark grey for info blurbs!
+ */
+ property var color: "#ffffff" // TODO: Theme!
+
+ Component.onCompleted:
+ {
+ recalculatePosition()
+
+ // Set the direction here so it's only set once and never mutated
+ originalDirection = (' ' + direction).slice(1)
+ }
+
+ background: Item
+ {
+ anchors.fill: parent
+
+ DropShadow
+ {
+ anchors.fill: pointedRectangle
+ color: UM.Theme.getColor("monitor_shadow")
+ radius: UM.Theme.getSize("monitor_shadow_radius").width
+ source: pointedRectangle
+ transparentBorder: true
+ verticalOffset: 2 * screenScaleFactor
+ }
+
+ Item
+ {
+ id: pointedRectangle
+ anchors
+ {
+ horizontalCenter: parent.horizontalCenter
+ verticalCenter: parent.verticalCenter
+ }
+ height: parent.height - 10 * screenScaleFactor // Because of the shadow
+ width: parent.width - 10 * screenScaleFactor // Because of the shadow
+
+ Rectangle
+ {
+ id: point
+ anchors
+ {
+ horizontalCenter:
+ {
+ switch(direction)
+ {
+ case "left":
+ return bloop.left
+ case "right":
+ return bloop.right
+ default:
+ return bloop.horizontalCenter
+ }
+ }
+ verticalCenter:
+ {
+ switch(direction)
+ {
+ case "up":
+ return bloop.top
+ case "down":
+ return bloop.bottom
+ default:
+ return bloop.verticalCenter
+ }
+ }
+ }
+ color: base.color
+ height: 12 * screenScaleFactor
+ transform: Rotation
+ {
+ angle: 45
+ origin.x: point.width / 2
+ origin.y: point.height / 2
+ }
+ width: height
+ }
+
+ Rectangle
+ {
+ id: bloop
+ anchors
+ {
+ fill: parent
+ leftMargin: direction == "left" ? 8 * screenScaleFactor : 0
+ rightMargin: direction == "right" ? 8 * screenScaleFactor : 0
+ topMargin: direction == "up" ? 8 * screenScaleFactor : 0
+ bottomMargin: direction == "down" ? 8 * screenScaleFactor : 0
+ }
+ color: base.color
+ width: parent.width
+ }
+ }
+ }
+
+ visible: false
+ onClosed: visible = false
+ onOpened:
+ {
+ // Flip orientation if necessary
+ recalculateOrientation()
+
+ // Fix position if necessary
+ recalculatePosition()
+
+ // Show the pop up
+ visible = true
+ }
+ closePolicy: closeOnClick ? Popup.CloseOnPressOutside : Popup.NoAutoClose
+
+ clip: true
+
+ padding: UM.Theme.getSize("monitor_shadow_radius").width
+ topPadding: direction == "up" ? padding + 8 * screenScaleFactor : padding
+ bottomPadding: direction == "down" ? padding + 8 * screenScaleFactor : padding
+ leftPadding: direction == "left" ? padding + 8 * screenScaleFactor : padding
+ rightPadding: direction == "right" ? padding + 8 * screenScaleFactor : padding
+
+ function recalculatePosition() {
+
+ // Stupid pop-up logic causes the pop-up to resize, so let's compute what it SHOULD be
+ const realWidth = contentItem.implicitWidth + leftPadding + rightPadding
+ const realHeight = contentItem.implicitHeight + topPadding + bottomPadding
+
+ var centered = {
+ x: target.x + target.width / 2 - realWidth / 2,
+ y: target.y + target.height / 2 - realHeight / 2
+ }
+
+ switch(direction)
+ {
+ case "left":
+ x = target.x + target.width
+ y = centered.y
+ break
+ case "right":
+ x = target.x - realWidth
+ y = centered.y
+ break
+ case "up":
+ x = centered.x
+ y = target.y + target.height
+ break
+ case "down":
+ x = centered.x
+ y = target.y - realHeight
+ break
+ }
+ }
+
+ function recalculateOrientation() {
+ var availableSpace
+ var targetPosition = target.mapToItem(monitorFrame, 0, 0)
+
+ // Stupid pop-up logic causes the pop-up to resize, so let's compute what it SHOULD be
+ const realWidth = contentItem.implicitWidth + leftPadding + rightPadding
+ const realHeight = contentItem.implicitHeight + topPadding + bottomPadding
+
+ switch(originalDirection)
+ {
+ case "up":
+ availableSpace = monitorFrame.height - (targetPosition.y + target.height)
+ direction = availableSpace < realHeight ? "down" : originalDirection
+ break
+ case "down":
+ availableSpace = targetPosition.y
+ direction = availableSpace < realHeight ? "up" : originalDirection
+ break
+ case "right":
+ availableSpace = targetPosition.x
+ direction = availableSpace < realWidth ? "left" : originalDirection
+ break
+ case "left":
+ availableSpace = monitorFrame.width - (targetPosition.x + target.width)
+ direction = availableSpace < realWidth ? "right" : originalDirection
+ break
+ }
+ }
+}
diff --git a/plugins/UM3NetworkPrinting/resources/qml/MonitorBuildplateConfiguration.qml b/plugins/UM3NetworkPrinting/resources/qml/MonitorBuildplateConfiguration.qml
new file mode 100644
index 0000000000..619658a7eb
--- /dev/null
+++ b/plugins/UM3NetworkPrinting/resources/qml/MonitorBuildplateConfiguration.qml
@@ -0,0 +1,75 @@
+// Copyright (c) 2018 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
+
+/**
+ * This component comprises a buildplate icon and the buildplate name. It is
+ * used by the MonitorPrinterConfiguration component along with two instances
+ * of MonitorExtruderConfiguration.
+ *
+ * NOTE: For most labels, a fixed height with vertical alignment is used to make
+ * layouts more deterministic (like the fixed-size textboxes used in original
+ * mock-ups). This is also a stand-in for CSS's 'line-height' property. Denoted
+ * with '// FIXED-LINE-HEIGHT:'.
+ */
+Item
+{
+ // The buildplate name
+ property var buildplate: null
+
+ // Height is one 18px label/icon
+ height: 18 * screenScaleFactor // TODO: Theme!
+ width: childrenRect.width
+
+ Row
+ {
+ height: parent.height
+ spacing: UM.Theme.getSize("print_setup_slider_handle").width // TODO: Theme! (Should be same as extruder spacing)
+
+ // This wrapper ensures that the buildplate icon is located centered
+ // below an extruder icon.
+ Item
+ {
+ height: parent.height
+ width: 32 * screenScaleFactor // Ensure the icon is centered under the extruder icon (same width)
+
+ Rectangle
+ {
+ anchors.centerIn: parent
+ height: parent.height
+ width: height
+ color: buildplateIcon.visible > 0 ? "transparent" : UM.Theme.getColor("monitor_skeleton_loading")
+ radius: Math.floor(height / 2)
+ }
+
+ UM.RecolorImage
+ {
+ id: buildplateIcon
+ anchors.centerIn: parent
+ color: UM.Theme.getColor("monitor_icon_primary")
+ height: parent.height
+ source: "../svg/icons/buildplate.svg"
+ width: height
+ visible: buildplate
+ }
+ }
+
+ Label
+ {
+ id: buildplateLabel
+ color: UM.Theme.getColor("monitor_text_primary")
+ elide: Text.ElideRight
+ font: UM.Theme.getFont("default") // 12pt, regular
+ text: buildplate ? buildplate : ""
+ visible: text !== ""
+
+ // 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
new file mode 100644
index 0000000000..0d7a177dd3
--- /dev/null
+++ b/plugins/UM3NetworkPrinting/resources/qml/MonitorCarousel.qml
@@ -0,0 +1,258 @@
+// Copyright (c) 2018 Ultimaker B.V.
+// Cura is released under the terms of the LGPLv3 or higher.
+
+import QtQuick 2.3
+import QtQuick.Controls 2.0
+import QtGraphicalEffects 1.0
+import UM 1.3 as UM
+
+Item
+{
+ id: base
+
+ property var currentIndex: 0
+ property var tileWidth: 834 * screenScaleFactor // TODO: Theme!
+ property var tileHeight: 216 * screenScaleFactor // TODO: Theme!
+ property var tileSpacing: 60 * screenScaleFactor // TODO: Theme!
+
+ // Array/model of printers to populate the carousel with
+ property var printers: []
+
+ // Maximum distance the carousel can be shifted
+ property var maxOffset: (printers.length - 1) * (tileWidth + tileSpacing)
+
+ height: centerSection.height
+ width: maximumWidth
+
+ // Enable keyboard navigation
+ Keys.onLeftPressed: navigateTo(currentIndex - 1)
+ Keys.onRightPressed: navigateTo(currentIndex + 1)
+
+ Item
+ {
+ id: leftHint
+ anchors
+ {
+ right: leftButton.left
+ rightMargin: 12 * screenScaleFactor // TODO: Theme!
+ left: parent.left
+ }
+ height: parent.height
+ z: 10
+ LinearGradient
+ {
+ anchors.fill: parent
+ start: Qt.point(0, 0)
+ end: Qt.point(leftHint.width, 0)
+ gradient: Gradient
+ {
+ GradientStop
+ {
+ position: 0.0
+ color: UM.Theme.getColor("monitor_stage_background")
+ }
+ GradientStop
+ {
+ position: 1.0
+ color: UM.Theme.getColor("monitor_stage_background_fade")
+ }
+ }
+ }
+ MouseArea
+ {
+ anchors.fill: parent
+ onClicked: navigateTo(currentIndex - 1)
+ }
+ }
+
+ Button
+ {
+ id: leftButton
+ anchors
+ {
+ verticalCenter: parent.verticalCenter
+ right: centerSection.left
+ rightMargin: 12 * screenScaleFactor // TODO: Theme!
+ }
+ width: 36 * screenScaleFactor // TODO: Theme!
+ height: 72 * screenScaleFactor // TODO: Theme!
+ visible: currentIndex > 0
+ hoverEnabled: true
+ z: 10
+ onClicked: navigateTo(currentIndex - 1)
+ background: Rectangle
+ {
+ color: leftButton.hovered ? UM.Theme.getColor("monitor_card_hover") : UM.Theme.getColor("monitor_card_background")
+ border.width: 1 * screenScaleFactor // TODO: Theme!
+ border.color: UM.Theme.getColor("monitor_card_border")
+ radius: 2 * screenScaleFactor // TODO: Theme!
+ }
+ contentItem: Item
+ {
+ anchors.fill: parent
+ UM.RecolorImage
+ {
+ anchors.centerIn: parent
+ width: 18 // TODO: Theme!
+ height: width // TODO: Theme!
+ sourceSize.width: width // TODO: Theme!
+ sourceSize.height: width // TODO: Theme!
+ color: UM.Theme.getColor("monitor_text_primary")
+ source: UM.Theme.getIcon("arrow_left")
+ }
+ }
+ }
+
+ Item
+ {
+ id: centerSection
+ anchors
+ {
+ verticalCenter: parent.verticalCenter
+ horizontalCenter: parent.horizontalCenter
+ }
+ width: tileWidth
+ height: tiles.height
+ z: 1
+
+ Row
+ {
+ id: tiles
+ height: childrenRect.height
+ width: 5 * tileWidth + 4 * tileSpacing // TODO: Theme!
+ x: 0
+ z: 0
+ Behavior on x
+ {
+ NumberAnimation
+ {
+ duration: 200
+ easing.type: Easing.InOutCubic
+ }
+ }
+ spacing: 60 * screenScaleFactor // TODO: Theme!
+
+ Repeater
+ {
+ model: printers
+ MonitorPrinterCard
+ {
+ printer: modelData
+ enabled: model.index == currentIndex
+ }
+ }
+ }
+ }
+
+ Button
+ {
+ id: rightButton
+ anchors
+ {
+ verticalCenter: parent.verticalCenter
+ left: centerSection.right
+ leftMargin: 12 * screenScaleFactor // TODO: Theme!
+ }
+ width: 36 * screenScaleFactor // TODO: Theme!
+ height: 72 * screenScaleFactor // TODO: Theme!
+ z: 10
+ visible: currentIndex < printers.length - 1
+ onClicked: navigateTo(currentIndex + 1)
+ hoverEnabled: true
+ background: Rectangle
+ {
+ color: rightButton.hovered ? UM.Theme.getColor("monitor_card_hover") : UM.Theme.getColor("monitor_card_background")
+ border.width: 1 * screenScaleFactor // TODO: Theme!
+ border.color: UM.Theme.getColor("monitor_card_border")
+ radius: 2 * screenScaleFactor // TODO: Theme!
+ }
+ contentItem: Item
+ {
+ anchors.fill: parent
+ UM.RecolorImage
+ {
+ anchors.centerIn: parent
+ width: 18 // TODO: Theme!
+ height: width // TODO: Theme!
+ sourceSize.width: width // TODO: Theme!
+ sourceSize.height: width // TODO: Theme!
+ color: UM.Theme.getColor("monitor_text_primary")
+ source: UM.Theme.getIcon("arrow_right")
+ }
+ }
+ }
+
+ Item
+ {
+ id: rightHint
+ anchors
+ {
+ left: rightButton.right
+ leftMargin: 12 * screenScaleFactor // TODO: Theme!
+ right: parent.right
+ }
+ height: centerSection.height
+ z: 10
+
+ LinearGradient
+ {
+ anchors.fill: parent
+ start: Qt.point(0, 0)
+ end: Qt.point(rightHint.width, 0)
+ gradient: Gradient
+ {
+ GradientStop
+ {
+ position: 0.0
+ color: UM.Theme.getColor("monitor_stage_background_fade")
+ }
+ GradientStop
+ {
+ position: 1.0
+ color: UM.Theme.getColor("monitor_stage_background")
+ }
+ }
+ }
+ MouseArea
+ {
+ anchors.fill: parent
+ onClicked: navigateTo(currentIndex + 1)
+ }
+ }
+
+ Row
+ {
+ id: navigationDots
+ anchors
+ {
+ horizontalCenter: centerSection.horizontalCenter
+ top: centerSection.bottom
+ topMargin: 36 * screenScaleFactor // TODO: Theme!
+ }
+ spacing: 8 * screenScaleFactor // TODO: Theme!
+ visible: printers.length > 1
+ Repeater
+ {
+ model: printers
+ Button
+ {
+ background: Rectangle
+ {
+ color: model.index == currentIndex ? UM.Theme.getColor("monitor_carousel_dot_current") : UM.Theme.getColor("monitor_carousel_dot")
+ radius: Math.floor(width / 2)
+ width: 12 * screenScaleFactor // TODO: Theme!
+ height: width // TODO: Theme!
+ }
+ onClicked: navigateTo(model.index)
+ }
+ }
+ }
+
+ function navigateTo( i ) {
+ if (i >= 0 && i < printers.length)
+ {
+ tiles.x = -1 * i * (tileWidth + tileSpacing)
+ currentIndex = i
+ }
+ }
+}
\ No newline at end of file
diff --git a/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml b/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml
new file mode 100644
index 0000000000..f0afb1fcaa
--- /dev/null
+++ b/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml
@@ -0,0 +1,163 @@
+// Copyright (c) 2018 Ultimaker B.V.
+// Cura is released under the terms of the LGPLv3 or higher.
+
+import QtQuick 2.3
+import QtQuick.Controls 1.4
+import QtQuick.Layouts 1.3
+import QtQuick.Dialogs 1.2
+import UM 1.3 as UM
+
+UM.Dialog
+{
+ id: overrideConfirmationDialog
+
+ property var printer: null
+
+ minimumWidth: screenScaleFactor * 640;
+ minimumHeight: screenScaleFactor * 320;
+ width: minimumWidth
+ height: minimumHeight
+ title: catalog.i18nc("@title:window", "Configuration Changes")
+ rightButtons:
+ [
+ Button
+ {
+ id: overrideButton
+ anchors.margins: UM.Theme.getSize("default_margin").width
+ text: catalog.i18nc("@action:button", "Override")
+ onClicked:
+ {
+ 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
+ {
+ id: cancelButton
+ anchors.margins: UM.Theme.getSize("default_margin").width
+ text: catalog.i18nc("@action:button", "Cancel")
+ onClicked:
+ {
+ overrideConfirmationDialog.reject()
+ }
+ }
+ ]
+
+ Label
+ {
+ anchors
+ {
+ fill: parent
+ margins: 36 * screenScaleFactor // TODO: Theme!
+ bottomMargin: 56 * screenScaleFactor // TODO: Theme!
+ }
+ wrapMode: Text.WordWrap
+ renderType: Text.NativeRendering
+ text:
+ {
+ if (!printer || !printer.activePrintJob)
+ {
+ return ""
+ }
+ var topLine
+ if (materialsAreKnown(printer.activePrintJob))
+ {
+ topLine = catalog.i18ncp("@label", "The assigned printer, %1, requires the following configuration change:", "The assigned printer, %1, requires the following configuration changes:", printer.activePrintJob.configurationChanges.length).arg(printer.name)
+ }
+ else
+ {
+ topLine = catalog.i18nc("@label", "The printer %1 is assigned, but the job contains an unknown material configuration.").arg(printer.name)
+ }
+ var result = "
" + topLine +"
\n\n"
+ for (var i = 0; i < printer.activePrintJob.configurationChanges.length; i++)
+ {
+ var change = printer.activePrintJob.configurationChanges[i]
+ var text
+ switch (change.typeOfChange)
+ {
+ case "material_change":
+ text = catalog.i18nc("@label", "Change material %1 from %2 to %3.").arg(change.index + 1).arg(change.originName).arg(change.targetName)
+ break
+ case "material_insert":
+ text = catalog.i18nc("@label", "Load %3 as material %1 (This cannot be overridden).").arg(change.index + 1).arg(change.targetName)
+ break
+ case "print_core_change":
+ text = catalog.i18nc("@label", "Change print core %1 from %2 to %3.").arg(change.index + 1).arg(change.originName).arg(change.targetName)
+ break
+ case "buildplate_change":
+ text = catalog.i18nc("@label", "Change build plate to %1 (This cannot be overridden).").arg(formatBuildPlateType(change.target_name))
+ break
+ default:
+ text = "unknown"
+ }
+ result += "
" + text + "
\n\n"
+ }
+ var bottomLine = catalog.i18nc("@label", "Override will use the specified settings with the existing printer configuration. This may result in a failed print.")
+ result += "
" + bottomLine + "
\n\n"
+ return result
+ }
+ }
+ // Utils
+ function formatPrintJobName(name)
+ {
+ var extensions = [ ".gcode.gz", ".gz", ".gcode", ".ufp" ]
+ for (var i = 0; i < extensions.length; i++)
+ {
+ var extension = extensions[i]
+ if (name.slice(-extension.length) === extension)
+ {
+ name = name.substring(0, name.length - extension.length)
+ }
+ }
+ return name;
+ }
+ function materialsAreKnown(job)
+ {
+ var conf0 = job.configuration[0]
+ if (conf0 && !conf0.material.material)
+ {
+ return false
+ }
+ var conf1 = job.configuration[1]
+ if (conf1 && !conf1.material.material)
+ {
+ return false
+ }
+ return true
+ }
+ function formatBuildPlateType(buildPlateType)
+ {
+ var translationText = ""
+ switch (buildPlateType) {
+ case "glass":
+ translationText = catalog.i18nc("@label", "Glass")
+ break
+ case "aluminum":
+ translationText = catalog.i18nc("@label", "Aluminum")
+ break
+ default:
+ translationText = null
+ }
+ return translationText
+ }
+}
diff --git a/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml b/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml
new file mode 100644
index 0000000000..fbae66117e
--- /dev/null
+++ b/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml
@@ -0,0 +1,182 @@
+// Copyright (c) 2018 Ultimaker B.V.
+// Cura is released under the terms of the LGPLv3 or higher.
+
+import QtQuick 2.3
+import QtQuick.Controls 2.0
+import QtQuick.Dialogs 1.1
+import UM 1.3 as UM
+
+/**
+ * A MonitorInfoBlurb is an extension of the GenericPopUp used to show static information (vs. interactive context
+ * menus). It accepts some text (text), an item to link to to (target), and a specification of which side of the target
+ * to appear on (direction). It also sets the GenericPopUp's color to black, to differentiate itself from a menu.
+ */
+Item
+{
+ property alias target: popUp.target
+
+ property var printJob: null
+
+ GenericPopUp
+ {
+ id: popUp
+
+ // Which way should the pop-up point? Default is up, but will flip when required
+ direction: "up"
+
+ // Use dark grey for info blurbs and white for context menus
+ color: UM.Theme.getColor("monitor_context_menu")
+
+ contentItem: Item
+ {
+ id: contentWrapper
+ implicitWidth: childrenRect.width
+ implicitHeight: menuItems.height + UM.Theme.getSize("default_margin").height
+
+ Column
+ {
+ id: menuItems
+ width: 144 * screenScaleFactor
+
+ anchors
+ {
+ top: parent.top
+ topMargin: Math.floor(UM.Theme.getSize("default_margin").height / 2)
+ }
+
+ spacing: Math.floor(UM.Theme.getSize("default_margin").height / 2)
+
+ PrintJobContextMenuItem {
+ onClicked: {
+ sendToTopConfirmationDialog.visible = true;
+ popUp.close();
+ }
+ text: catalog.i18nc("@label", "Move to top");
+ visible: {
+ if (printJob && (printJob.state == "queued" || printJob.state == "error") && !isAssigned(printJob)) {
+ if (OutputDevice && OutputDevice.queuedPrintJobs[0]) {
+ return OutputDevice.queuedPrintJobs[0].key != printJob.key;
+ }
+ }
+ return false;
+ }
+ }
+
+ PrintJobContextMenuItem {
+ onClicked: {
+ deleteConfirmationDialog.visible = true;
+ popUp.close();
+ }
+ text: catalog.i18nc("@label", "Delete");
+ visible: {
+ if (!printJob) {
+ return false;
+ }
+ var states = ["queued", "error", "sent_to_printer"];
+ return states.indexOf(printJob.state) !== -1;
+ }
+ }
+
+ PrintJobContextMenuItem {
+ enabled: visible && !(printJob.state == "pausing" || printJob.state == "resuming");
+ onClicked: {
+ if (printJob.state == "paused") {
+ printJob.setState("resume");
+ popUp.close();
+ return;
+ }
+ if (printJob.state == "printing") {
+ printJob.setState("pause");
+ popUp.close();
+ return;
+ }
+ }
+ text: {
+ if (!printJob) {
+ return "";
+ }
+ switch(printJob.state) {
+ case "paused":
+ return catalog.i18nc("@label", "Resume");
+ case "pausing":
+ return catalog.i18nc("@label", "Pausing...");
+ case "resuming":
+ return catalog.i18nc("@label", "Resuming...");
+ default:
+ catalog.i18nc("@label", "Pause");
+ }
+ }
+ visible: {
+ if (!printJob) {
+ return false;
+ }
+ var states = ["printing", "pausing", "paused", "resuming"];
+ return states.indexOf(printJob.state) !== -1;
+ }
+ }
+
+ PrintJobContextMenuItem {
+ enabled: visible && printJob.state !== "aborting";
+ onClicked: {
+ abortConfirmationDialog.visible = true;
+ popUp.close();
+ }
+ text: printJob && printJob.state == "aborting" ? catalog.i18nc("@label", "Aborting...") : catalog.i18nc("@label", "Abort");
+ visible: {
+ if (!printJob) {
+ return false;
+ }
+ var states = ["pre_print", "printing", "pausing", "paused", "resuming"];
+ return states.indexOf(printJob.state) !== -1;
+ }
+ }
+ }
+ }
+ }
+
+ MessageDialog {
+ id: sendToTopConfirmationDialog
+ Component.onCompleted: visible = false
+ icon: StandardIcon.Warning
+ onYes: OutputDevice.sendJobToTop(printJob.key)
+ standardButtons: StandardButton.Yes | StandardButton.No
+ text: printJob && printJob.name ? catalog.i18nc("@label %1 is the name of a print job.", "Are you sure you want to move %1 to the top of the queue?").arg(printJob.name) : ""
+ title: catalog.i18nc("@window:title", "Move print job to top")
+ }
+
+ MessageDialog {
+ id: deleteConfirmationDialog
+ Component.onCompleted: visible = false
+ icon: StandardIcon.Warning
+ onYes: OutputDevice.deleteJobFromQueue(printJob.key)
+ standardButtons: StandardButton.Yes | StandardButton.No
+ text: printJob && printJob.name ? catalog.i18nc("@label %1 is the name of a print job.", "Are you sure you want to delete %1?").arg(printJob.name) : ""
+ title: catalog.i18nc("@window:title", "Delete print job")
+ }
+
+ MessageDialog {
+ id: abortConfirmationDialog
+ Component.onCompleted: visible = false
+ icon: StandardIcon.Warning
+ onYes: printJob.setState("abort")
+ standardButtons: StandardButton.Yes | StandardButton.No
+ text: printJob && printJob.name ? catalog.i18nc("@label %1 is the name of a print job.", "Are you sure you want to abort %1?").arg(printJob.name) : ""
+ title: catalog.i18nc("@window:title", "Abort print")
+ }
+
+ function switchPopupState() {
+ popUp.visible ? popUp.close() : popUp.open()
+ }
+ function open() {
+ popUp.open()
+ }
+ function close() {
+ popUp.close()
+ }
+ function isAssigned(job) {
+ if (!job) {
+ return false;
+ }
+ return job.assignedPrinter ? true : false;
+ }
+}
diff --git a/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenuButton.qml b/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenuButton.qml
new file mode 100644
index 0000000000..e91e8b04d2
--- /dev/null
+++ b/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenuButton.qml
@@ -0,0 +1,32 @@
+// Copyright (c) 2018 Ultimaker B.V.
+// Cura is released under the terms of the LGPLv3 or higher.
+
+import QtQuick 2.3
+import QtQuick.Controls 2.0
+import UM 1.3 as UM
+import Cura 1.0 as Cura
+
+Button
+{
+ id: base
+ background: Rectangle
+ {
+ color: enabled ? UM.Theme.getColor("viewport_background") : "transparent"
+ height: base.height
+ opacity: base.down || base.hovered ? 1 : 0
+ radius: Math.round(0.5 * width)
+ width: base.width
+ }
+ contentItem: Label {
+ color: enabled ? UM.Theme.getColor("monitor_text_primary") : UM.Theme.getColor("monitor_text_disabled")
+ font.pixelSize: 32 * screenScaleFactor
+ 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
new file mode 100644
index 0000000000..deed3ac5e6
--- /dev/null
+++ b/plugins/UM3NetworkPrinting/resources/qml/MonitorExtruderConfiguration.qml
@@ -0,0 +1,102 @@
+// Copyright (c) 2018 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
+
+/**
+ * This component comprises a colored extruder icon, the material name, and the
+ * print core name. It is used by the MonitorPrinterConfiguration component with
+ * a sibling instance as well as a MonitorBuildplateConfiguration instance.
+ *
+ * NOTE: For most labels, a fixed height with vertical alignment is used to make
+ * layouts more deterministic (like the fixed-size textboxes used in original
+ * mock-ups). This is also a stand-in for CSS's 'line-height' property. Denoted
+ * with '// FIXED-LINE-HEIGHT:'.
+ */
+Item
+{
+ // The material color
+ property alias color: extruderIcon.color
+
+ // The extruder position; NOTE: Decent human beings count from 0
+ property alias position: extruderIcon.position
+
+ // The material name
+ property alias material: materialLabel.text
+
+ // The print core name (referred to as hotendID in Python)
+ property alias printCore: printCoreLabel.text
+
+ // Height is 2 x 18px labels, plus 4px spacing between them
+ height: 40 * screenScaleFactor // TODO: Theme!
+ width: childrenRect.width
+
+ MonitorIconExtruder
+ {
+ id: extruderIcon
+ color: UM.Theme.getColor("monitor_skeleton_loading")
+ position: 0
+ }
+
+ Rectangle
+ {
+ id: materialLabelWrapper
+ anchors
+ {
+ left: extruderIcon.right
+ leftMargin: 12 * screenScaleFactor // TODO: Theme!
+ }
+ color: materialLabel.visible > 0 ? "transparent" : UM.Theme.getColor("monitor_skeleton_loading")
+ height: 18 * screenScaleFactor // TODO: Theme!
+ width: Math.max(materialLabel.contentWidth, 60 * screenScaleFactor) // TODO: Theme!
+ radius: 2 * screenScaleFactor // TODO: Theme!
+
+ Label
+ {
+ id: materialLabel
+
+ color: UM.Theme.getColor("monitor_text_primary")
+ elide: Text.ElideRight
+ font: UM.Theme.getFont("default") // 12pt, regular
+ text: ""
+ visible: text !== ""
+
+ // FIXED-LINE-HEIGHT:
+ height: parent.height
+ verticalAlignment: Text.AlignVCenter
+ renderType: Text.NativeRendering
+ }
+ }
+
+ Rectangle
+ {
+ id: printCoreLabelWrapper
+ anchors
+ {
+ left: materialLabelWrapper.left
+ bottom: parent.bottom
+ }
+ color: printCoreLabel.visible > 0 ? "transparent" : UM.Theme.getColor("monitor_skeleton_loading")
+ height: 18 * screenScaleFactor // TODO: Theme!
+ width: Math.max(printCoreLabel.contentWidth, 36 * screenScaleFactor) // TODO: Theme!
+ radius: 2 * screenScaleFactor // TODO: Theme!
+
+ Label
+ {
+ id: printCoreLabel
+
+ color: UM.Theme.getColor("monitor_text_primary")
+ elide: Text.ElideRight
+ font: UM.Theme.getFont("default_bold") // 12pt, bold
+ text: ""
+ visible: text !== ""
+
+ // 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
new file mode 100644
index 0000000000..f6b84d69b2
--- /dev/null
+++ b/plugins/UM3NetworkPrinting/resources/qml/MonitorIconExtruder.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.2
+import QtQuick.Controls 2.0
+import UM 1.3 as UM
+
+/**
+ * This component is a sort of "super icon" which includes a colored SVG image
+ * as well as the extruder position number. It is used in the the
+ * MonitorExtruderConfiguration component.
+ */
+Item
+{
+ // The material color
+ property alias color: icon.color
+
+ // The extruder position; NOTE: Decent human beings count from 0
+ property int position: 0
+
+ // The extruder icon size; NOTE: This shouldn't need to be changed
+ property int size: 32 * screenScaleFactor // TODO: Theme!
+
+ // THe extruder icon source; NOTE: This shouldn't need to be changed
+ property string iconSource: "../svg/icons/extruder.svg"
+
+ height: size
+ width: size
+
+ UM.RecolorImage
+ {
+ id: icon
+ anchors.fill: parent
+ source: iconSource
+ width: size
+ }
+
+ Label
+ {
+ id: positionLabel
+ font: UM.Theme.getFont("small")
+ color: UM.Theme.getColor("monitor_text_primary")
+ height: Math.round(size / 2)
+ horizontalAlignment: Text.AlignHCenter
+ text: position + 1
+ verticalAlignment: Text.AlignVCenter
+ width: Math.round(size / 2)
+ 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
new file mode 100644
index 0000000000..0d2c7f8beb
--- /dev/null
+++ b/plugins/UM3NetworkPrinting/resources/qml/MonitorInfoBlurb.qml
@@ -0,0 +1,54 @@
+// Copyright (c) 2018 Ultimaker B.V.
+// Cura is released under the terms of the LGPLv3 or higher.
+
+import QtQuick 2.3
+import QtQuick.Controls 2.0
+import UM 1.3 as UM
+
+/**
+ * A MonitorInfoBlurb is an extension of the GenericPopUp used to show static information (vs. interactive context
+ * menus). It accepts some text (text), an item to link to to (target), and a specification of which side of the target
+ * to appear on (direction). It also sets the GenericPopUp's color to black, to differentiate itself from a menu.
+ */
+Item
+{
+ property alias text: innerLabel.text
+ property alias target: popUp.target
+ property alias direction: popUp.direction
+
+ GenericPopUp
+ {
+ id: popUp
+
+ // Which way should the pop-up point? Default is up, but will flip when required
+ direction: "up"
+
+ // Use dark grey for info blurbs and white for context menus
+ color: UM.Theme.getColor("monitor_tooltip")
+
+ contentItem: Item
+ {
+ id: contentWrapper
+ implicitWidth: childrenRect.width
+ implicitHeight: innerLabel.contentHeight + 2 * innerLabel.padding
+ Label
+ {
+ id: innerLabel
+ padding: 12 * screenScaleFactor // TODO: Theme!
+ text: ""
+ wrapMode: Text.WordWrap
+ width: 240 * screenScaleFactor // TODO: Theme!
+ color: UM.Theme.getColor("monitor_tooltip_text")
+ font: UM.Theme.getFont("default")
+ renderType: Text.NativeRendering
+ }
+ }
+ }
+
+ function open() {
+ popUp.open()
+ }
+ function close() {
+ popUp.close()
+ }
+}
diff --git a/plugins/UM3NetworkPrinting/resources/qml/MonitorItem.qml b/plugins/UM3NetworkPrinting/resources/qml/MonitorItem.qml
index bbbc3feee6..41b3a93a7b 100644
--- a/plugins/UM3NetworkPrinting/resources/qml/MonitorItem.qml
+++ b/plugins/UM3NetworkPrinting/resources/qml/MonitorItem.qml
@@ -1,54 +1,45 @@
+// Copyright (c) 2018 Ultimaker B.V.
+// Cura is released under the terms of the LGPLv3 or higher.
+
import QtQuick 2.2
-
-
import UM 1.3 as UM
import Cura 1.0 as Cura
-Component
-{
- Item
- {
- width: maximumWidth
- height: maximumHeight
- Image
- {
- id: cameraImage
- width: Math.min(sourceSize.width === 0 ? 800 * screenScaleFactor : sourceSize.width, maximumWidth)
- height: Math.floor((sourceSize.height === 0 ? 600 * screenScaleFactor : sourceSize.height) * width / sourceSize.width)
- anchors.horizontalCenter: parent.horizontalCenter
- anchors.verticalCenter: parent.verticalCenter
- z: 1
- Component.onCompleted:
- {
- if(OutputDevice.activePrinter != null && OutputDevice.activePrinter.camera != null)
- {
- OutputDevice.activePrinter.camera.start()
+Component {
+ Item {
+ height: maximumHeight;
+ width: maximumWidth;
+
+ Cura.NetworkMJPGImage {
+ id: cameraImage;
+ anchors {
+ horizontalCenter: parent.horizontalCenter;
+ verticalCenter: parent.verticalCenter;
+ }
+ Component.onCompleted: {
+ if (OutputDevice.activePrinter != null && OutputDevice.activePrinter.cameraUrl != null) {
+ cameraImage.start();
}
}
- onVisibleChanged:
- {
- if(visible)
- {
- if(OutputDevice.activePrinter != null && OutputDevice.activePrinter.camera != null)
- {
- OutputDevice.activePrinter.camera.start()
+ height: Math.floor((imageHeight === 0 ? 600 * screenScaleFactor : imageHeight) * width / imageWidth);
+ onVisibleChanged: {
+ if (visible) {
+ if (OutputDevice.activePrinter != null && OutputDevice.activePrinter.cameraUrl != null) {
+ cameraImage.start();
}
- } else
- {
- if(OutputDevice.activePrinter != null && OutputDevice.activePrinter.camera != null)
- {
- OutputDevice.activePrinter.camera.stop()
+ } else {
+ if (OutputDevice.activePrinter != null && OutputDevice.activePrinter.cameraUrl != null) {
+ cameraImage.stop();
}
}
}
- source:
- {
- if(OutputDevice.activePrinter != null && OutputDevice.activePrinter.camera != null && OutputDevice.activePrinter.camera.latestImage)
- {
- return OutputDevice.activePrinter.camera.latestImage;
+ source: {
+ if (OutputDevice.activePrinter != null && OutputDevice.activePrinter.cameraUrl != null) {
+ return OutputDevice.activePrinter.cameraUrl;
}
- return "";
}
+ width: Math.min(imageWidth === 0 ? 800 * screenScaleFactor : imageWidth, maximumWidth);
+ z: 1;
}
}
}
\ No newline at end of file
diff --git a/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobCard.qml b/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobCard.qml
new file mode 100644
index 0000000000..ea6da9c25d
--- /dev/null
+++ b/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobCard.qml
@@ -0,0 +1,253 @@
+// Copyright (c) 2018 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
+import Cura 1.0 as Cura
+
+/**
+ * A Print Job Card is essentially just a filled-in Expandable Card item. All
+ * data within it is derived from being passed a printJob property.
+ *
+ * NOTE: For most labels, a fixed height with vertical alignment is used to make
+ * layouts more deterministic (like the fixed-size textboxes used in original
+ * mock-ups). This is also a stand-in for CSS's 'line-height' property. Denoted
+ * with '// FIXED-LINE-HEIGHT:'.
+ */
+Item
+{
+ id: base
+
+ // The print job which all other data is derived from
+ property var printJob: null
+
+ width: parent.width
+ height: childrenRect.height
+
+ ExpandableCard
+ {
+ enabled: printJob != null
+ borderColor: printJob && printJob.configurationChanges.length !== 0 ? UM.Theme.getColor("warning") : UM.Theme.getColor("monitor_card_border")
+ headerItem: Row
+ {
+ height: 48 * screenScaleFactor // TODO: Theme!
+ anchors.left: parent.left
+ anchors.leftMargin: 24 * screenScaleFactor // TODO: Theme!
+ spacing: 18 * screenScaleFactor // TODO: Theme!
+
+ MonitorPrintJobPreview
+ {
+ printJob: base.printJob
+ size: 32 * screenScaleFactor // TODO: Theme!
+ anchors.verticalCenter: parent.verticalCenter
+ }
+
+ Item
+ {
+ anchors.verticalCenter: parent.verticalCenter
+ height: 18 * screenScaleFactor // TODO: Theme!
+ width: UM.Theme.getSize("monitor_column").width
+ Rectangle
+ {
+ color: UM.Theme.getColor("monitor_skeleton_loading")
+ width: Math.round(parent.width / 2)
+ height: parent.height
+ visible: !printJob
+ radius: 2 * screenScaleFactor // TODO: Theme!
+ }
+ Label
+ {
+ text: printJob && printJob.name ? printJob.name : ""
+ color: UM.Theme.getColor("monitor_text_primary")
+ elide: Text.ElideRight
+ font: UM.Theme.getFont("medium") // 14pt, regular
+ visible: printJob
+
+ // FIXED-LINE-HEIGHT:
+ height: parent.height
+ verticalAlignment: Text.AlignVCenter
+ renderType: Text.NativeRendering
+ }
+ }
+
+ Item
+ {
+ anchors.verticalCenter: parent.verticalCenter
+ height: 18 * screenScaleFactor // TODO: Theme!
+ width: UM.Theme.getSize("monitor_column").width
+ Rectangle
+ {
+ color: UM.Theme.getColor("monitor_skeleton_loading")
+ width: Math.round(parent.width / 3)
+ height: parent.height
+ visible: !printJob
+ radius: 2 * screenScaleFactor // TODO: Theme!
+ }
+ Label
+ {
+ text: printJob ? OutputDevice.formatDuration(printJob.timeTotal) : ""
+ color: UM.Theme.getColor("monitor_text_primary")
+ elide: Text.ElideRight
+ font: UM.Theme.getFont("medium") // 14pt, regular
+ visible: printJob
+
+ // FIXED-LINE-HEIGHT:
+ height: 18 * screenScaleFactor // TODO: Theme!
+ verticalAlignment: Text.AlignVCenter
+ renderType: Text.NativeRendering
+ }
+ }
+
+ Item
+ {
+ anchors.verticalCenter: parent.verticalCenter
+ height: 18 * screenScaleFactor // TODO: This should be childrenRect.height but QML throws warnings
+ width: childrenRect.width
+
+ Rectangle
+ {
+ color: UM.Theme.getColor("monitor_skeleton_loading")
+ width: 72 * screenScaleFactor // TODO: Theme!
+ height: parent.height
+ visible: !printJob
+ radius: 2 * screenScaleFactor // TODO: Theme!
+ }
+
+ Label
+ {
+ id: printerAssignmentLabel
+ anchors.verticalCenter: parent.verticalCenter
+ color: UM.Theme.getColor("monitor_text_primary")
+ elide: Text.ElideRight
+ font: UM.Theme.getFont("medium") // 14pt, regular
+ text: {
+ if (printJob !== null) {
+ if (printJob.assignedPrinter == null)
+ {
+ if (printJob.state == "error")
+ {
+ return catalog.i18nc("@label", "Unavailable printer")
+ }
+ return catalog.i18nc("@label", "First available")
+ }
+ return printJob.assignedPrinter.name
+ }
+ return ""
+ }
+ visible: printJob
+ width: 120 * screenScaleFactor // TODO: Theme!
+
+ // FIXED-LINE-HEIGHT:
+ height: parent.height
+ verticalAlignment: Text.AlignVCenter
+ renderType: Text.NativeRendering
+ }
+
+ Row
+ {
+ id: printerFamilyPills
+ anchors
+ {
+ left: printerAssignmentLabel.right;
+ leftMargin: 12 // TODO: Theme!
+ verticalCenter: parent.verticalCenter
+ }
+ height: childrenRect.height
+ spacing: 6 // TODO: Theme!
+ visible: printJob
+
+ MonitorPrinterPill
+ {
+ text: printJob.configuration.printerType
+ }
+ }
+ }
+ }
+ drawerItem: Row
+ {
+ anchors
+ {
+ left: parent.left
+ leftMargin: 74 * screenScaleFactor // TODO: Theme!
+ }
+ height: 108 * screenScaleFactor // TODO: Theme!
+ spacing: 18 * screenScaleFactor // TODO: Theme!
+
+ MonitorPrinterConfiguration
+ {
+ id: printerConfiguration
+ anchors.verticalCenter: parent.verticalCenter
+ buildplate: catalog.i18nc("@label", "Glass")
+ configurations:
+ [
+ base.printJob.configuration.extruderConfigurations[0],
+ base.printJob.configuration.extruderConfigurations[1]
+ ]
+ height: 72 * screenScaleFactor // TODO: Theme!
+ }
+ Label {
+ text: printJob && printJob.owner ? printJob.owner : ""
+ color: UM.Theme.getColor("monitor_text_primary")
+ elide: Text.ElideRight
+ font: UM.Theme.getFont("medium") // 14pt, regular
+ anchors.top: printerConfiguration.top
+
+ // FIXED-LINE-HEIGHT:
+ height: 18 * screenScaleFactor // TODO: Theme!
+ verticalAlignment: Text.AlignVCenter
+ renderType: Text.NativeRendering
+ }
+ }
+ }
+
+ MonitorContextMenuButton
+ {
+ id: contextMenuButton
+ anchors
+ {
+ right: parent.right
+ rightMargin: 8 * screenScaleFactor // TODO: Theme!
+ top: parent.top
+ topMargin: 8 * screenScaleFactor // TODO: Theme!
+ }
+ width: 32 * screenScaleFactor // TODO: Theme!
+ height: 32 * screenScaleFactor // TODO: Theme!
+ enabled: OutputDevice.supportsPrintJobActions
+ onClicked: enabled ? contextMenu.switchPopupState() : {}
+ visible:
+ {
+ if (!printJob) {
+ return false
+ }
+ var states = ["queued", "error", "sent_to_printer", "pre_print", "printing", "pausing", "paused", "resuming"]
+ return states.indexOf(printJob.state) !== -1
+ }
+ }
+
+ MonitorContextMenu
+ {
+ id: contextMenu
+ printJob: base.printJob ? base.printJob : null
+ target: contextMenuButton
+ }
+
+ // For cloud printing, add this mouse area over the disabled contextButton to indicate that it's not available
+ MouseArea
+ {
+ id: contextMenuDisabledButtonArea
+ anchors.fill: contextMenuButton
+ hoverEnabled: contextMenuButton.visible && !contextMenuButton.enabled
+ onEntered: contextMenuDisabledInfo.open()
+ onExited: contextMenuDisabledInfo.close()
+ enabled: !contextMenuButton.enabled
+ }
+
+ // TODO: uncomment this tooltip as soon as the required firmware is released
+ // 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
new file mode 100644
index 0000000000..a392571757
--- /dev/null
+++ b/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobPreview.qml
@@ -0,0 +1,101 @@
+// Copyright (c) 2018 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
+
+// TODO: Documentation!
+Item
+{
+ id: printJobPreview
+
+ property var printJob: null
+ property var size: 256
+
+ width: size
+ height: size
+
+ Rectangle
+ {
+ anchors.fill: parent
+ color: printJob ? "transparent" : UM.Theme.getColor("monitor_skeleton_loading")
+ radius: 8 // TODO: Theme!
+ Image
+ {
+ id: previewImage
+ anchors.fill: parent
+ opacity:
+ {
+ if (printJob && (printJob.state == "error" || printJob.configurationChanges.length > 0 || !printJob.isActive))
+ {
+ return 0.5
+ }
+ return 1.0
+ }
+ source: printJob ? printJob.previewImageUrl : ""
+ }
+ }
+
+
+ UM.RecolorImage
+ {
+ id: ultiBotImage
+
+ anchors.centerIn: printJobPreview
+ color: UM.Theme.getColor("monitor_placeholder_image")
+ height: printJobPreview.height
+ source: "../svg/ultibot.svg"
+ sourceSize
+ {
+ height: height
+ width: width
+ }
+ /* Since print jobs ALWAYS have an image url, we have to check if that image URL errors or
+ not in order to determine if we show the placeholder (ultibot) image instead. */
+ visible: printJob && previewImage.status == Image.Error
+ width: printJobPreview.width
+ }
+
+ UM.RecolorImage
+ {
+ id: overlayIcon
+ anchors.centerIn: printJobPreview
+ color: UM.Theme.getColor("monitor_image_overlay")
+ height: 0.5 * printJobPreview.height
+ source:
+ {
+ if (!printJob)
+ {
+ return ""
+ }
+ if (printJob.configurationChanges.length > 0)
+ {
+ return "../svg/warning-icon.svg"
+ }
+ switch(printJob.state)
+ {
+ case "error":
+ return "../svg/aborted-icon.svg"
+ case "wait_cleanup":
+ return printJob.timeTotal > printJob.timeElapsed ? "../svg/aborted-icon.svg" : ""
+ case "pausing":
+ return "../svg/paused-icon.svg"
+ case "paused":
+ return "../svg/paused-icon.svg"
+ case "resuming":
+ return "../svg/paused-icon.svg"
+ default:
+ return ""
+ }
+ return ""
+ }
+ sourceSize
+ {
+ height: height
+ width: width
+ }
+ 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
new file mode 100644
index 0000000000..e6d09b68f6
--- /dev/null
+++ b/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml
@@ -0,0 +1,110 @@
+// Copyright (c) 2018 Ultimaker B.V.
+// Cura is released under the terms of the LGPLv3 or higher.
+
+import QtQuick 2.3
+import QtQuick.Controls.Styles 1.3
+import QtQuick.Controls 1.4
+import UM 1.3 as UM
+
+/**
+ * NOTE: For most labels, a fixed height with vertical alignment is used to make
+ * layouts more deterministic (like the fixed-size textboxes used in original
+ * mock-ups). This is also a stand-in for CSS's 'line-height' property. Denoted
+ * with '// FIXED-LINE-HEIGHT:'.
+ */
+Item
+{
+ id: base
+
+ // The print job which all other information is dervied from
+ property var printJob: null
+
+ width: childrenRect.width
+ height: 18 * screenScaleFactor // TODO: Theme!
+
+ UM.ProgressBar
+ {
+ id: progressBar
+ anchors
+ {
+ verticalCenter: parent.verticalCenter
+ left: parent.left
+ }
+ value: printJob ? printJob.progress : 0
+ width: UM.Theme.getSize("monitor_column").width
+ }
+
+ Label
+ {
+ id: percentLabel
+ anchors
+ {
+ left: progressBar.right
+ leftMargin: 18 * screenScaleFactor // TODO: Theme!
+ 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
+
+ // FIXED-LINE-HEIGHT:
+ height: 18 * screenScaleFactor // TODO: Theme!
+ verticalAlignment: Text.AlignVCenter
+ renderType: Text.NativeRendering
+ }
+ Label
+ {
+ id: statusLabel
+ anchors
+ {
+ left: percentLabel.right
+ leftMargin: 18 * screenScaleFactor // TODO: Theme!
+ verticalCenter: parent.verticalCenter
+ }
+ color: UM.Theme.getColor("monitor_text_primary")
+ font: UM.Theme.getFont("medium") // 14pt, regular
+ text:
+ {
+ if (!printJob)
+ {
+ return ""
+ }
+ switch (printJob.state)
+ {
+ case "wait_cleanup":
+ if (printJob.timeTotal > printJob.timeElapsed)
+ {
+ return catalog.i18nc("@label:status", "Aborted")
+ }
+ return catalog.i18nc("@label:status", "Finished")
+ case "finished":
+ return catalog.i18nc("@label:status", "Finished")
+ case "sent_to_printer":
+ return catalog.i18nc("@label:status", "Preparing...")
+ case "pre_print":
+ return catalog.i18nc("@label:status", "Preparing...")
+ case "aborting": // NOTE: Doesn't exist but maybe should someday
+ return catalog.i18nc("@label:status", "Aborting...")
+ case "aborted": // NOTE: Unused, see above
+ return catalog.i18nc("@label:status", "Aborted")
+ case "pausing":
+ return catalog.i18nc("@label:status", "Pausing...")
+ case "paused":
+ return catalog.i18nc("@label:status", "Paused")
+ case "resuming":
+ return catalog.i18nc("@label:status", "Resuming...")
+ case "queued":
+ 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 )))
+ }
+ }
+ width: contentWidth
+
+ // 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/MonitorPrinterCard.qml b/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml
new file mode 100644
index 0000000000..8562cec59d
--- /dev/null
+++ b/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml
@@ -0,0 +1,458 @@
+// Copyright (c) 2018 Ultimaker B.V.
+// Cura is released under the terms of the LGPLv3 or higher.
+
+import QtQuick 2.3
+import QtQuick.Controls 2.0
+import QtQuick.Dialogs 1.1
+import UM 1.3 as UM
+import Cura 1.0 as Cura
+
+/**
+ * A Printer Card is has two main components: the printer portion and the print job portion, the latter being paired in
+ * the UI when a print job is paired a printer in-cluster.
+ *
+ * NOTE: For most labels, a fixed height with vertical alignment is used to make layouts more deterministic (like the
+ * fixed-size textboxes used in original mock-ups). This is also a stand-in for CSS's 'line-height' property. Denoted
+ * with '// FIXED-LINE-HEIGHT:'.
+ */
+Item
+{
+ id: base
+
+ // The printer which all printer data is derived from
+ property var printer: null
+
+ property var borderSize: 1 * screenScaleFactor // TODO: Theme, and remove from here
+
+ // If the printer card's controls are enabled. This is used by the carousel to prevent opening the context menu or
+ // camera while the printer card is not "in focus"
+ property var enabled: true
+
+ // 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: 834 * screenScaleFactor // TODO: Theme!
+ height: childrenRect.height
+
+ Rectangle
+ {
+ id: background
+ anchors.fill: parent
+ color: UM.Theme.getColor("monitor_card_background")
+ border
+ {
+ color: UM.Theme.getColor("monitor_card_border")
+ width: borderSize // TODO: Remove once themed
+ }
+ radius: 2 * screenScaleFactor // TODO: Theme!
+ }
+
+ // Printer portion
+ Item
+ {
+ id: printerInfo
+
+ width: parent.width
+ height: 144 * screenScaleFactor // TODO: Theme!
+
+ Row
+ {
+ anchors
+ {
+ left: parent.left
+ leftMargin: 36 * screenScaleFactor // TODO: Theme!
+ verticalCenter: parent.verticalCenter
+ }
+ spacing: 18 * screenScaleFactor // TODO: Theme!
+
+ Rectangle
+ {
+ id: printerImage
+ width: 108 * screenScaleFactor // TODO: Theme!
+ height: 108 * screenScaleFactor // TODO: Theme!
+ color: printer ? "transparent" : UM.Theme.getColor("monitor_skeleton_loading")
+ radius: 8 // TODO: Theme!
+ Image
+ {
+ anchors.fill: parent
+ fillMode: Image.PreserveAspectFit
+ source: printer ? "../png/" + printer.type + ".png" : ""
+ mipmap: true
+ }
+ }
+
+
+ Item
+ {
+ anchors
+ {
+ verticalCenter: parent.verticalCenter
+ }
+ width: 180 * screenScaleFactor // TODO: Theme!
+ height: printerNameLabel.height + printerFamilyPill.height + 6 * screenScaleFactor // TODO: Theme!
+
+ Rectangle
+ {
+ id: printerNameLabel
+ color: printer ? "transparent" : UM.Theme.getColor("monitor_skeleton_loading")
+ height: 18 * screenScaleFactor // TODO: Theme!
+ width: parent.width
+ radius: 2 * screenScaleFactor // TODO: Theme!
+
+ Label
+ {
+ text: printer && printer.name ? printer.name : ""
+ color: UM.Theme.getColor("monitor_text_primary")
+ elide: Text.ElideRight
+ font: UM.Theme.getFont("large") // 16pt, bold
+ width: parent.width
+ visible: printer
+
+ // FIXED-LINE-HEIGHT:
+ height: parent.height
+ verticalAlignment: Text.AlignVCenter
+ renderType: Text.NativeRendering
+ }
+ }
+
+ Rectangle
+ {
+ color: UM.Theme.getColor("monitor_skeleton_loading")
+ height: 18 * screenScaleFactor // TODO: Theme!
+ radius: 2 * screenScaleFactor // TODO: Theme!
+ visible: !printer
+ width: 48 * screenScaleFactor // TODO: Theme!
+ }
+ MonitorPrinterPill
+ {
+ id: printerFamilyPill
+ anchors
+ {
+ top: printerNameLabel.bottom
+ topMargin: 6 * screenScaleFactor // TODO: Theme!
+ left: printerNameLabel.left
+ }
+ text: printer ? printer.type : ""
+ }
+ }
+
+ MonitorPrinterConfiguration
+ {
+ id: printerConfiguration
+ anchors.verticalCenter: parent.verticalCenter
+ buildplate: printer ? catalog.i18nc("@label", "Glass") : null // 'Glass' as a default
+ configurations:
+ {
+ var configs = []
+ if (printer)
+ {
+ configs.push(printer.printerConfiguration.extruderConfigurations[0])
+ configs.push(printer.printerConfiguration.extruderConfigurations[1])
+ }
+ else
+ {
+ configs.push(null, null)
+ }
+ return configs
+ }
+ height: 72 * screenScaleFactor // TODO: Theme!te theRect's x property
+ }
+ }
+
+ MonitorContextMenuButton
+ {
+ id: contextMenuButton
+ anchors
+ {
+ right: parent.right
+ rightMargin: 12 * screenScaleFactor // TODO: Theme!
+ top: parent.top
+ topMargin: 12 * screenScaleFactor // TODO: Theme!
+ }
+ width: 36 * screenScaleFactor // TODO: Theme!
+ height: 36 * screenScaleFactor // TODO: Theme!
+ enabled: OutputDevice.supportsPrintJobActions
+ onClicked: enabled ? contextMenu.switchPopupState() : {}
+ visible:
+ {
+ if (!printer || !printer.activePrintJob) {
+ return false
+ }
+ var states = ["queued", "error", "sent_to_printer", "pre_print", "printing", "pausing", "paused", "resuming"]
+ return states.indexOf(printer.activePrintJob.state) !== -1
+ }
+ }
+
+ MonitorContextMenu
+ {
+ id: contextMenu
+ printJob: printer ? printer.activePrintJob : null
+ target: contextMenuButton
+ }
+
+ // For cloud printing, add this mouse area over the disabled contextButton to indicate that it's not available
+ MouseArea
+ {
+ id: contextMenuDisabledButtonArea
+ anchors.fill: contextMenuButton
+ hoverEnabled: contextMenuButton.visible && !contextMenuButton.enabled
+ onEntered: contextMenuDisabledInfo.open()
+ onExited: contextMenuDisabledInfo.close()
+ enabled: !contextMenuButton.enabled
+ }
+
+ // TODO: uncomment this tooltip as soon as the required firmware is released
+ // MonitorInfoBlurb
+ // {
+ // id: contextMenuDisabledInfo
+ // text: catalog.i18nc("@info", "Please update your printer's firmware to manage the queue remotely.")
+ // target: contextMenuButton
+ // }
+
+ CameraButton
+ {
+ id: cameraButton
+ anchors
+ {
+ right: parent.right
+ rightMargin: 20 * screenScaleFactor // TODO: Theme!
+ bottom: parent.bottom
+ bottomMargin: 20 * screenScaleFactor // TODO: Theme!
+ }
+ iconSource: "../svg/icons/camera.svg"
+ enabled: !cloudConnection
+ visible: printer
+ }
+
+ // For cloud printing, add this mouse area over the disabled cameraButton to indicate that it's not available
+ MouseArea
+ {
+ id: cameraDisabledButtonArea
+ anchors.fill: cameraButton
+ hoverEnabled: cameraButton.visible && !cameraButton.enabled
+ onEntered: cameraDisabledInfo.open()
+ onExited: cameraDisabledInfo.close()
+ enabled: !cameraButton.enabled
+ }
+
+ MonitorInfoBlurb
+ {
+ id: cameraDisabledInfo
+ text: catalog.i18nc("@info", "The webcam is not available because you are monitoring a cloud printer.")
+ target: cameraButton
+ }
+ }
+
+ // Divider
+ Rectangle
+ {
+ anchors
+ {
+ top: printJobInfo.top
+ left: printJobInfo.left
+ right: printJobInfo.right
+ }
+ height: borderSize // Remove once themed
+ color: background.border.color
+ }
+
+ // Print job portion
+ Rectangle
+ {
+ id: printJobInfo
+ anchors
+ {
+ top: printerInfo.bottom
+ topMargin: -borderSize * screenScaleFactor // TODO: Theme!
+ }
+ border
+ {
+ color: printer && printer.activePrintJob && printer.activePrintJob.configurationChanges.length > 0 ? UM.Theme.getColor("warning") : "transparent" // TODO: Theme!
+ width: borderSize // TODO: Remove once themed
+ }
+ color: "transparent" // TODO: Theme!
+ height: 84 * screenScaleFactor + borderSize // TODO: Remove once themed
+ width: parent.width
+
+ Row
+ {
+ anchors
+ {
+ fill: parent
+ topMargin: 12 * screenScaleFactor + borderSize // TODO: Theme!
+ bottomMargin: 12 * screenScaleFactor // TODO: Theme!
+ leftMargin: 36 * screenScaleFactor // TODO: Theme!
+ }
+ height: childrenRect.height
+ spacing: 18 * screenScaleFactor // TODO: Theme!
+
+ Label
+ {
+ id: printerStatus
+ anchors
+ {
+ verticalCenter: parent.verticalCenter
+ }
+ color: printer ? UM.Theme.getColor("monitor_text_primary") : UM.Theme.getColor("monitor_text_disabled")
+ font: UM.Theme.getFont("large_bold") // 16pt, bold
+ text: {
+ if (!printer) {
+ return catalog.i18nc("@label:status", "Loading...")
+ }
+ if (printer && printer.state == "disabled")
+ {
+ return catalog.i18nc("@label:status", "Unavailable")
+ }
+ if (printer && printer.state == "unreachable")
+ {
+ return catalog.i18nc("@label:status", "Unreachable")
+ }
+ if (printer && !printer.activePrintJob && printer.state == "idle")
+ {
+ return catalog.i18nc("@label:status", "Idle")
+ }
+ return ""
+ }
+ visible: text !== ""
+ renderType: Text.NativeRendering
+ }
+
+ Item
+ {
+ anchors
+ {
+ verticalCenter: parent.verticalCenter
+ }
+ width: printerImage.width
+ height: 60 * screenScaleFactor // TODO: Theme!
+ MonitorPrintJobPreview
+ {
+ anchors.centerIn: parent
+ printJob: printer ? printer.activePrintJob : null
+ size: parent.height
+ }
+ visible: printer && printer.activePrintJob && !printerStatus.visible
+ }
+
+ Item
+ {
+ anchors
+ {
+ verticalCenter: parent.verticalCenter
+ }
+ width: 180 * screenScaleFactor // TODO: Theme!
+ height: printerNameLabel.height + printerFamilyPill.height + 6 * screenScaleFactor // TODO: Theme!
+ visible: printer && printer.activePrintJob && !printerStatus.visible
+
+ Label
+ {
+ id: printerJobNameLabel
+ color: printer && printer.activePrintJob && printer.activePrintJob.isActive ? UM.Theme.getColor("monitor_text_primary") : UM.Theme.getColor("monitor_text_disabled")
+ elide: Text.ElideRight
+ font: UM.Theme.getFont("large") // 16pt, bold
+ text: printer && printer.activePrintJob ? printer.activePrintJob.name : catalog.i18nc("@label", "Untitled")
+ width: parent.width
+
+ // FIXED-LINE-HEIGHT:
+ height: 18 * screenScaleFactor // TODO: Theme!
+ verticalAlignment: Text.AlignVCenter
+ renderType: Text.NativeRendering
+ }
+
+ Label
+ {
+ id: printerJobOwnerLabel
+ anchors
+ {
+ top: printerJobNameLabel.bottom
+ topMargin: 6 * screenScaleFactor // TODO: Theme!
+ left: printerJobNameLabel.left
+ }
+ color: printer && printer.activePrintJob && printer.activePrintJob.isActive ? UM.Theme.getColor("monitor_text_primary") : UM.Theme.getColor("monitor_text_disabled")
+ elide: Text.ElideRight
+ font: UM.Theme.getFont("default") // 12pt, regular
+ text: printer && printer.activePrintJob ? printer.activePrintJob.owner : catalog.i18nc("@label", "Anonymous")
+ width: parent.width
+
+ // FIXED-LINE-HEIGHT:
+ height: 18 * screenScaleFactor // TODO: Theme!
+ verticalAlignment: Text.AlignVCenter
+ renderType: Text.NativeRendering
+ }
+ }
+
+ MonitorPrintJobProgressBar
+ {
+ anchors
+ {
+ verticalCenter: parent.verticalCenter
+ }
+ printJob: printer && printer.activePrintJob
+ visible: printer && printer.activePrintJob && printer.activePrintJob.configurationChanges.length === 0 && !printerStatus.visible
+ }
+
+ Label
+ {
+ anchors
+ {
+ verticalCenter: parent.verticalCenter
+ }
+ font: UM.Theme.getFont("default")
+ text: catalog.i18nc("@label:status", "Requires configuration changes")
+ visible: printer && printer.activePrintJob && printer.activePrintJob.configurationChanges.length > 0 && !printerStatus.visible
+ color: UM.Theme.getColor("monitor_text_primary")
+
+ // FIXED-LINE-HEIGHT:
+ height: 18 * screenScaleFactor // TODO: Theme!
+ verticalAlignment: Text.AlignVCenter
+ renderType: Text.NativeRendering
+ }
+ }
+
+ Button
+ {
+ id: detailsButton
+ anchors
+ {
+ verticalCenter: parent.verticalCenter
+ right: parent.right
+ rightMargin: 18 * screenScaleFactor // TODO: Theme!
+ }
+ background: Rectangle
+ {
+ color: UM.Theme.getColor("monitor_secondary_button_shadow")
+ radius: 2 * screenScaleFactor // Todo: Theme!
+ Rectangle
+ {
+ anchors.fill: parent
+ anchors.bottomMargin: 2 * screenScaleFactor // TODO: Theme!
+ color: detailsButton.hovered ? UM.Theme.getColor("monitor_secondary_button_hover") : UM.Theme.getColor("monitor_secondary_button")
+ radius: 2 * screenScaleFactor // Todo: Theme!
+ }
+ }
+ contentItem: Label
+ {
+ anchors.fill: parent
+ anchors.bottomMargin: 2 * screenScaleFactor // TODO: Theme!
+ color: UM.Theme.getColor("monitor_secondary_button_text")
+ font: UM.Theme.getFont("medium") // 14pt, regular
+ text: catalog.i18nc("@action:button","Details");
+ 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() : {}
+ }
+ }
+
+ MonitorConfigOverrideDialog
+ {
+ id: overrideConfirmationDialog
+ printer: base.printer
+ }
+}
diff --git a/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterConfiguration.qml b/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterConfiguration.qml
new file mode 100644
index 0000000000..dbe085e18e
--- /dev/null
+++ b/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterConfiguration.qml
@@ -0,0 +1,58 @@
+// Copyright (c) 2018 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
+
+/**
+ * The MonitorPrinterConfiguration accepts 2 configuration objects as input and
+ * applies them to a MonitorBuildplateConfiguration instance and two instances
+ * of MonitorExtruderConfiguration. It's used in both the MonitorPrintJobCard
+ * component as well as the MonitorPrinterCard component.
+ */
+Item
+{
+ id: base
+
+ // Extracted buildplate configuration
+ property alias buildplate: buildplateConfig.buildplate
+
+ // Array of extracted extruder configurations
+ property var configurations: [null,null]
+
+ // Default size, but should be stretched to fill parent
+ height: 72 * parent.height
+ width: 450 * screenScaleFactor // TODO: Theme!
+
+ Row
+ {
+ id: extruderConfigurationRow
+ spacing: 18 * screenScaleFactor // TODO: Theme!
+
+ Repeater
+ {
+ id: extruderConfigurationRepeater
+ model: configurations
+
+ MonitorExtruderConfiguration
+ {
+ color: modelData && modelData.activeMaterial ? modelData.activeMaterial.color : UM.Theme.getColor("monitor_skeleton_loading")
+ material: modelData && modelData.activeMaterial ? modelData.activeMaterial.name : ""
+ position: modelData && typeof(modelData.position) === "number" ? modelData.position : -1 // Use negative one to create empty extruder number
+ printCore: modelData ? modelData.hotendID : ""
+
+ // Keep things responsive!
+ width: Math.floor((base.width - (configurations.length - 1) * extruderConfigurationRow.spacing) / configurations.length)
+ }
+
+ }
+ }
+
+ MonitorBuildplateConfiguration
+ {
+ id: buildplateConfig
+ 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
new file mode 100644
index 0000000000..3123631784
--- /dev/null
+++ b/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterPill.qml
@@ -0,0 +1,36 @@
+// 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.4
+import UM 1.2 as UM
+
+/**
+ * A MonitorPrinterPill is a blue-colored tag indicating which printers a print
+ * job is compatible with. It is used by the MonitorPrintJobCard component.
+ */
+Item
+{
+ id: monitorPrinterPill
+ property var text: ""
+
+ implicitHeight: 18 * screenScaleFactor // TODO: Theme!
+ implicitWidth: Math.max(printerNameLabel.contentWidth + 12 * screenScaleFactor, 36 * screenScaleFactor) // TODO: Theme!
+
+ Rectangle {
+ id: background
+ anchors.fill: parent
+ color: printerNameLabel.visible ? UM.Theme.getColor("monitor_printer_family_tag") : UM.Theme.getColor("monitor_skeleton_loading")
+ radius: 2 * screenScaleFactor // TODO: Theme!
+ }
+
+ Label {
+ id: printerNameLabel
+ anchors.centerIn: parent
+ color: UM.Theme.getColor("monitor_text_primary")
+ text: monitorPrinterPill.text
+ font.pointSize: 10 // TODO: Theme!
+ visible: monitorPrinterPill.text !== ""
+ renderType: Text.NativeRendering
+ }
+}
diff --git a/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml b/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml
new file mode 100644
index 0000000000..6727c7bd8c
--- /dev/null
+++ b/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml
@@ -0,0 +1,203 @@
+// 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.4
+import QtQuick.Controls.Styles 1.4
+import UM 1.3 as UM
+import Cura 1.0 as Cura
+
+/**
+ * This component contains the print job queue, extracted from the primary
+ * MonitorStage.qml file not for reusability but simply to keep it lean and more
+ * readable.
+ */
+Item
+{
+ // 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
+
+ Label
+ {
+ id: queuedLabel
+ anchors
+ {
+ left: queuedPrintJobs.left
+ top: parent.top
+ }
+ color: UM.Theme.getColor("monitor_text_primary")
+ font: UM.Theme.getFont("large")
+ text: catalog.i18nc("@label", "Queued")
+ renderType: Text.NativeRendering
+ }
+
+ Item
+ {
+ id: manageQueueLabel
+ anchors
+ {
+ right: queuedPrintJobs.right
+ verticalCenter: queuedLabel.verticalCenter
+ }
+ height: 18 * screenScaleFactor // TODO: Theme!
+ width: childrenRect.width
+
+ UM.RecolorImage
+ {
+ id: externalLinkIcon
+ anchors.verticalCenter: manageQueueLabel.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: manageQueueText
+ anchors
+ {
+ left: externalLinkIcon.right
+ leftMargin: 6 * screenScaleFactor // TODO: Theme!
+ verticalCenter: externalLinkIcon.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", "Manage in browser")
+ renderType: Text.NativeRendering
+ }
+ }
+
+ MouseArea
+ {
+ anchors.fill: manageQueueLabel
+ onClicked: OutputDevice.openPrintJobControlPanel()
+ onEntered:
+ {
+ manageQueueText.font.underline = true
+ }
+ onExited:
+ {
+ manageQueueText.font.underline = false
+ }
+ }
+
+ Row
+ {
+ id: printJobQueueHeadings
+ anchors
+ {
+ left: queuedPrintJobs.left
+ leftMargin: 6 * screenScaleFactor // TODO: Theme!
+ top: queuedLabel.bottom
+ topMargin: 24 * screenScaleFactor // TODO: Theme!
+ }
+ 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
+ width: 600 * screenScaleFactor // TODO: Theme! (Should match column size)
+
+ // 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")
+ color: UM.Theme.getColor("monitor_text_primary")
+ elide: Text.ElideRight
+ font: UM.Theme.getFont("medium") // 14pt, regular
+ anchors.verticalCenter: parent.verticalCenter
+ width: 284 * screenScaleFactor // TODO: Theme! (Should match column size)
+
+ // FIXED-LINE-HEIGHT:
+ height: 18 * screenScaleFactor // TODO: Theme!
+ verticalAlignment: Text.AlignVCenter
+ renderType: Text.NativeRendering
+ visible: printJobList.count > 0
+ }
+
+ Label
+ {
+ text: catalog.i18nc("@label", "Total print time")
+ color: UM.Theme.getColor("monitor_text_primary")
+ elide: Text.ElideRight
+ font: UM.Theme.getFont("medium") // 14pt, regular
+ anchors.verticalCenter: parent.verticalCenter
+ 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
+ {
+ text: catalog.i18nc("@label", "Waiting for")
+ color: UM.Theme.getColor("monitor_text_primary")
+ elide: Text.ElideRight
+ font: UM.Theme.getFont("medium") // 14pt, regular
+ anchors.verticalCenter: parent.verticalCenter
+ 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
+ }
+ }
+
+ ScrollView
+ {
+ id: queuedPrintJobs
+ anchors
+ {
+ bottom: parent.bottom
+ horizontalCenter: parent.horizontalCenter
+ top: printJobQueueHeadings.bottom
+ topMargin: 12 * screenScaleFactor // TODO: Theme!
+ }
+ style: UM.Theme.styles.scrollview
+ width: parent.width
+
+ ListView
+ {
+ id: printJobList
+ anchors.fill: parent
+ delegate: MonitorPrintJobCard
+ {
+ anchors
+ {
+ left: parent.left
+ right: parent.right
+ }
+ printJob: modelData
+ }
+ 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)
+ {
+ return OutputDevice.queuedPrintJobs
+ }
+ return [null, null]
+ }
+ spacing: 6 // TODO: Theme!
+ }
+ }
+}
diff --git a/plugins/UM3NetworkPrinting/resources/qml/MonitorStage.qml b/plugins/UM3NetworkPrinting/resources/qml/MonitorStage.qml
new file mode 100644
index 0000000000..e68418c21a
--- /dev/null
+++ b/plugins/UM3NetworkPrinting/resources/qml/MonitorStage.qml
@@ -0,0 +1,87 @@
+// 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.4
+import QtQuick.Controls.Styles 1.4
+import UM 1.3 as UM
+import Cura 1.0 as Cura
+import QtGraphicalEffects 1.0
+
+// This is the root component for the monitor stage.
+Component
+{
+ Rectangle
+ {
+ id: monitorFrame
+
+ height: maximumHeight
+ onVisibleChanged:
+ {
+ if (monitorFrame != null && !monitorFrame.visible)
+ {
+ OutputDevice.setActiveCameraUrl("")
+ }
+ }
+ 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
+ Component.onCompleted: forceActiveFocus()
+
+ UM.I18nCatalog
+ {
+ id: catalog
+ name: "cura"
+ }
+
+ Item
+ {
+ id: printers
+ anchors
+ {
+ top: parent.top
+ topMargin: 48 * screenScaleFactor // TODO: Theme!
+ }
+ width: parent.width
+ height: 264 * screenScaleFactor // TODO: Theme!
+ MonitorCarousel
+ {
+ id: carousel
+ printers:
+ {
+ // 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)
+ {
+ return OutputDevice.printers
+ }
+ return [null]
+ }
+ }
+ }
+
+ MonitorQueue
+ {
+ id: queue
+ width: Math.min(834 * screenScaleFactor, maximumWidth)
+ anchors
+ {
+ bottom: parent.bottom
+ horizontalCenter: parent.horizontalCenter
+ top: printers.bottom
+ topMargin: 48 * screenScaleFactor // TODO: Theme!
+ }
+ }
+
+ PrinterVideoStream
+ {
+ anchors.fill: parent
+ cameraUrl: OutputDevice.activeCameraUrl
+ visible: OutputDevice.activeCameraUrl != ""
+ }
+ }
+}
diff --git a/plugins/UM3NetworkPrinting/resources/qml/PrintCoreConfiguration.qml b/plugins/UM3NetworkPrinting/resources/qml/PrintCoreConfiguration.qml
deleted file mode 100644
index b2f4e85f9a..0000000000
--- a/plugins/UM3NetworkPrinting/resources/qml/PrintCoreConfiguration.qml
+++ /dev/null
@@ -1,93 +0,0 @@
-import QtQuick 2.2
-import QtQuick.Controls 1.4
-import QtQuick.Controls.Styles 1.4
-
-import UM 1.2 as UM
-
-
-Item
-{
- id: extruderInfo
- property var printCoreConfiguration
-
- width: Math.round(parent.width / 2)
- height: childrenRect.height
-
- Item
- {
- id: extruderCircle
- width: 30
- height: 30
-
- anchors.verticalCenter: printAndMaterialLabel.verticalCenter
- opacity:
- {
- if(printCoreConfiguration == null || printCoreConfiguration.activeMaterial == null || printCoreConfiguration.hotendID == null)
- {
- return 0.5
- }
- return 1
- }
-
- Rectangle
- {
- anchors.fill: parent
- radius: Math.round(width / 2)
- border.width: 2
- border.color: "black"
- }
-
- Label
- {
- anchors.centerIn: parent
- font: UM.Theme.getFont("default_bold")
- text: printCoreConfiguration.position + 1
- }
- }
-
- Item
- {
- id: printAndMaterialLabel
- anchors
- {
- right: parent.right
- left: extruderCircle.right
- margins: UM.Theme.getSize("default_margin").width
- }
- height: childrenRect.height
-
- Label
- {
- id: materialLabel
- text:
- {
- if(printCoreConfiguration != undefined && printCoreConfiguration.activeMaterial != undefined)
- {
- return printCoreConfiguration.activeMaterial.name
- }
- return ""
- }
- font: UM.Theme.getFont("default")
- elide: Text.ElideRight
- width: parent.width
- }
-
- Label
- {
- id: printCoreLabel
- text:
- {
- if(printCoreConfiguration != undefined && printCoreConfiguration.hotendID != undefined)
- {
- return printCoreConfiguration.hotendID
- }
- return ""
- }
- anchors.top: materialLabel.bottom
- elide: Text.ElideRight
- width: parent.width
- opacity: 0.6
- font: UM.Theme.getFont("default")
- }
- }
-}
diff --git a/plugins/UM3NetworkPrinting/resources/qml/PrintJobContextMenuItem.qml b/plugins/UM3NetworkPrinting/resources/qml/PrintJobContextMenuItem.qml
new file mode 100644
index 0000000000..ff5635e45d
--- /dev/null
+++ b/plugins/UM3NetworkPrinting/resources/qml/PrintJobContextMenuItem.qml
@@ -0,0 +1,24 @@
+// Copyright (c) 2018 Ultimaker B.V.
+// Cura is released under the terms of the LGPLv3 or higher.
+
+import QtQuick 2.2
+import QtQuick.Controls 2.0
+import QtQuick.Controls.Styles 1.4
+import UM 1.3 as UM
+
+Button {
+ background: Rectangle {
+ opacity: parent.down || parent.hovered ? 1 : 0;
+ color: UM.Theme.getColor("monitor_context_menu_hover")
+ }
+ contentItem: Label {
+ color: enabled ? UM.Theme.getColor("monitor_text_primary") : UM.Theme.getColor("monitor_text_disabled");
+ 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/PrintJobInfoBlock.qml b/plugins/UM3NetworkPrinting/resources/qml/PrintJobInfoBlock.qml
deleted file mode 100644
index cfadabad5c..0000000000
--- a/plugins/UM3NetworkPrinting/resources/qml/PrintJobInfoBlock.qml
+++ /dev/null
@@ -1,429 +0,0 @@
-import QtQuick 2.2
-import QtQuick.Dialogs 1.1
-import QtQuick.Controls 2.0
-import QtQuick.Controls.Styles 1.4
-import QtGraphicalEffects 1.0
-
-import UM 1.3 as UM
-
-
-Item
-{
- id: base
- property var printJob: null
- property var shadowRadius: 5 * screenScaleFactor
- function getPrettyTime(time)
- {
- return OutputDevice.formatDuration(time)
- }
-
- width: parent.width
-
- UM.I18nCatalog
- {
- id: catalog
- name: "cura"
- }
-
- Rectangle
- {
- id: background
- anchors
- {
- top: parent.top
- topMargin: 3 * screenScaleFactor
- left: parent.left
- leftMargin: base.shadowRadius
- rightMargin: base.shadowRadius
- right: parent.right
- bottom: parent.bottom
- bottomMargin: base.shadowRadius
- }
-
- layer.enabled: true
- layer.effect: DropShadow
- {
- radius: base.shadowRadius
- verticalOffset: 2 * screenScaleFactor
- color: "#3F000000" // 25% shadow
- }
-
- Item
- {
- // Content on the left of the infobox
- anchors
- {
- top: parent.top
- bottom: parent.bottom
- left: parent.left
- right: parent.horizontalCenter
- margins: UM.Theme.getSize("wide_margin").width
- rightMargin: UM.Theme.getSize("default_margin").width
- }
-
- Label
- {
- id: printJobName
- text: printJob.name
- font: UM.Theme.getFont("default_bold")
- width: parent.width
- elide: Text.ElideRight
- }
-
- Label
- {
- id: ownerName
- anchors.top: printJobName.bottom
- text: printJob.owner
- font: UM.Theme.getFont("default")
- opacity: 0.6
- width: parent.width
- elide: Text.ElideRight
- }
-
- Image
- {
- id: printJobPreview
- source: printJob.previewImageUrl
- anchors.top: ownerName.bottom
- anchors.horizontalCenter: parent.horizontalCenter
- anchors.bottom: totalTimeLabel.bottom
- width: height
- opacity: printJob.state == "error" ? 0.5 : 1.0
- }
-
- UM.RecolorImage
- {
- id: statusImage
- anchors.centerIn: printJobPreview
- source: printJob.state == "error" ? "../svg/aborted-icon.svg" : ""
- visible: source != ""
- width: 0.5 * printJobPreview.width
- height: 0.5 * printJobPreview.height
- sourceSize.width: width
- sourceSize.height: height
- color: "black"
- }
-
- Label
- {
- id: totalTimeLabel
- anchors.bottom: parent.bottom
- anchors.right: parent.right
- font: UM.Theme.getFont("default")
- text: printJob != null ? getPrettyTime(printJob.timeTotal) : ""
- elide: Text.ElideRight
- }
- }
-
- Item
- {
- // Content on the right side of the infobox.
- anchors
- {
- top: parent.top
- bottom: parent.bottom
- left: parent.horizontalCenter
- right: parent.right
- margins: 2 * UM.Theme.getSize("default_margin").width
- leftMargin: UM.Theme.getSize("default_margin").width
- rightMargin: UM.Theme.getSize("default_margin").width / 2
- }
-
- Label
- {
- id: targetPrinterLabel
- elide: Text.ElideRight
- font: UM.Theme.getFont("default_bold")
- text:
- {
- if(printJob.assignedPrinter == null)
- {
- if(printJob.state == "error")
- {
- return catalog.i18nc("@label", "Waiting for: Unavailable printer")
- }
- return catalog.i18nc("@label", "Waiting for: First available")
- }
- else
- {
- return catalog.i18nc("@label", "Waiting for: ") + printJob.assignedPrinter.name
- }
-
- }
-
- anchors
- {
- left: parent.left
- right: contextButton.left
- rightMargin: UM.Theme.getSize("default_margin").width
- }
- }
-
-
- function switchPopupState()
- {
- popup.visible ? popup.close() : popup.open()
- }
-
- Button
- {
- id: contextButton
- text: "\u22EE" //Unicode; Three stacked points.
- width: 35
- height: width
- anchors
- {
- right: parent.right
- top: parent.top
- }
- hoverEnabled: true
-
- background: Rectangle
- {
- opacity: contextButton.down || contextButton.hovered ? 1 : 0
- width: contextButton.width
- height: contextButton.height
- radius: 0.5 * width
- color: UM.Theme.getColor("viewport_background")
- }
- contentItem: Label
- {
- text: contextButton.text
- color: UM.Theme.getColor("monitor_text_inactive")
- font.pixelSize: 25
- verticalAlignment: Text.AlignVCenter
- horizontalAlignment: Text.AlignHCenter
- }
-
- onClicked: parent.switchPopupState()
- }
-
- Popup
- {
- // TODO Change once updating to Qt5.10 - The 'opened' property is in 5.10 but the behavior is now implemented with the visible property
- id: popup
- clip: true
- closePolicy: Popup.CloseOnPressOutside
- x: (parent.width - width) + 26 * screenScaleFactor
- y: contextButton.height - 5 * screenScaleFactor // Because shadow
- width: 182 * screenScaleFactor
- height: contentItem.height + 2 * padding
- visible: false
- padding: 5 * screenScaleFactor // Because shadow
-
- transformOrigin: Popup.Top
- contentItem: Item
- {
- width: popup.width
- height: childrenRect.height + 36 * screenScaleFactor
- anchors.topMargin: 10 * screenScaleFactor
- anchors.bottomMargin: 10 * screenScaleFactor
- Button
- {
- id: sendToTopButton
- text: catalog.i18nc("@label", "Move to top")
- onClicked:
- {
- sendToTopConfirmationDialog.visible = true;
- popup.close();
- }
- width: parent.width
- enabled: OutputDevice.queuedPrintJobs[0].key != printJob.key
- visible: enabled
- anchors.top: parent.top
- anchors.topMargin: 18 * screenScaleFactor
- height: visible ? 39 * screenScaleFactor : 0 * screenScaleFactor
- hoverEnabled: true
- background: Rectangle
- {
- opacity: sendToTopButton.down || sendToTopButton.hovered ? 1 : 0
- color: UM.Theme.getColor("viewport_background")
- }
- contentItem: Label
- {
- text: sendToTopButton.text
- horizontalAlignment: Text.AlignLeft
- verticalAlignment: Text.AlignVCenter
- }
- }
-
- MessageDialog
- {
- id: sendToTopConfirmationDialog
- title: catalog.i18nc("@window:title", "Move print job to top")
- icon: StandardIcon.Warning
- text: catalog.i18nc("@label %1 is the name of a print job.", "Are you sure you want to move %1 to the top of the queue?").arg(printJob.name)
- standardButtons: StandardButton.Yes | StandardButton.No
- Component.onCompleted: visible = false
- onYes: OutputDevice.sendJobToTop(printJob.key)
- }
-
- Button
- {
- id: deleteButton
- text: catalog.i18nc("@label", "Delete")
- onClicked:
- {
- deleteConfirmationDialog.visible = true;
- popup.close();
- }
- width: parent.width
- height: 39 * screenScaleFactor
- anchors.top: sendToTopButton.bottom
- hoverEnabled: true
- background: Rectangle
- {
- opacity: deleteButton.down || deleteButton.hovered ? 1 : 0
- color: UM.Theme.getColor("viewport_background")
- }
- contentItem: Label
- {
- text: deleteButton.text
- horizontalAlignment: Text.AlignLeft
- verticalAlignment: Text.AlignVCenter
- }
- }
-
- MessageDialog
- {
- id: deleteConfirmationDialog
- title: catalog.i18nc("@window:title", "Delete print job")
- icon: StandardIcon.Warning
- text: catalog.i18nc("@label %1 is the name of a print job.", "Are you sure you want to delete %1?").arg(printJob.name)
- standardButtons: StandardButton.Yes | StandardButton.No
- Component.onCompleted: visible = false
- onYes: OutputDevice.deleteJobFromQueue(printJob.key)
- }
- }
-
- background: Item
- {
- width: popup.width
- height: popup.height
-
- DropShadow
- {
- anchors.fill: pointedRectangle
- radius: 5
- color: "#3F000000" // 25% shadow
- source: pointedRectangle
- transparentBorder: true
- verticalOffset: 2
- }
-
- Item
- {
- id: pointedRectangle
- width: parent.width - 10 * screenScaleFactor // Because of the shadow
- height: parent.height - 10 * screenScaleFactor // Because of the shadow
- anchors.horizontalCenter: parent.horizontalCenter
- anchors.verticalCenter: parent.verticalCenter
-
- Rectangle
- {
- id: point
- height: 14 * screenScaleFactor
- width: 14 * screenScaleFactor
- color: UM.Theme.getColor("setting_control")
- transform: Rotation { angle: 45}
- anchors.right: bloop.right
- anchors.rightMargin: 24
- y: 1
- }
-
- Rectangle
- {
- id: bloop
- color: UM.Theme.getColor("setting_control")
- width: parent.width
- anchors.top: parent.top
- anchors.topMargin: 8 * screenScaleFactor // Because of the shadow + point
- anchors.bottom: parent.bottom
- anchors.bottomMargin: 8 * screenScaleFactor // Because of the shadow
- }
- }
- }
-
- exit: Transition
- {
- // This applies a default NumberAnimation to any changes a state change makes to x or y properties
- NumberAnimation { property: "visible"; duration: 75; }
- }
- enter: Transition
- {
- // This applies a default NumberAnimation to any changes a state change makes to x or y properties
- NumberAnimation { property: "visible"; duration: 75; }
- }
-
- onClosed: visible = false
- onOpened: visible = true
- }
-
- Row
- {
- id: printerFamilyPills
- spacing: 0.5 * UM.Theme.getSize("default_margin").width
- anchors
- {
- left: parent.left
- right: parent.right
- bottom: extrudersInfo.top
- bottomMargin: UM.Theme.getSize("default_margin").height
- }
- height: childrenRect.height
- Repeater
- {
- model: printJob.compatibleMachineFamilies
-
- delegate: PrinterFamilyPill
- {
- text: modelData
- color: UM.Theme.getColor("viewport_background")
- padding: 3 * screenScaleFactor
- }
- }
- }
- // PrintCore && Material config
- Row
- {
- id: extrudersInfo
- anchors.bottom: parent.bottom
-
- anchors
- {
- left: parent.left
- right: parent.right
- }
- height: childrenRect.height
-
- spacing: UM.Theme.getSize("default_margin").width
-
- PrintCoreConfiguration
- {
- id: leftExtruderInfo
- width: Math.round(parent.width / 2) * screenScaleFactor
- printCoreConfiguration: printJob.configuration.extruderConfigurations[0]
- }
-
- PrintCoreConfiguration
- {
- id: rightExtruderInfo
- width: Math.round(parent.width / 2) * screenScaleFactor
- printCoreConfiguration: printJob.configuration.extruderConfigurations[1]
- }
- }
-
- }
-
- Rectangle
- {
- color: UM.Theme.getColor("viewport_background")
- width: 2 * screenScaleFactor
- anchors.top: parent.top
- anchors.bottom: parent.bottom
- anchors.margins: UM.Theme.getSize("default_margin").height
- anchors.horizontalCenter: parent.horizontalCenter
- }
- }
-}
\ No newline at end of file
diff --git a/plugins/UM3NetworkPrinting/resources/qml/PrintWindow.qml b/plugins/UM3NetworkPrinting/resources/qml/PrintWindow.qml
index 9793b218fc..548e5ce1ea 100644
--- a/plugins/UM3NetworkPrinting/resources/qml/PrintWindow.qml
+++ b/plugins/UM3NetworkPrinting/resources/qml/PrintWindow.qml
@@ -4,112 +4,101 @@
import QtQuick 2.2
import QtQuick.Window 2.2
import QtQuick.Controls 1.2
-
import UM 1.1 as UM
-UM.Dialog
-{
+UM.Dialog {
id: base;
-
- minimumWidth: 500 * screenScaleFactor
- minimumHeight: 140 * screenScaleFactor
- maximumWidth: minimumWidth
- maximumHeight: minimumHeight
- width: minimumWidth
- height: minimumHeight
-
- visible: true
- modality: Qt.ApplicationModal
- onVisibleChanged:
- {
- if(visible)
- {
- resetPrintersModel()
- }
- else
- {
- OutputDevice.cancelPrintSelection()
- }
- }
- title: catalog.i18nc("@title:window", "Print over network")
-
- property var printersModel: ListModel{}
- 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})
- }
- }
-
- Column
- {
- id: printerSelection
- anchors.fill: parent
- anchors.top: parent.top
- anchors.topMargin: UM.Theme.getSize("default_margin").height
- anchors.leftMargin: UM.Theme.getSize("default_margin").width
- anchors.rightMargin: UM.Theme.getSize("default_margin").width
- height: 50 * screenScaleFactor
- Label
- {
- id: manualPrinterSelectionLabel
- anchors
- {
- left: parent.left
- topMargin: UM.Theme.getSize("default_margin").height
- right: parent.right
- }
- text: catalog.i18nc("@label", "Printer selection")
- wrapMode: Text.Wrap
- height: 20 * screenScaleFactor
- }
-
- ComboBox
- {
- id: printerSelectionCombobox
- model: base.printersModel
- textRole: "name"
-
- width: parent.width
- height: 40 * screenScaleFactor
- Behavior on height { NumberAnimation { duration: 100 } }
- }
-
- SystemPalette
- {
- id: palette
- }
-
- UM.I18nCatalog { id: catalog; name: "cura"; }
- }
-
+ height: minimumHeight;
leftButtons: [
- Button
- {
- text: catalog.i18nc("@action:button","Cancel")
- enabled: true
+ Button {
+ enabled: true;
onClicked: {
base.visible = false;
- printerSelectionCombobox.currentIndex = 0
- OutputDevice.cancelPrintSelection()
+ 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();
+ }
+ }
rightButtons: [
- Button
- {
- text: catalog.i18nc("@action:button","Print")
- enabled: true
+ Button {
+ enabled: true;
onClicked: {
base.visible = false;
- OutputDevice.selectPrinter(printerSelectionCombobox.model.get(printerSelectionCombobox.currentIndex).key)
+ OutputDevice.selectPrinter(printerSelectionCombobox.model.get(printerSelectionCombobox.currentIndex).key);
// reset to defaults
- printerSelectionCombobox.currentIndex = 0
+ printerSelectionCombobox.currentIndex = 0;
}
+ text: catalog.i18nc("@action:button","Print");
}
]
+ title: catalog.i18nc("@title:window", "Print over network");
+ visible: true;
+ width: minimumWidth;
+
+ Column {
+ id: printerSelection;
+ anchors {
+ fill: parent;
+ leftMargin: UM.Theme.getSize("default_margin").width;
+ rightMargin: UM.Theme.getSize("default_margin").width;
+ top: parent.top;
+ topMargin: UM.Theme.getSize("default_margin").height;
+ }
+ height: 50 * screenScaleFactor;
+
+ SystemPalette {
+ id: palette;
+ }
+
+ UM.I18nCatalog {
+ id: catalog;
+ name: "cura";
+ }
+
+ Label {
+ id: manualPrinterSelectionLabel;
+ anchors {
+ left: parent.left;
+ right: parent.right;
+ topMargin: UM.Theme.getSize("default_margin").height;
+ }
+ height: 20 * screenScaleFactor;
+ text: catalog.i18nc("@label", "Printer selection");
+ wrapMode: Text.Wrap;
+ renderType: Text.NativeRendering;
+ }
+
+ ComboBox {
+ id: printerSelectionCombobox;
+ Behavior on height { NumberAnimation { duration: 100 } }
+ height: 40 * screenScaleFactor;
+ model: ListModel {
+ id: printersModel;
+ }
+ 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/PrinterFamilyPill.qml b/plugins/UM3NetworkPrinting/resources/qml/PrinterFamilyPill.qml
deleted file mode 100644
index b785cd02b7..0000000000
--- a/plugins/UM3NetworkPrinting/resources/qml/PrinterFamilyPill.qml
+++ /dev/null
@@ -1,28 +0,0 @@
-import QtQuick 2.2
-import QtQuick.Controls 1.4
-import UM 1.2 as UM
-
-Item
-{
- property alias color: background.color
- property alias text: familyNameLabel.text
- property var padding: 0
- implicitHeight: familyNameLabel.contentHeight + 2 * padding // Apply the padding to top and bottom.
- implicitWidth: familyNameLabel.contentWidth + implicitHeight // The extra height is added to ensure the radius doesn't cut something off.
- Rectangle
- {
- id: background
- height: parent.height
- width: parent.width
- color: parent.color
- anchors.right: parent.right
- anchors.horizontalCenter: parent.horizontalCenter
- radius: 0.5 * height
- }
- Label
- {
- id: familyNameLabel
- anchors.centerIn: parent
- text: ""
- }
-}
\ No newline at end of file
diff --git a/plugins/UM3NetworkPrinting/resources/qml/PrinterVideoStream.qml b/plugins/UM3NetworkPrinting/resources/qml/PrinterVideoStream.qml
index d0213a4571..77b481f6d8 100644
--- a/plugins/UM3NetworkPrinting/resources/qml/PrinterVideoStream.qml
+++ b/plugins/UM3NetworkPrinting/resources/qml/PrinterVideoStream.qml
@@ -1,84 +1,65 @@
+// 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.4
import QtQuick.Controls.Styles 1.4
-
import UM 1.3 as UM
+import Cura 1.0 as Cura
+Item {
+ property var cameraUrl: "";
-Item
-{
- property var camera: null
-
- Rectangle
- {
- anchors.fill:parent
- color: UM.Theme.getColor("viewport_overlay")
- opacity: 0.5
+ Rectangle {
+ anchors.fill:parent;
+ color: UM.Theme.getColor("viewport_overlay");
+ opacity: 0.5;
}
- MouseArea
- {
- anchors.fill: parent
- onClicked: OutputDevice.setActiveCamera(null)
- z: 0
+ MouseArea {
+ anchors.fill: parent;
+ onClicked: OutputDevice.setActiveCameraUrl("");
+ z: 0;
}
- CameraButton
- {
- id: closeCameraButton
- iconSource: UM.Theme.getIcon("cross1")
- anchors
- {
- top: cameraImage.top
- topMargin: UM.Theme.getSize("default_margin").height
+ CameraButton {
+ id: closeCameraButton;
+ anchors {
right: cameraImage.right
rightMargin: UM.Theme.getSize("default_margin").width
+ top: cameraImage.top
+ topMargin: UM.Theme.getSize("default_margin").height
}
- z: 999
+ iconSource: UM.Theme.getIcon("cross1");
+ z: 999;
}
- Image
- {
+ Cura.NetworkMJPGImage {
id: cameraImage
- width: Math.min(sourceSize.width === 0 ? 800 * screenScaleFactor : sourceSize.width, maximumWidth)
- height: Math.round((sourceSize.height === 0 ? 600 * screenScaleFactor : sourceSize.height) * width / sourceSize.width)
- anchors.horizontalCenter: parent.horizontalCenter
- anchors.verticalCenter: parent.verticalCenter
+ anchors.horizontalCenter: parent.horizontalCenter;
+ anchors.verticalCenter: parent.verticalCenter;
+ height: Math.round((imageHeight === 0 ? 600 * screenScaleFactor : imageHeight) * width / imageWidth);
+ onVisibleChanged: {
+ if (visible) {
+ if (cameraUrl != "") {
+ start();
+ }
+ } else {
+ if (cameraUrl != "") {
+ stop();
+ }
+ }
+ }
+ source: cameraUrl
+ width: Math.min(imageWidth === 0 ? 800 * screenScaleFactor : imageWidth, maximumWidth);
z: 1
- onVisibleChanged:
- {
- if(visible)
- {
- if(camera != null)
- {
- camera.start()
- }
- } else
- {
- if(camera != null)
- {
- camera.stop()
- }
- }
- }
-
- source:
- {
- if(camera != null && camera.latestImage != null)
- {
- return camera.latestImage;
- }
- return "";
- }
}
- MouseArea
- {
- anchors.fill: cameraImage
- onClicked:
- {
- OutputDevice.setActiveCamera(null)
+ MouseArea {
+ anchors.fill: cameraImage;
+ onClicked: {
+ OutputDevice.setActiveCameraUrl("");
}
- z: 1
+ z: 1;
}
}
diff --git a/plugins/UM3NetworkPrinting/resources/qml/UM3InfoComponents.qml b/plugins/UM3NetworkPrinting/resources/qml/UM3InfoComponents.qml
index a19d1be60d..c99ed1688e 100644
--- a/plugins/UM3NetworkPrinting/resources/qml/UM3InfoComponents.qml
+++ b/plugins/UM3NetworkPrinting/resources/qml/UM3InfoComponents.qml
@@ -1,125 +1,93 @@
-import UM 1.2 as UM
-import Cura 1.0 as Cura
+// 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: printerConnected && Cura.MachineManager.printerOutputDevices[0].acceptsCommands
- property bool authenticationRequested: printerConnected && (Cura.MachineManager.printerOutputDevices[0].authenticationState == 2 || Cura.MachineManager.printerOutputDevices[0].authenticationState == 5) // AuthState.AuthenticationRequested or AuthenticationReceived.
-
- Row
+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:
{
- objectName: "networkPrinterConnectButton"
- visible: isUM3
- spacing: UM.Theme.getSize("default_margin").width
-
- Button
+ if (printerConnected && Cura.MachineManager.printerOutputDevices[0])
{
- height: UM.Theme.getSize("save_button_save_to_button").height
- tooltip: catalog.i18nc("@info:tooltip", "Send access request to the printer")
- text: catalog.i18nc("@action:button", "Request Access")
- style: UM.Theme.styles.sidebar_action_button
- onClicked: Cura.MachineManager.printerOutputDevices[0].requestAuthentication()
- visible: printerConnected && !printerAcceptsCommands && !authenticationRequested
+ 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
- tooltip: catalog.i18nc("@info:tooltip", "Connect to a printer")
- text: catalog.i18nc("@action:button", "Connect")
- style: UM.Theme.styles.sidebar_action_button
- onClicked: connectActionDialog.show()
- visible: !printerConnected
+ 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
- Loader
- {
- anchors.fill: parent
- source: "DiscoverUM3Action.qml"
+ UM.Dialog {
+ id: connectActionDialog;
+ rightButtons: Button {
+ iconName: "dialog-close";
+ onClicked: connectActionDialog.reject();
+ text: catalog.i18nc("@action:button", "Close");
}
- rightButtons: Button
- {
- text: catalog.i18nc("@action:button", "Close")
- iconName: "dialog-close"
- onClicked: connectActionDialog.reject()
+
+ Loader {
+ anchors.fill: parent;
+ source: "DiscoverUM3Action.qml";
}
}
-
-
- Column
- {
- objectName: "networkPrinterConnectionInfo"
- visible: isUM3
- spacing: UM.Theme.getSize("default_margin").width
- anchors.fill: parent
-
- Button
- {
- tooltip: catalog.i18nc("@info:tooltip", "Send access request to the printer")
- text: catalog.i18nc("@action:button", "Request Access")
- onClicked: Cura.MachineManager.printerOutputDevices[0].requestAuthentication()
- visible: printerConnected && !printerAcceptsCommands && !authenticationRequested
- }
-
- Row
- {
- visible: printerConnected
- spacing: UM.Theme.getSize("default_margin").width
-
- anchors.left: parent.left
- anchors.right: parent.right
- height: childrenRect.height
-
- Column
- {
- Repeater
- {
- model: Cura.ExtrudersModel { simpleNames: true }
- Label { text: model.name }
- }
- }
- Column
- {
- Repeater
- {
- id: nozzleColumn
- model: printerConnected ? Cura.MachineManager.printerOutputDevices[0].hotendIds : null
- Label { text: nozzleColumn.model[index] }
- }
- }
- Column
- {
- Repeater
- {
- id: materialColumn
- model: printerConnected ? Cura.MachineManager.printerOutputDevices[0].materialNames : null
- Label { text: materialColumn.model[index] }
- }
- }
- }
-
- Button
- {
- tooltip: catalog.i18nc("@info:tooltip", "Load the configuration of the printer into Cura")
- text: catalog.i18nc("@action:button", "Activate Configuration")
- visible: false // printerConnected && !isClusterPrinter()
- onClicked: manager.loadConfigurationFromPrinter()
- }
- }
-
- UM.I18nCatalog{id: catalog; name:"cura"}
}
diff --git a/plugins/UM3NetworkPrinting/resources/svg/cloud-flow-completed.svg b/plugins/UM3NetworkPrinting/resources/svg/cloud-flow-completed.svg
new file mode 100644
index 0000000000..8eba62ecc8
--- /dev/null
+++ b/plugins/UM3NetworkPrinting/resources/svg/cloud-flow-completed.svg
@@ -0,0 +1,27 @@
+
+
\ No newline at end of file
diff --git a/plugins/UM3NetworkPrinting/resources/svg/cloud-flow-start.svg b/plugins/UM3NetworkPrinting/resources/svg/cloud-flow-start.svg
new file mode 100644
index 0000000000..746dc269fd
--- /dev/null
+++ b/plugins/UM3NetworkPrinting/resources/svg/cloud-flow-start.svg
@@ -0,0 +1,13 @@
+
+
\ No newline at end of file
diff --git a/plugins/UM3NetworkPrinting/resources/svg/icons/buildplate.svg b/plugins/UM3NetworkPrinting/resources/svg/icons/buildplate.svg
new file mode 100644
index 0000000000..bcb278a8ca
--- /dev/null
+++ b/plugins/UM3NetworkPrinting/resources/svg/icons/buildplate.svg
@@ -0,0 +1,5 @@
+
\ No newline at end of file
diff --git a/plugins/UM3NetworkPrinting/resources/svg/icons/camera.svg b/plugins/UM3NetworkPrinting/resources/svg/icons/camera.svg
new file mode 100644
index 0000000000..2eaebb812d
--- /dev/null
+++ b/plugins/UM3NetworkPrinting/resources/svg/icons/camera.svg
@@ -0,0 +1,5 @@
+
\ No newline at end of file
diff --git a/plugins/UM3NetworkPrinting/resources/svg/icons/extruder.svg b/plugins/UM3NetworkPrinting/resources/svg/icons/extruder.svg
new file mode 100644
index 0000000000..235cb432e9
--- /dev/null
+++ b/plugins/UM3NetworkPrinting/resources/svg/icons/extruder.svg
@@ -0,0 +1,5 @@
+
\ No newline at end of file
diff --git a/plugins/UM3NetworkPrinting/resources/svg/ultibot.svg b/plugins/UM3NetworkPrinting/resources/svg/ultibot.svg
new file mode 100644
index 0000000000..be6ca64723
--- /dev/null
+++ b/plugins/UM3NetworkPrinting/resources/svg/ultibot.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/plugins/UM3NetworkPrinting/resources/svg/warning-icon.svg b/plugins/UM3NetworkPrinting/resources/svg/warning-icon.svg
index 1e5359a5eb..064d0783e0 100644
--- a/plugins/UM3NetworkPrinting/resources/svg/warning-icon.svg
+++ b/plugins/UM3NetworkPrinting/resources/svg/warning-icon.svg
@@ -1 +1,4 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/plugins/UM3NetworkPrinting/src/Cloud/CloudApiClient.py b/plugins/UM3NetworkPrinting/src/Cloud/CloudApiClient.py
new file mode 100644
index 0000000000..30bdd8e774
--- /dev/null
+++ b/plugins/UM3NetworkPrinting/src/Cloud/CloudApiClient.py
@@ -0,0 +1,186 @@
+# Copyright (c) 2018 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+import json
+from json import JSONDecodeError
+from time import time
+from typing import Callable, List, Type, TypeVar, Union, Optional, Tuple, Dict, Any, cast
+
+from PyQt5.QtCore import QUrl
+from PyQt5.QtNetwork import QNetworkRequest, QNetworkReply, QNetworkAccessManager
+
+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
+
+
+## The generic type variable used to document the methods below.
+CloudApiClientModel = TypeVar("CloudApiClientModel", bound = BaseModel)
+
+
+## The cloud API client is responsible for handling the requests and responses from the cloud.
+# Each method should only handle models instead of exposing Any HTTP details.
+class CloudApiClient:
+
+ # The cloud URL to use for this remote cluster.
+ ROOT_PATH = UltimakerCloudAuthentication.CuraCloudAPIRoot
+ CLUSTER_API_ROOT = "{}/connect/v1".format(ROOT_PATH)
+ CURA_API_ROOT = "{}/cura/v1".format(ROOT_PATH)
+
+ ## 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.
+ def __init__(self, account: Account, on_error: Callable[[List[CloudError]], None]) -> None:
+ super().__init__()
+ self._manager = QNetworkAccessManager()
+ 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
+ def account(self) -> Account:
+ return self._account
+
+ ## 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)
+ reply = self._manager.get(self._createEmptyRequest(url))
+ self._addCallback(reply, on_finished, CloudClusterResponse)
+
+ ## Retrieves the status of the given cluster.
+ # \param cluster_id: The ID of the cluster.
+ # \param on_finished: The function to be called after the result is parsed.
+ def getClusterStatus(self, cluster_id: str, on_finished: Callable[[CloudClusterStatus], Any]) -> None:
+ url = "{}/clusters/{}/status".format(self.CLUSTER_API_ROOT, cluster_id)
+ reply = self._manager.get(self._createEmptyRequest(url))
+ self._addCallback(reply, on_finished, CloudClusterStatus)
+
+ ## 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:
+ url = "{}/jobs/upload".format(self.CURA_API_ROOT)
+ body = json.dumps({"data": request.toDict()})
+ reply = self._manager.put(self._createEmptyRequest(url), body.encode())
+ self._addCallback(reply, on_finished, CloudPrintJobResponse)
+
+ ## Uploads a print job tool path to the cloud.
+ # \param print_job: The object received after requesting an upload with `self.requestUpload`.
+ # \param mesh: The tool path data to be uploaded.
+ # \param on_finished: The function to be called after the upload is successful.
+ # \param on_progress: A function to be called during upload progress. It receives a percentage (0-100).
+ # \param on_error: A function to be called if the upload fails.
+ def uploadToolPath(self, print_job: CloudPrintJobResponse, mesh: bytes, on_finished: Callable[[], Any],
+ on_progress: Callable[[int], Any], on_error: Callable[[], Any]):
+ self._upload = ToolPathUploader(self._manager, print_job, mesh, on_finished, on_progress, on_error)
+ self._upload.start()
+
+ # Requests a cluster to print the given print job.
+ # \param cluster_id: The ID of the cluster.
+ # \param job_id: The ID of the print job.
+ # \param on_finished: The function to be called after the result is parsed.
+ def requestPrint(self, cluster_id: str, job_id: str, on_finished: Callable[[CloudPrintResponse], Any]) -> None:
+ url = "{}/clusters/{}/print/{}".format(self.CLUSTER_API_ROOT, cluster_id, job_id)
+ 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 = b""
+ if data:
+ try:
+ body = json.dumps({"data": data}).encode()
+ except JSONDecodeError as err:
+ Logger.log("w", "Could not encode body: %s", err)
+ return
+ 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.
+ def _createEmptyRequest(self, path: str, content_type: Optional[str] = "application/json") -> QNetworkRequest:
+ request = QNetworkRequest(QUrl(path))
+ if content_type:
+ request.setHeader(QNetworkRequest.ContentTypeHeader, content_type)
+ access_token = self._account.accessToken
+ if access_token:
+ request.setRawHeader(b"Authorization", "Bearer {}".format(access_token).encode())
+ 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:
+ error = CloudError(code=type(err).__name__, title=str(err), http_code=str(status_code),
+ id=str(time()), http_status="500")
+ Logger.logException("e", "Could not parse the stardust response: %s", error.toDict())
+ return status_code, {"errors": [error.toDict()]}
+
+ ## 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[[CloudApiClientModel], Any],
+ Callable[[List[CloudApiClientModel]], Any]],
+ model_class: Type[CloudApiClientModel]) -> None:
+ if "data" in response:
+ data = response["data"]
+ if isinstance(data, list):
+ results = [model_class(**c) for c in data] # type: List[CloudApiClientModel]
+ on_finished_list = cast(Callable[[List[CloudApiClientModel]], Any], on_finished)
+ on_finished_list(results)
+ else:
+ result = model_class(**data) # type: CloudApiClientModel
+ on_finished_item = cast(Callable[[CloudApiClientModel], Any], on_finished)
+ on_finished_item(result)
+ elif "errors" in response:
+ self._on_error([CloudError(**error) for error in response["errors"]])
+ else:
+ Logger.log("e", "Cannot find data or errors in the cloud response: %s", 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. Depending on the endpoint it will be either
+ # a list or a single item.
+ # \param model: The type of the model to convert the response to.
+ def _addCallback(self,
+ reply: QNetworkReply,
+ on_finished: Union[Callable[[CloudApiClientModel], Any],
+ Callable[[List[CloudApiClientModel]], Any]],
+ model: Type[CloudApiClientModel],
+ ) -> None:
+ def parse() -> None:
+ # 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._anti_gc_callbacks.remove(parse)
+ self._parseModels(response, on_finished, model)
+ return
+
+ 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
new file mode 100644
index 0000000000..8c09483990
--- /dev/null
+++ b/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputController.py
@@ -0,0 +1,26 @@
+# Copyright (c) 2018 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 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 = 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/Cloud/CloudOutputDevice.py b/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py
new file mode 100644
index 0000000000..fc2cdae563
--- /dev/null
+++ b/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py
@@ -0,0 +1,479 @@
+# Copyright (c) 2018 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 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.Models.PrinterOutputModel import PrinterOutputModel
+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 formatDateCompleted, formatTimeCompleted
+
+I18N_CATALOG = i18nCatalog("cura")
+
+
+## The cloud output device is a network output device that works remotely but has limited functionality.
+# 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):
+ # The interval with which the remote clusters are checked
+ CHECK_CLUSTER_INTERVAL = 10.0 # seconds
+
+ # The minimum version of firmware that support print job actions over cloud.
+ PRINT_JOB_ACTIONS_MIN_VERSION = Version("5.3.0")
+
+ # Signal triggered when the print jobs in the queue were changed.
+ printJobsChanged = pyqtSignal()
+
+ # Signal triggered when the selected printer in the UI should be changed.
+ 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()
+
+ ## Creates a new cloud output device
+ # \param api_client: The client that will run the API calls
+ # \param cluster: The device response received from the cloud API.
+ # \param parent: The optional parent of this output device.
+ def __init__(self, api_client: CloudApiClient, cluster: CloudClusterResponse, parent: QObject = None) -> None:
+
+ # The following properties are expected on each networked output device.
+ # 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": 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": 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
+
+ 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:
+ plugin_path = PluginRegistry.getInstance().getPluginPath("UM3NetworkPrinting")
+ if plugin_path is None:
+ Logger.log("e", "Cloud not find plugin path for plugin UM3NetworkPrnting")
+ raise RuntimeError("Cloud not find plugin path for plugin UM3NetworkPrnting")
+ self._monitor_view_qml_path = os.path.join(plugin_path, "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()
+
+ # 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]
+
+ # Reference to the uploaded print job / mesh
+ self._tool_path = None # type: Optional[bytes]
+ self._uploaded_print_job = None # type: Optional[CloudPrintJobResponse]
+
+ ## Connects this device.
+ def connect(self) -> None:
+ if self.isConnected():
+ return
+ super().connect()
+ Logger.log("i", "Connected to cluster %s", self.key)
+ CuraApplication.getInstance().getBackend().backendStateChange.connect(self._onBackendStateChange)
+
+ ## Disconnects the device
+ def disconnect(self) -> None:
+ super().disconnect()
+ Logger.log("i", "Disconnected from cluster %s", self.key)
+ CuraApplication.getInstance().getBackend().backendStateChange.disconnect(self._onBackendStateChange)
+
+ ## Resets the print job that was uploaded to force a new upload, runs whenever the user re-slices.
+ def _onBackendStateChange(self, _: BackendState) -> None:
+ self._tool_path = None
+ self._uploaded_print_job = None
+
+ ## Gets the cluster response from which this device was created.
+ @property
+ def clusterData(self) -> CloudClusterResponse:
+ return self._cluster
+
+ ## Updates the cluster data from the cloud.
+ @clusterData.setter
+ 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:
+ # Typically, a network key looks like "ultimakersystem-aabbccdd0011._ultimaker._tcp.local."
+ # the host name should then be "ultimakersystem-aabbccdd0011"
+ if network_key.startswith(self.clusterData.host_name):
+ 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
+ if self.clusterData.host_internal_ip is not None and network_key.find(self.clusterData.host_internal_ip):
+ 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.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, filter_by_machine: bool = False, **kwargs) -> 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 remote_printers: The printers received from the cloud.
+ def _updatePrinters(self, remote_printers: List[CloudClusterPrinterStatus]) -> None:
+
+ # 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 = []
+
+ # 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 not printer:
+ new_printers.append(printer_data.createOutputModel(CloudOutputController(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
+ if self._printers and not self.activePrinter:
+ self.setActivePrinter(self._printers[0])
+
+ self.printersChanged.emit()
+
+ ## Updates the local list of print jobs with the list received from the cloud.
+ # \param remote_jobs: The print jobs received from the cloud.
+ def _updatePrintJobs(self, remote_jobs: List[CloudClusterPrintJobStatus]) -> None:
+
+ # 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)
+ 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)
+ removed_job.stateChanged.disconnect(self._onPrintJobStateChanged)
+
+ 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: CloudClusterPrintJobStatus) -> UM3PrintJobOutputModel:
+ model = remote_job.createOutputModel(CloudOutputController(self))
+ model.stateChanged.connect(self._onPrintJobStateChanged)
+ if remote_job.printer_uuid:
+ self._updateAssignedPrinter(model, remote_job.printer_uuid)
+ return 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()
+
+ ## Whether the printer that this output device represents supports print job actions via the cloud.
+ @pyqtProperty(bool, notify=_clusterPrintersChanged)
+ 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
+
+ ## Gets the number of printers in the cluster.
+ # We use a minimum of 1 because cloud devices are always a cluster and printer discovery needs it.
+ @pyqtProperty(int, notify=_clusterPrintersChanged)
+ def clusterSize(self) -> int:
+ return max(1, len(self._printers))
+
+ ## 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()
+
+ ## 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"]
+
+ ## 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)
+ 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)
+ def deleteJobFromQueue(self, print_job_uuid: str) -> None:
+ self._api.doPrintJobAction(self._cluster.cluster_id, print_job_uuid, "remove")
+
+ @pyqtSlot(str)
+ def forceSendJob(self, print_job_uuid: str) -> None:
+ self._api.doPrintJobAction(self._cluster.cluster_id, print_job_uuid, "force")
+
+ @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)
+
+ @pyqtProperty(bool, notify=printJobsChanged)
+ def receivedPrintJobs(self) -> bool:
+ return bool(self._print_jobs)
+
+ @pyqtSlot()
+ def openPrintJobControlPanel(self) -> None:
+ QDesktopServices.openUrl(QUrl("https://mycloud.ultimaker.com"))
+
+ @pyqtSlot()
+ def openPrinterControlPanel(self) -> None:
+ QDesktopServices.openUrl(QUrl("https://mycloud.ultimaker.com"))
+
+ ## 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("QVariantList", notify=_clusterPrintersChanged)
+ def connectedPrintersTypeCount(self) -> List[Dict[str, str]]:
+ return []
diff --git a/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py b/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py
new file mode 100644
index 0000000000..ced53e347b
--- /dev/null
+++ b/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py
@@ -0,0 +1,211 @@
+# Copyright (c) 2018 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+from typing import Dict, List
+
+from PyQt5.QtCore import QTimer
+
+from UM import i18nCatalog
+from UM.Logger import Logger
+from UM.Message import Message
+from UM.Signal import Signal
+from cura.API import Account
+from cura.CuraApplication import CuraApplication
+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
+
+
+## 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"
+
+ # The interval with which the remote clusters are checked
+ CHECK_CLUSTER_INTERVAL = 30.0 # seconds
+
+ # The translation catalog for this device.
+ I18N_CATALOG = i18nCatalog("cura")
+
+ addedCloudCluster = Signal()
+ removedCloudCluster = 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)
+
+ # 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._running = False
+
+ # 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()
+ else:
+ if self._update_timer.isActive():
+ self._update_timer.stop()
+
+ # Notify that all clusters have disappeared
+ self._onGetRemoteClustersFinished([])
+
+ ## 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.
+ 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]
+
+ 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 device in removed_devices:
+ if device.isConnected():
+ device.disconnect()
+ device.close()
+ self._output_device_manager.removeOutputDevice(device.key)
+ self._application.getDiscoveredPrintersModel().removeDiscoveredPrinter(device.key)
+ self.removedCloudCluster.emit(device)
+ del self._remote_clusters[device.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 cluster in added_clusters:
+ device = CloudOutputDevice(self._api, cluster)
+ self._remote_clusters[cluster.cluster_id] = device
+ self._application.getDiscoveredPrintersModel().addDiscoveredPrinter(
+ device.key,
+ device.key,
+ cluster.friendly_name,
+ self._createMachineFromDiscoveredPrinter,
+ device.printerType,
+ device
+ )
+ self.addedCloudCluster.emit(cluster)
+
+ # Update the output devices
+ for device, cluster in updates:
+ device.clusterData = cluster
+ self._application.getDiscoveredPrintersModel().updateDiscoveredPrinter(
+ device.key,
+ cluster.friendly_name,
+ device.printerType,
+ )
+
+ self._connectToActiveMachine()
+
+ def _createMachineFromDiscoveredPrinter(self, key: str) -> None:
+ device = self._remote_clusters[key] # type: CloudOutputDevice
+ if not device:
+ Logger.log("e", "Could not find discovered device with key [%s]", key)
+ return
+
+ group_name = device.clusterData.friendly_name
+ machine_type_id = device.printerType
+
+ Logger.log("i", "Creating machine from cloud device with key = [%s], group name = [%s], printer type = [%s]",
+ key, group_name, machine_type_id)
+
+ # The newly added machine is automatically activated.
+ self._application.getMachineManager().addMachine(machine_type_id, group_name)
+ active_machine = CuraApplication.getInstance().getGlobalContainerStack()
+ if not active_machine:
+ return
+
+ active_machine.setMetaDataEntry(self.META_CLUSTER_ID, device.key)
+ self._connectToOutputDevice(device, active_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.
+ 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)
+
+ ## 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)
+
+ ## 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()
+
+ ## 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)
diff --git a/plugins/UM3NetworkPrinting/src/Cloud/CloudProgressMessage.py b/plugins/UM3NetworkPrinting/src/Cloud/CloudProgressMessage.py
new file mode 100644
index 0000000000..943bef2bc1
--- /dev/null
+++ b/plugins/UM3NetworkPrinting/src/Cloud/CloudProgressMessage.py
@@ -0,0 +1,32 @@
+# Copyright (c) 2018 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")
+
+
+## Class responsible for showing a progress message while a mesh is being uploaded to the cloud.
+class CloudProgressMessage(Message):
+ def __init__(self):
+ super().__init__(
+ title = I18N_CATALOG.i18nc("@info:status", "Sending Print Job"),
+ text = I18N_CATALOG.i18nc("@info:status", "Uploading via Ultimaker Cloud"),
+ progress = -1,
+ lifetime = 0,
+ dismissable = False,
+ use_inactivity_timer = False
+ )
+
+ ## Shows the progress message.
+ def show(self):
+ self.setProgress(0)
+ super().show()
+
+ ## Updates the percentage of the uploaded.
+ # \param percentage: The percentage amount (0-100).
+ def update(self, percentage: int) -> None:
+ if not self._visible:
+ super().show()
+ self.setProgress(percentage)
diff --git a/plugins/UM3NetworkPrinting/src/Cloud/Models/BaseCloudModel.py b/plugins/UM3NetworkPrinting/src/Cloud/Models/BaseCloudModel.py
new file mode 100644
index 0000000000..18a8cb5cba
--- /dev/null
+++ b/plugins/UM3NetworkPrinting/src/Cloud/Models/BaseCloudModel.py
@@ -0,0 +1,55 @@
+# Copyright (c) 2018 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
+
+
+## Base class for the models used in the interface with the Ultimaker cloud APIs.
+class BaseCloudModel(BaseModel):
+ ## Checks whether the two models are equal.
+ # \param other: The other model.
+ # \return True if they are equal, False if they are different.
+ def __eq__(self, other):
+ return type(self) == type(other) and self.toDict() == other.toDict()
+
+ ## Checks whether the two models are different.
+ # \param other: The other model.
+ # \return True if they are different, False if they are the same.
+ def __ne__(self, other) -> bool:
+ return type(self) != type(other) or self.toDict() != other.toDict()
+
+ ## Converts the model into a serializable dictionary
+ 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.
+ # \return An instance of the model_class given.
+ @staticmethod
+ def parseModel(model_class: Type[T], values: Union[T, Dict[str, Any]]) -> T:
+ if isinstance(values, dict):
+ return model_class(**values)
+ return values
+
+ ## Parses a list of models.
+ # \param model_class: The model class.
+ # \param values: The value of the list. Each value is usually a dictionary, but may also be already parsed.
+ # \return A list of instances of the model_class given.
+ @classmethod
+ def parseModels(cls, model_class: Type[T], values: List[Union[T, Dict[str, Any]]]) -> List[T]:
+ return [cls.parseModel(model_class, value) for value in values]
+
+ ## Parses the given date string.
+ # \param date: The date to parse.
+ # \return The parsed date.
+ @staticmethod
+ def parseDate(date: Union[str, datetime]) -> datetime:
+ if isinstance(date, datetime):
+ return date
+ return datetime.strptime(date, "%Y-%m-%dT%H:%M:%S.%fZ").replace(tzinfo=timezone.utc)
diff --git a/plugins/UM3NetworkPrinting/src/Cloud/Models/CloudClusterBuildPlate.py b/plugins/UM3NetworkPrinting/src/Cloud/Models/CloudClusterBuildPlate.py
new file mode 100644
index 0000000000..4386bbb435
--- /dev/null
+++ b/plugins/UM3NetworkPrinting/src/Cloud/Models/CloudClusterBuildPlate.py
@@ -0,0 +1,13 @@
+# 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/CloudClusterPrintCoreConfiguration.py b/plugins/UM3NetworkPrinting/src/Cloud/Models/CloudClusterPrintCoreConfiguration.py
new file mode 100644
index 0000000000..aba1cdb755
--- /dev/null
+++ b/plugins/UM3NetworkPrinting/src/Cloud/Models/CloudClusterPrintCoreConfiguration.py
@@ -0,0 +1,52 @@
+# Copyright (c) 2018 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+from typing import Union, Dict, Optional, Any
+
+from cura.PrinterOutput.Models.ExtruderConfigurationModel import ExtruderConfigurationModel
+from cura.PrinterOutput.Models.ExtruderOutputModel import ExtruderOutputModel
+from .CloudClusterPrinterConfigurationMaterial import CloudClusterPrinterConfigurationMaterial
+from .BaseCloudModel import BaseCloudModel
+
+
+## Class representing a cloud cluster printer configuration
+# Spec: https://api-staging.ultimaker.com/connect/v1/spec
+class CloudClusterPrintCoreConfiguration(BaseCloudModel):
+ ## 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],
+ print_core_id: Optional[str] = None, **kwargs) -> None:
+ self.extruder_index = extruder_index
+ self.material = self.parseModel(CloudClusterPrinterConfigurationMaterial, material) if material else None
+ self.print_core_id = print_core_id
+ super().__init__(**kwargs)
+
+ ## Updates the given output model.
+ # \param model - The output model to update.
+ def updateOutputModel(self, model: ExtruderOutputModel) -> None:
+ if self.print_core_id is not None:
+ model.updateHotendID(self.print_core_id)
+
+ if self.material:
+ active_material = model.activeMaterial
+ if active_material is None or active_material.guid != self.material.guid:
+ material = self.material.createOutputModel()
+ model.updateActiveMaterial(material)
+ else:
+ model.updateActiveMaterial(None)
+
+ ## Creates a configuration model
+ def createConfigurationModel(self) -> ExtruderConfigurationModel:
+ model = ExtruderConfigurationModel(position = self.extruder_index)
+ self.updateConfigurationModel(model)
+ return model
+
+ ## Creates a configuration model
+ def updateConfigurationModel(self, model: ExtruderConfigurationModel) -> ExtruderConfigurationModel:
+ model.setHotendID(self.print_core_id)
+ if self.material:
+ model.setMaterial(self.material.createOutputModel())
+ return model
diff --git a/plugins/UM3NetworkPrinting/src/Cloud/Models/CloudClusterPrintJobConfigurationChange.py b/plugins/UM3NetworkPrinting/src/Cloud/Models/CloudClusterPrintJobConfigurationChange.py
new file mode 100644
index 0000000000..9ff4154666
--- /dev/null
+++ b/plugins/UM3NetworkPrinting/src/Cloud/Models/CloudClusterPrintJobConfigurationChange.py
@@ -0,0 +1,27 @@
+# Copyright (c) 2018 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+from typing import Optional
+
+from .BaseCloudModel import BaseCloudModel
+
+
+## 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):
+ ## 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
+ # \param target_id: Target material guid or hotend id
+ # \param origin_id: Original/current material guid or hotend id
+ # \param target_name: Target material name or hotend id
+ # \param origin_name: Original/current material name or hotend id
+ def __init__(self, type_of_change: str, target_id: str, origin_id: str,
+ index: Optional[int] = None, target_name: Optional[str] = None, origin_name: Optional[str] = None,
+ **kwargs) -> None:
+ self.type_of_change = type_of_change
+ self.index = index
+ self.target_id = target_id
+ self.origin_id = origin_id
+ self.target_name = target_name
+ self.origin_name = origin_name
+ super().__init__(**kwargs)
diff --git a/plugins/UM3NetworkPrinting/src/Cloud/Models/CloudClusterPrintJobConstraint.py b/plugins/UM3NetworkPrinting/src/Cloud/Models/CloudClusterPrintJobConstraint.py
new file mode 100644
index 0000000000..8236ec06b9
--- /dev/null
+++ b/plugins/UM3NetworkPrinting/src/Cloud/Models/CloudClusterPrintJobConstraint.py
@@ -0,0 +1,16 @@
+# Copyright (c) 2018 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+from typing import Optional
+
+from .BaseCloudModel import BaseCloudModel
+
+
+## Class representing a cloud cluster print job constraint
+# Spec: https://api-staging.ultimaker.com/connect/v1/spec
+class CloudClusterPrintJobConstraints(BaseCloudModel):
+ ## 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'
+ def __init__(self, require_printer_name: Optional[str] = None, **kwargs) -> None:
+ self.require_printer_name = require_printer_name
+ super().__init__(**kwargs)
diff --git a/plugins/UM3NetworkPrinting/src/Cloud/Models/CloudClusterPrintJobImpediment.py b/plugins/UM3NetworkPrinting/src/Cloud/Models/CloudClusterPrintJobImpediment.py
new file mode 100644
index 0000000000..12b67996c1
--- /dev/null
+++ b/plugins/UM3NetworkPrinting/src/Cloud/Models/CloudClusterPrintJobImpediment.py
@@ -0,0 +1,15 @@
+# Copyright (c) 2018 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+from .BaseCloudModel import BaseCloudModel
+
+
+## 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):
+ ## 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 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
+ self.severity = severity
+ super().__init__(**kwargs)
diff --git a/plugins/UM3NetworkPrinting/src/Cloud/Models/CloudClusterPrintJobStatus.py b/plugins/UM3NetworkPrinting/src/Cloud/Models/CloudClusterPrintJobStatus.py
new file mode 100644
index 0000000000..4a3823ccca
--- /dev/null
+++ b/plugins/UM3NetworkPrinting/src/Cloud/Models/CloudClusterPrintJobStatus.py
@@ -0,0 +1,133 @@
+# Copyright (c) 2018 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.Models.PrinterConfigurationModel import PrinterConfigurationModel
+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
+
+
+## Model for the status of a single print job in a cluster.
+# Spec: https://api-staging.ultimaker.com/connect/v1/spec
+class CloudClusterPrintJobStatus(BaseCloudModel):
+ ## 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.
+ # \param constraints: Print job constraints object.
+ # \param created_at: The timestamp when the job was created in Cura Connect.
+ # \param force: Allow this job to be printed despite of mismatching configurations.
+ # \param last_seen: The number of seconds since this job was checked.
+ # \param machine_variant: The machine type that this job should be printed on.Coincides with the machine_type field
+ # of the printer object.
+ # \param name: The name of the print job. Usually the name of the .gcode file.
+ # \param network_error_count: The number of errors encountered when requesting data for this print job.
+ # \param owner: The name of the user who added the print job to Cura Connect.
+ # \param printer_uuid: UUID of the printer that the job is currently printing on or assigned to.
+ # \param started: Whether the job has started printing or not.
+ # \param status: The status of the print job.
+ # \param time_elapsed: The remaining printing time in seconds.
+ # \param time_total: The total printing time in seconds.
+ # \param uuid: UUID of this print job. Should be used for identification purposes.
+ # \param deleted_at: The time when this print job was deleted.
+ # \param printed_on_uuid: UUID of the printer used to print this job.
+ # \param configuration_changes_required: List of configuration changes the printer this job is associated with
+ # needs to make in order to be able to print this job
+ # \param build_plate: The build plate (type) this job needs to be printed on.
+ # \param compatible_machine_families: Family names of machines suitable for this print job
+ # \param impediments_to_printing: A list of reasons that prevent this job from being printed on the associated
+ # 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]],
+ 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,
+ compatible_machine_families: List[str] = None,
+ impediments_to_printing: List[Union[Dict[str, Any], CloudClusterPrintJobImpediment]] = None,
+ **kwargs) -> None:
+ self.assigned_to = assigned_to
+ self.configuration = self.parseModels(CloudClusterPrintCoreConfiguration, configuration)
+ self.constraints = self.parseModels(CloudClusterPrintJobConstraints, constraints)
+ self.created_at = created_at
+ self.force = force
+ self.last_seen = last_seen
+ self.machine_variant = machine_variant
+ self.name = name
+ self.network_error_count = network_error_count
+ self.owner = owner
+ self.printer_uuid = printer_uuid
+ self.started = started
+ self.status = status
+ self.time_elapsed = time_elapsed
+ self.time_total = time_total
+ self.uuid = uuid
+ self.deleted_at = deleted_at
+ self.printed_on_uuid = printed_on_uuid
+
+ self.configuration_changes_required = self.parseModels(CloudClusterPrintJobConfigurationChange,
+ configuration_changes_required) \
+ if configuration_changes_required else []
+ self.build_plate = self.parseModel(CloudClusterBuildPlate, 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) \
+ 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:
+ model = UM3PrintJobOutputModel(controller, self.uuid, self.name)
+ self.updateOutputModel(model)
+ return model
+
+ ## Creates a new configuration model
+ def _createConfigurationModel(self) -> PrinterConfigurationModel:
+ extruders = [extruder.createConfigurationModel() for extruder in self.configuration or ()]
+ configuration = PrinterConfigurationModel()
+ configuration.setExtruderConfigurations(extruders)
+ return configuration
+
+ ## Updates an UM3 print job output model based on this cloud cluster print job.
+ # \param model: The model to update.
+ def updateOutputModel(self, model: UM3PrintJobOutputModel) -> None:
+ model.updateConfiguration(self._createConfigurationModel())
+ model.updateTimeTotal(self.time_total)
+ model.updateTimeElapsed(self.time_elapsed)
+ model.updateOwner(self.owner)
+ model.updateState(self.status)
+ model.setCompatibleMachineFamilies(self.compatible_machine_families)
+ model.updateTimeTotal(self.time_total)
+ model.updateTimeElapsed(self.time_elapsed)
+ model.updateOwner(self.owner)
+
+ status_set_by_impediment = False
+ for impediment in self.impediments_to_printing:
+ # TODO: impediment.severity is defined as int, this will not work, is there a translation?
+ if impediment.severity == "UNFIXABLE":
+ status_set_by_impediment = True
+ model.updateState("error")
+ break
+
+ if not status_set_by_impediment:
+ model.updateState(self.status)
+
+ model.updateConfigurationChanges(
+ [ConfigurationChangeModel(
+ type_of_change = change.type_of_change,
+ index = change.index if change.index else 0,
+ target_name = change.target_name if change.target_name else "",
+ origin_name = change.origin_name if change.origin_name else "")
+ for change in self.configuration_changes_required])
diff --git a/plugins/UM3NetworkPrinting/src/Cloud/Models/CloudClusterPrinterConfigurationMaterial.py b/plugins/UM3NetworkPrinting/src/Cloud/Models/CloudClusterPrinterConfigurationMaterial.py
new file mode 100644
index 0000000000..db09133a14
--- /dev/null
+++ b/plugins/UM3NetworkPrinting/src/Cloud/Models/CloudClusterPrinterConfigurationMaterial.py
@@ -0,0 +1,55 @@
+from typing import Optional
+
+from UM.Logger import Logger
+from cura.CuraApplication import CuraApplication
+from cura.PrinterOutput.Models.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
new file mode 100644
index 0000000000..0b76ba1bce
--- /dev/null
+++ b/plugins/UM3NetworkPrinting/src/Cloud/Models/CloudClusterPrinterStatus.py
@@ -0,0 +1,73 @@
+# 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.Models.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/CloudClusterResponse.py b/plugins/UM3NetworkPrinting/src/Cloud/Models/CloudClusterResponse.py
new file mode 100644
index 0000000000..a872a6ba68
--- /dev/null
+++ b/plugins/UM3NetworkPrinting/src/Cloud/Models/CloudClusterResponse.py
@@ -0,0 +1,39 @@
+# Copyright (c) 2018 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+from typing import Optional
+
+from .BaseCloudModel import BaseCloudModel
+
+
+## Class representing a cloud connected cluster.
+# Spec: https://api-staging.ultimaker.com/connect/v1/spec
+class CloudClusterResponse(BaseCloudModel):
+ ## 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'.
+ # \param host_name: The name of the printer as configured during the Wi-Fi setup. Used as identifier for end users.
+ # \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_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.
+ def validate(self) -> None:
+ super().validate()
+ if not self.cluster_id:
+ raise ValueError("cluster_id is required on CloudCluster")
diff --git a/plugins/UM3NetworkPrinting/src/Cloud/Models/CloudClusterStatus.py b/plugins/UM3NetworkPrinting/src/Cloud/Models/CloudClusterStatus.py
new file mode 100644
index 0000000000..b0250c2ebb
--- /dev/null
+++ b/plugins/UM3NetworkPrinting/src/Cloud/Models/CloudClusterStatus.py
@@ -0,0 +1,26 @@
+# Copyright (c) 2018 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
+
+
+# Model that represents the status of the cluster for the cloud
+# Spec: https://api-staging.ultimaker.com/connect/v1/spec
+class CloudClusterStatus(BaseCloudModel):
+ ## 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]]],
+ 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)
+ super().__init__(**kwargs)
diff --git a/plugins/UM3NetworkPrinting/src/Cloud/Models/CloudError.py b/plugins/UM3NetworkPrinting/src/Cloud/Models/CloudError.py
new file mode 100644
index 0000000000..b53361022e
--- /dev/null
+++ b/plugins/UM3NetworkPrinting/src/Cloud/Models/CloudError.py
@@ -0,0 +1,28 @@
+# Copyright (c) 2018 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+from typing import Dict, Optional, Any
+
+from .BaseCloudModel import BaseCloudModel
+
+
+## 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):
+ ## 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
+ # of the problem, except for purposes of localization.
+ # \param code: An application-specific error code, expressed as a string value.
+ # \param detail: A human-readable explanation specific to this occurrence of the problem. Like title, this field's
+ # value can be localized.
+ # \param http_status: The HTTP status code applicable to this problem, converted to string.
+ # \param meta: Non-standard meta-information about the error, depending on the error code.
+ def __init__(self, id: str, code: str, title: str, http_status: str, detail: Optional[str] = None,
+ meta: Optional[Dict[str, Any]] = None, **kwargs) -> None:
+ self.id = id
+ self.code = code
+ self.http_status = http_status
+ self.title = title
+ self.detail = detail
+ self.meta = meta
+ super().__init__(**kwargs)
diff --git a/plugins/UM3NetworkPrinting/src/Cloud/Models/CloudPrintJobResponse.py b/plugins/UM3NetworkPrinting/src/Cloud/Models/CloudPrintJobResponse.py
new file mode 100644
index 0000000000..79196ee38c
--- /dev/null
+++ b/plugins/UM3NetworkPrinting/src/Cloud/Models/CloudPrintJobResponse.py
@@ -0,0 +1,33 @@
+# Copyright (c) 2018 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+from typing import Optional
+
+from .BaseCloudModel import BaseCloudModel
+
+
+# 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):
+ ## 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.
+ # \param status_description: Contains more details about the status, e.g. the cause of failures.
+ # \param download_url: A signed URL to download the resulting status. Only available when the job is finished.
+ # \param job_name: The name of the print job.
+ # \param slicing_details: Model for slice information.
+ # \param upload_url: The one-time use URL where the toolpath must be uploaded to (only if status is uploading).
+ # \param content_type: The content type of the print job (e.g. text/plain or application/gzip)
+ # \param generated_time: The datetime when the object was generated on the server-side.
+ def __init__(self, job_id: str, status: str, download_url: Optional[str] = None, job_name: Optional[str] = None,
+ upload_url: Optional[str] = None, content_type: Optional[str] = None,
+ status_description: Optional[str] = None, slicing_details: Optional[dict] = None, **kwargs) -> None:
+ self.job_id = job_id
+ self.status = status
+ self.download_url = download_url
+ self.job_name = job_name
+ 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/Cloud/Models/CloudPrintJobUploadRequest.py
new file mode 100644
index 0000000000..e59c571558
--- /dev/null
+++ b/plugins/UM3NetworkPrinting/src/Cloud/Models/CloudPrintJobUploadRequest.py
@@ -0,0 +1,17 @@
+# Copyright (c) 2018 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+from .BaseCloudModel import BaseCloudModel
+
+
+# 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):
+ ## 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.
+ # \param content_type: The content type of the print job (e.g. text/plain or application/gzip)
+ def __init__(self, job_name: str, file_size: int, content_type: str, **kwargs) -> None:
+ self.job_name = job_name
+ self.file_size = file_size
+ self.content_type = content_type
+ super().__init__(**kwargs)
diff --git a/plugins/UM3NetworkPrinting/src/Cloud/Models/CloudPrintResponse.py b/plugins/UM3NetworkPrinting/src/Cloud/Models/CloudPrintResponse.py
new file mode 100644
index 0000000000..919d1b3c3a
--- /dev/null
+++ b/plugins/UM3NetworkPrinting/src/Cloud/Models/CloudPrintResponse.py
@@ -0,0 +1,23 @@
+# Copyright (c) 2018 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
+
+
+# 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):
+ ## 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).
+ # \param generated_time: The datetime when the object was generated on the server-side.
+ # \param cluster_job_id: The unique ID of a print job inside of the cluster. This ID is generated by Cura Connect.
+ def __init__(self, job_id: str, status: str, generated_time: Union[str, datetime],
+ cluster_job_id: Optional[str] = None, **kwargs) -> None:
+ self.job_id = job_id
+ self.status = status
+ self.cluster_job_id = cluster_job_id
+ self.generated_time = self.parseDate(generated_time)
+ super().__init__(**kwargs)
diff --git a/plugins/UM3NetworkPrinting/src/Cloud/Models/__init__.py b/plugins/UM3NetworkPrinting/src/Cloud/Models/__init__.py
new file mode 100644
index 0000000000..f3f6970c54
--- /dev/null
+++ b/plugins/UM3NetworkPrinting/src/Cloud/Models/__init__.py
@@ -0,0 +1,2 @@
+# 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
new file mode 100644
index 0000000000..176b7e6ab7
--- /dev/null
+++ b/plugins/UM3NetworkPrinting/src/Cloud/ToolPathUploader.py
@@ -0,0 +1,148 @@
+# Copyright (c) 2018 Ultimaker B.V.
+# !/usr/bin/env python
+# -*- coding: utf-8 -*-
+from PyQt5.QtCore import QUrl
+from PyQt5.QtNetwork import QNetworkRequest, QNetworkReply, QNetworkAccessManager
+from typing import Optional, Callable, Any, Tuple, cast
+
+from UM.Logger import Logger
+from .Models.CloudPrintJobResponse import CloudPrintJobResponse
+
+
+## Class responsible for uploading meshes to the cloud in separate requests.
+class ToolPathUploader:
+
+ # The maximum amount of times to retry if the server returns one of the RETRY_HTTP_CODES
+ MAX_RETRIES = 10
+
+ # The HTTP codes that should trigger a retry.
+ RETRY_HTTP_CODES = {500, 502, 503, 504}
+
+ # The amount of bytes to send per request
+ BYTES_PER_REQUEST = 256 * 1024
+
+ ## Creates a mesh upload object.
+ # \param manager: The network access manager that will handle the HTTP requests.
+ # \param print_job: The print job response that was returned by the cloud after registering the upload.
+ # \param data: The mesh bytes to be uploaded.
+ # \param on_finished: The method to be called when done.
+ # \param on_progress: The method to be called when the progress changes (receives a percentage 0-100).
+ # \param on_error: The method to be called when an error occurs.
+ def __init__(self, manager: QNetworkAccessManager, print_job: CloudPrintJobResponse, data: bytes,
+ on_finished: Callable[[], Any], on_progress: Callable[[int], Any], on_error: Callable[[], Any]
+ ) -> None:
+ self._manager = manager
+ self._print_job = print_job
+ self._data = data
+
+ self._on_finished = on_finished
+ self._on_progress = on_progress
+ self._on_error = on_error
+
+ self._sent_bytes = 0
+ self._retries = 0
+ self._finished = False
+ self._reply = None # type: Optional[QNetworkReply]
+
+ ## Returns the print job for which this object was created.
+ @property
+ def printJob(self):
+ return self._print_job
+
+ ## Creates a network request to the print job upload URL, adding the needed content range header.
+ 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())
+ Logger.log("i", "Uploading %s to %s", content_range, self._print_job.upload_url)
+
+ return request
+
+ ## Determines the bytes that should be uploaded next.
+ # \return: A tuple with the first and the last byte to upload.
+ def _chunkRange(self) -> Tuple[int, int]:
+ last_byte = min(len(self._data), self._sent_bytes + self.BYTES_PER_REQUEST)
+ return self._sent_bytes, last_byte
+
+ ## Starts uploading the mesh.
+ def start(self) -> None:
+ if self._finished:
+ # reset state.
+ self._sent_bytes = 0
+ self._retries = 0
+ self._finished = False
+ self._uploadChunk()
+
+ ## Stops uploading the mesh, marking it as finished.
+ def stop(self):
+ Logger.log("i", "Stopped uploading")
+ self._finished = True
+
+ ## Uploads a chunk of the mesh to the cloud.
+ def _uploadChunk(self) -> None:
+ if self._finished:
+ raise ValueError("The upload is already finished")
+
+ first_byte, last_byte = self._chunkRange()
+ request = self._createRequest()
+
+ # now send the reply and subscribe to the results
+ self._reply = self._manager.put(request, self._data[first_byte:last_byte])
+ self._reply.finished.connect(self._finishedCallback)
+ self._reply.uploadProgress.connect(self._progressCallback)
+ self._reply.error.connect(self._errorCallback)
+
+ ## Handles an update to the upload progress
+ # \param bytes_sent: The amount of bytes sent in the current request.
+ # \param bytes_total: The amount of bytes to send in the current request.
+ def _progressCallback(self, bytes_sent: int, bytes_total: int) -> None:
+ Logger.log("i", "Progress callback %s / %s", bytes_sent, bytes_total)
+ if bytes_total:
+ total_sent = self._sent_bytes + bytes_sent
+ self._on_progress(int(total_sent / len(self._data) * 100))
+
+ ## Handles an error uploading.
+ def _errorCallback(self) -> None:
+ reply = cast(QNetworkReply, self._reply)
+ body = bytes(reply.readAll()).decode()
+ Logger.log("e", "Received error while uploading: %s", body)
+ self.stop()
+ self._on_error()
+
+ ## Checks whether a chunk of data was uploaded successfully, starting the next chunk if needed.
+ def _finishedCallback(self) -> None:
+ reply = cast(QNetworkReply, self._reply)
+ Logger.log("i", "Finished callback %s %s",
+ reply.attribute(QNetworkRequest.HttpStatusCodeAttribute), reply.url().toString())
+
+ status_code = reply.attribute(QNetworkRequest.HttpStatusCodeAttribute) # type: int
+
+ # check if we should retry the last chunk
+ if self._retries < self.MAX_RETRIES and status_code in self.RETRY_HTTP_CODES:
+ self._retries += 1
+ Logger.log("i", "Retrying %s/%s request %s", self._retries, self.MAX_RETRIES, reply.url().toString())
+ self._uploadChunk()
+ return
+
+ # Http codes that are not to be retried are assumed to be errors.
+ if status_code > 308:
+ self._errorCallback()
+ return
+
+ Logger.log("d", "status_code: %s, Headers: %s, body: %s", status_code,
+ [bytes(header).decode() for header in reply.rawHeaderList()], bytes(reply.readAll()).decode())
+ self._chunkUploaded()
+
+ ## Handles a chunk of data being uploaded, starting the next chunk if needed.
+ def _chunkUploaded(self) -> None:
+ # We got a successful response. Let's start the next chunk or report the upload is finished.
+ first_byte, last_byte = self._chunkRange()
+ self._sent_bytes += last_byte - first_byte
+ if self._sent_bytes >= len(self._data):
+ self.stop()
+ self._on_finished()
+ else:
+ self._uploadChunk()
diff --git a/plugins/UM3NetworkPrinting/src/Cloud/Utils.py b/plugins/UM3NetworkPrinting/src/Cloud/Utils.py
new file mode 100644
index 0000000000..5136e0e7db
--- /dev/null
+++ b/plugins/UM3NetworkPrinting/src/Cloud/Utils.py
@@ -0,0 +1,54 @@
+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/Cloud/__init__.py b/plugins/UM3NetworkPrinting/src/Cloud/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py b/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py
index 409ca7a84a..177836bccd 100644
--- a/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py
+++ b/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py
@@ -1,72 +1,79 @@
-# 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 Any, cast, Optional, Set, Tuple, Union
-
-from UM.FileHandler.FileHandler import FileHandler
-from UM.FileHandler.FileWriter import FileWriter # To choose based on the output file mode (text vs. binary).
-from UM.FileHandler.WriteFileJob import WriteFileJob # To call the file writer asynchronously.
-from UM.Logger import Logger
-from UM.Settings.ContainerRegistry import ContainerRegistry
-from UM.i18n import i18nCatalog
-
-from UM.Message import Message
-from UM.Qt.Duration import Duration, DurationFormat
-from UM.OutputDevice import OutputDeviceError # To show that something went wrong when writing.
-from UM.Scene.SceneNode import SceneNode # For typing.
-from UM.Version import Version # To check against firmware versions for support.
-
-from cura.CuraApplication import CuraApplication
-from cura.PrinterOutput.ConfigurationModel import ConfigurationModel
-from cura.PrinterOutput.ExtruderConfigurationModel import ExtruderConfigurationModel
-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.PrinterOutput.NetworkCamera import NetworkCamera
-
-from .ClusterUM3PrinterOutputController import ClusterUM3PrinterOutputController
-from .SendMaterialJob import SendMaterialJob
-
-from PyQt5.QtNetwork import QNetworkRequest, QNetworkReply
-from PyQt5.QtGui import QDesktopServices, QImage
-from PyQt5.QtCore import pyqtSlot, QUrl, pyqtSignal, pyqtProperty, QObject
-
+from typing import Any, cast, Tuple, Union, Optional, Dict, List
from time import time
-from datetime import datetime
-from typing import Optional, Dict, List
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.Models.PrinterConfigurationModel import PrinterConfigurationModel
+from cura.PrinterOutput.Models.ExtruderConfigurationModel import ExtruderConfigurationModel
+from cura.PrinterOutput.NetworkedPrinterOutputDevice import AuthState, NetworkedPrinterOutputDevice
+from cura.PrinterOutput.Models.PrinterOutputModel import PrinterOutputModel
+from cura.PrinterOutput.Models.MaterialOutputModel import MaterialOutputModel
+from cura.PrinterOutput.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()
- activeCameraChanged = pyqtSignal()
+ activeCameraUrlChanged = pyqtSignal()
+ receivedPrintJobsChanged = pyqtSignal()
- # This is a bit of a hack, as the notify can only use signals that are defined by the class that they are in.
- # Inheritance doesn't seem to work. Tying them together does work, but i'm open for better suggestions.
- clusterPrintersChanged = 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, parent = parent)
+ 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[str, Dict, Union[io.StringIO, io.BytesIO]]
+ 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[PrintJobOutputModel]
+ self._print_jobs = [] # type: List[UM3PrintJobOutputModel]
+ self._received_print_jobs = False # type: bool
- self._monitor_view_qml_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "../resources/qml/ClusterMonitorItem.qml")
- self._control_view_qml_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "../resources/qml/ClusterControlItem.qml")
+ if PluginRegistry.getInstance() is not None:
+ plugin_path = PluginRegistry.getInstance().getPluginPath("UM3NetworkPrinting")
+ if plugin_path is None:
+ Logger.log("e", "Cloud not find plugin path for plugin UM3NetworkPrnting")
+ raise RuntimeError("Cloud not find plugin path for plugin UM3NetworkPrnting")
+ self._monitor_view_qml_path = os.path.join(plugin_path, "resources", "qml", "MonitorStage.qml")
- # See comments about this hack with the clusterPrintersChanged signal
- self.printersChanged.connect(self.clusterPrintersChanged)
+ # Trigger the printersChanged signal when the private signal is triggered
+ self.printersChanged.connect(self._clusterPrintersChanged)
self._accepts_commands = True # type: bool
@@ -90,62 +97,28 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice):
self._printer_uuid_to_unique_name_mapping = {} # type: Dict[str, str]
- self._finished_jobs = [] # type: List[PrintJobOutputModel]
+ 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 = None # type: Optional[NetworkCamera]
+ 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:
+ 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:
self.writeStarted.emit(self)
self.sendMaterialProfiles()
- # Formats supported by this application (file types that we can actually write).
- if file_handler:
- file_formats = file_handler.getSupportedFileTypesWrite()
- else:
- file_formats = CuraApplication.getInstance().getMeshFileHandler().getSupportedFileTypesWrite()
-
- global_stack = CuraApplication.getInstance().getGlobalContainerStack()
- # Create a list from the supported file formats string.
- if not global_stack:
- Logger.log("e", "Missing global stack!")
- return
-
- 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(self.firmwareVersion) >= Version("4.4"):
- machine_file_formats = ["application/x-ufp"] + machine_file_formats
-
- # Take the intersection between file_formats and machine_file_formats.
- format_by_mimetype = {format["mime_type"]: format for format in file_formats}
- file_formats = [format_by_mimetype[mimetype] for mimetype in machine_file_formats] #Keep them ordered according to the preference in machine_file_formats.
-
- if len(file_formats) == 0:
- Logger.log("e", "There are no file formats available to write with!")
- raise OutputDeviceError.WriteRequestFailedError(i18n_catalog.i18nc("@info:status", "There are no file formats available to write with!"))
- preferred_format = file_formats[0]
-
- # Just take the first file format available.
- if file_handler is not None:
- writer = file_handler.getWriterByMimeType(cast(str, preferred_format["mime_type"]))
- else:
- writer = CuraApplication.getInstance().getMeshFileHandler().getWriterByMimeType(cast(str, preferred_format["mime_type"]))
-
- if not writer:
- Logger.log("e", "Unexpected error when trying to get the FileWriter")
- return
+ 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 writer:
+ if not mesh_format.is_valid:
Logger.log("e", "Missing file or mesh writer!")
return
- self._sending_job = self._sendPrintJob(writer, preferred_format, nodes)
+ self._sending_job = self._sendPrintJob(mesh_format, nodes)
if self._sending_job is not None:
self._sending_job.send(None) # Start the generator.
@@ -158,11 +131,20 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice):
def _spawnPrinterSelectionDialog(self):
if self._printer_selection_dialog is None:
- path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "../resources/qml/PrintWindow.qml")
- self._printer_selection_dialog = CuraApplication.getInstance().createQmlComponent(path, {"OutputDevice": self})
+ 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()
+ ## 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
+
@pyqtProperty(int, constant=True)
def clusterSize(self) -> int:
return self._cluster_size
@@ -185,11 +167,8 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice):
# greenlet in order to optionally wait for selectPrinter() to select a
# printer.
# The greenlet yields exactly three times: First time None,
- # \param writer The file writer to use to create the data.
- # \param preferred_format A dictionary containing some information about
- # what format to write to. This is necessary to create the correct buffer
- # types and file extension and such.
- def _sendPrintJob(self, writer: FileWriter, preferred_format: Dict, nodes: List[SceneNode]):
+ # \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(
@@ -203,35 +182,37 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice):
self._sending_gcode = True
- target_printer = yield #Potentially wait on the user to select a target printer.
+ # 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 = io.BytesIO() # type: Union[io.BytesIO, io.StringIO]# Binary mode.
- if preferred_format["mode"] == FileWriter.OutputMode.TextMode:
- stream = io.StringIO()
+ stream = mesh_format.createStream()
- job = WriteFileJob(writer, stream, nodes, preferred_format["mode"])
+ 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 = 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()
- self._dummy_lambdas = (target_printer, 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.
+ 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,
+ 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 = None, description = "")
+ 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 = []
@@ -246,7 +227,7 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice):
# Add user name to the print_job
parts.append(self._createFormPart("name=owner", bytes(self._getUserName(), "utf-8"), "text/plain"))
- file_name = CuraApplication.getInstance().getPrintInformation().jobName + "." + preferred_format["extension"]
+ 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):
@@ -255,36 +236,29 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice):
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)
+ 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
- @pyqtProperty(QObject, notify=activeCameraChanged)
- def activeCamera(self) -> Optional[NetworkCamera]:
- return self._active_camera
-
@pyqtSlot(QObject)
def setActivePrinter(self, printer: Optional[PrinterOutputModel]) -> None:
if self._active_printer != printer:
- if self._active_printer and self._active_printer.camera:
- self._active_printer.camera.stop()
self._active_printer = printer
self.activePrinterChanged.emit()
- @pyqtSlot(QObject)
- def setActiveCamera(self, camera: Optional[NetworkCamera]) -> None:
- if self._active_camera != camera:
- if self._active_camera:
- self._active_camera.stop()
+ @pyqtProperty(QUrl, notify = activeCameraUrlChanged)
+ def activeCameraUrl(self) -> "QUrl":
+ return self._active_camera_url
- self._active_camera = camera
-
- if self._active_camera:
- self._active_camera.start()
-
- self.activeCameraChanged.emit()
+ @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:
@@ -292,13 +266,18 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice):
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 and new_progress > self._progress_message.getProgress():
+ 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)
@@ -310,7 +289,7 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice):
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=None,
+ 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()
@@ -326,7 +305,7 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice):
self._progress_message.hide()
self._compressing_gcode = False
self._sending_gcode = False
- CuraApplication.getInstance().getController().setActiveStage("PrepareStage")
+ 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
@@ -336,7 +315,7 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice):
def _successMessageActionTriggered(self, message_id: Optional[str] = None, action_id: Optional[str] = None) -> None:
if action_id == "View":
- CuraApplication.getInstance().getController().setActiveStage("MonitorStage")
+ self._application.getController().setActiveStage("MonitorStage")
@pyqtSlot()
def openPrintJobControlPanel(self) -> None:
@@ -349,18 +328,22 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice):
QDesktopServices.openUrl(QUrl("http://" + self._address + "/printers"))
@pyqtProperty("QVariantList", notify = printJobsChanged)
- def printJobs(self)-> List[PrintJobOutputModel]:
+ 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[PrintJobOutputModel]:
+ 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[PrintJobOutputModel]:
+ 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)
+ @pyqtProperty("QVariantList", notify = _clusterPrintersChanged)
def connectedPrintersTypeCount(self) -> List[Dict[str, str]]:
printer_count = {} # type: Dict[str, int]
for printer in self._printers:
@@ -373,25 +356,21 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice):
result.append({"machine_type": machine_type, "count": str(printer_count[machine_type])})
return result
- @pyqtProperty("QVariantList", notify=clusterPrintersChanged)
+ @pyqtProperty("QVariantList", notify=_clusterPrintersChanged)
def printers(self):
return self._printers
- @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:
- current_time = time()
- datetime_completed = datetime.fromtimestamp(current_time + time_remaining)
- return "{hour:02d}:{minute:02d}".format(hour=datetime_completed.hour, minute=datetime_completed.minute)
+ return formatTimeCompleted(time_remaining)
@pyqtSlot(int, result = str)
def getDateCompleted(self, time_remaining: int) -> str:
- current_time = time()
- datetime_completed = datetime.fromtimestamp(current_time + time_remaining)
- return (datetime_completed.strftime("%a %b ") + "{day}".format(day=datetime_completed.day)).upper()
+ 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:
@@ -406,6 +385,18 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice):
# 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)
+
+ # Set the remote print job state.
+ def setJobState(self, print_job_uuid: str, state: str) -> None:
+ # We rewrite 'resume' to 'print' here because we are using the old print job action endpoints.
+ action = "print" if state == "resume" else state
+ data = "{\"action\": \"%s\"}" % action
+ self.put("print_jobs/%s/action" % print_job_uuid, data, on_finished=None)
+
def _printJobStateChanged(self) -> None:
username = self._getUserName()
@@ -417,9 +408,9 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice):
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))
+ 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_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()
@@ -455,6 +446,9 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice):
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
@@ -533,15 +527,15 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice):
def _createPrinterModel(self, data: Dict[str, Any]) -> PrinterOutputModel:
printer = PrinterOutputModel(output_controller = ClusterUM3PrinterOutputController(self),
number_of_extruders = self._number_of_extruders)
- printer.setCamera(NetworkCamera("http://" + data["ip_address"] + ":8080/?action=stream"))
+ printer.setCameraUrl(QUrl("http://" + data["ip_address"] + ":8080/?action=stream"))
self._printers.append(printer)
return printer
- def _createPrintJobModel(self, data: Dict[str, Any]) -> PrintJobOutputModel:
- print_job = PrintJobOutputModel(output_controller=ClusterUM3PrinterOutputController(self),
+ def _createPrintJobModel(self, data: Dict[str, Any]) -> UM3PrintJobOutputModel:
+ print_job = UM3PrintJobOutputModel(output_controller=ClusterUM3PrinterOutputController(self),
key=data["uuid"], name= data["name"])
- configuration = ConfigurationModel()
+ configuration = PrinterConfigurationModel()
extruders = [ExtruderConfigurationModel(position = idx) for idx in range(0, self._number_of_extruders)]
for index in range(0, self._number_of_extruders):
try:
@@ -553,12 +547,13 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice):
extruder.setMaterial(self._createMaterialOutputModel(extruder_data.get("material", {})))
configuration.setExtruderConfigurations(extruders)
+ configuration.setPrinterType(data.get("machine_variant", ""))
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: PrintJobOutputModel, data: Dict[str, Any]) -> None:
+ 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", [])
@@ -574,14 +569,56 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice):
if not status_set_by_impediment:
print_job.updateState(data["status"])
+ print_job.updateConfigurationChanges(self._createConfigurationChanges(data["configuration_changes_required"]))
- def _createMaterialOutputModel(self, material_data) -> MaterialOutputModel:
- containers = ContainerRegistry.getInstance().findInstanceContainers(type="material", GUID=material_data["guid"])
- if containers:
- color = containers[0].getMetaDataEntry("color_code")
- brand = containers[0].getMetaDataEntry("brand")
- material_type = containers[0].getMetaDataEntry("material")
- name = containers[0].getName()
+ 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(
@@ -589,9 +626,10 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice):
color = material_data["color"]
brand = material_data["brand"]
material_type = material_data["material"]
- name = "Empty" if material_data["material"] == "empty" else "Unknown"
- return MaterialOutputModel(guid=material_data["guid"], type=material_type,
- brand=brand, color=color, name=name)
+ 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.
@@ -609,9 +647,14 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice):
printer.updateKey(data["uuid"])
printer.updateType(data["machine_variant"])
+ if data["status"] != "unreachable":
+ self._application.getDiscoveredPrintersModel().updateDiscoveredPrinter(data["ip_address"],
+ name = data["friendly_name"],
+ machine_type = 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.updateBuildplateName(data["build_plate"]["type"])
+ printer.updateBuildplate(data["build_plate"]["type"])
if not data["enabled"]:
printer.updateState("disabled")
else:
@@ -631,7 +674,7 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice):
material = self._createMaterialOutputModel(material_data)
extruder.updateActiveMaterial(material)
- def _removeJob(self, job: PrintJobOutputModel) -> bool:
+ def _removeJob(self, job: UM3PrintJobOutputModel) -> bool:
if job not in self._print_jobs:
return False
@@ -656,7 +699,6 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice):
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"))
@@ -675,7 +717,7 @@ def checkValidGetReply(reply: QNetworkReply) -> bool:
return True
-def findByKey(lst: List[Union[PrintJobOutputModel, PrinterOutputModel]], key: str) -> Optional[PrintJobOutputModel]:
+def findByKey(lst: List[Union[UM3PrintJobOutputModel, PrinterOutputModel]], key: str) -> Optional[UM3PrintJobOutputModel]:
for item in lst:
if item.key == key:
return item
diff --git a/plugins/UM3NetworkPrinting/src/ClusterUM3PrinterOutputController.py b/plugins/UM3NetworkPrinting/src/ClusterUM3PrinterOutputController.py
index fcced0b883..103be8b01e 100644
--- a/plugins/UM3NetworkPrinting/src/ClusterUM3PrinterOutputController.py
+++ b/plugins/UM3NetworkPrinting/src/ClusterUM3PrinterOutputController.py
@@ -5,7 +5,8 @@ from cura.PrinterOutput.PrinterOutputController import PrinterOutputController
MYPY = False
if MYPY:
- from cura.PrinterOutput.PrintJobOutputModel import PrintJobOutputModel
+ from cura.PrinterOutput.Models.PrintJobOutputModel import PrintJobOutputModel
+
class ClusterUM3PrinterOutputController(PrinterOutputController):
def __init__(self, output_device):
@@ -15,7 +16,5 @@ class ClusterUM3PrinterOutputController(PrinterOutputController):
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)
-
+ def setJobState(self, job: "PrintJobOutputModel", state: str) -> None:
+ self._output_device.setJobState(job.key, state)
diff --git a/plugins/UM3NetworkPrinting/src/ConfigurationChangeModel.py b/plugins/UM3NetworkPrinting/src/ConfigurationChangeModel.py
new file mode 100644
index 0000000000..7136d8b93f
--- /dev/null
+++ b/plugins/UM3NetworkPrinting/src/ConfigurationChangeModel.py
@@ -0,0 +1,38 @@
+# 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
+
+BLOCKING_CHANGE_TYPES = [
+ "material_insert", "buildplate_change"
+]
+
+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._can_override = self._type_of_change not in BLOCKING_CHANGE_TYPES
+ self._index = index
+ self._target_name = target_name
+ self._origin_name = origin_name
+
+ @pyqtProperty(int, constant = True)
+ def index(self) -> int:
+ return self._index
+
+ @pyqtProperty(str, constant = True)
+ def typeOfChange(self) -> str:
+ return self._type_of_change
+
+ @pyqtProperty(str, constant = True)
+ def targetName(self) -> str:
+ return self._target_name
+
+ @pyqtProperty(str, constant = True)
+ def originName(self) -> str:
+ return self._origin_name
+
+ @pyqtProperty(bool, constant = True)
+ def canOverride(self) -> bool:
+ return self._can_override
\ No newline at end of file
diff --git a/plugins/UM3NetworkPrinting/src/DiscoverUM3Action.py b/plugins/UM3NetworkPrinting/src/DiscoverUM3Action.py
index be83e04585..b67f4d7185 100644
--- a/plugins/UM3NetworkPrinting/src/DiscoverUM3Action.py
+++ b/plugins/UM3NetworkPrinting/src/DiscoverUM3Action.py
@@ -3,7 +3,7 @@
import os.path
import time
-from typing import cast, Optional
+from typing import Optional, TYPE_CHECKING
from PyQt5.QtCore import pyqtSignal, pyqtProperty, pyqtSlot, QObject
@@ -13,9 +13,13 @@ 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.PrinterOutput.PrinterOutputDevice import PrinterOutputDevice
+
catalog = i18nCatalog("cura")
@@ -37,6 +41,11 @@ class DiscoverUM3Action(MachineAction):
# Time to wait after a zero-conf service change before allowing a zeroconf reset
self._zero_conf_change_grace_period = 0.25 #type: float
+ # Overrides the one in MachineAction.
+ # This requires not attention from the user (any more), so we don't need to show any 'upgrade screens'.
+ def needsUserInteraction(self) -> bool:
+ return False
+
@pyqtSlot()
def startDiscovery(self):
if not self._network_plugin:
@@ -101,41 +110,25 @@ class DiscoverUM3Action(MachineAction):
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 "connect_group_name" in meta_data:
- previous_connect_group_name = meta_data["connect_group_name"]
- global_container_stack.setMetaDataEntry("connect_group_name", group_name)
- # Find all the places where there is the same group name and change it accordingly
- CuraApplication.getInstance().getMachineManager().replaceContainersMetadata(key = "connect_group_name", value = previous_connect_group_name, new_value = group_name)
- else:
- global_container_stack.setMetaDataEntry("connect_group_name", group_name)
+ # Update a GlobalStacks in the same group with the new group name.
+ group_id = global_container_stack.getMetaDataEntry("group_id")
+ machine_manager = CuraApplication.getInstance().getMachineManager()
+ for machine in machine_manager.getMachinesInGroup(group_id):
+ machine.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()
-
- @pyqtSlot(str)
- def setKey(self, key: str) -> None:
- Logger.log("d", "Attempting to set the network key of the active machine to %s", key)
- global_container_stack = CuraApplication.getInstance().getGlobalContainerStack()
- if global_container_stack:
- meta_data = global_container_stack.getMetaData()
- if "um_network_key" in meta_data:
- previous_network_key= meta_data["um_network_key"]
- global_container_stack.setMetaDataEntry("um_network_key", key)
- # Delete old authentication data.
- Logger.log("d", "Removing old authentication id %s for device %s", global_container_stack.getMetaDataEntry("network_authentication_id", None), key)
- global_container_stack.removeMetaDataEntry("network_authentication_id")
- global_container_stack.removeMetaDataEntry("network_authentication_key")
- CuraApplication.getInstance().getMachineManager().replaceContainersMetadata(key = "um_network_key", value = previous_network_key, new_value = key)
- else:
- global_container_stack.setMetaDataEntry("um_network_key", key)
+ self._network_plugin.refreshConnections()
+ # 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 self._network_plugin:
- # Ensure that the connection states are refreshed.
- self._network_plugin.reCheckConnections()
+ self._network_plugin.associateActiveMachineWithPrinterDevice(printer_device)
@pyqtSlot(result = str)
def getStoredKey(self) -> str:
@@ -155,7 +148,9 @@ class DiscoverUM3Action(MachineAction):
@pyqtSlot(str, result = bool)
def existsKey(self, key: str) -> bool:
- return CuraApplication.getInstance().getMachineManager().existNetworkInstances(network_key = key)
+ metadata_filter = {"um_network_key": key}
+ containers = CuraContainerRegistry.getInstance().findContainerStacks(type="machine", **metadata_filter)
+ return bool(containers)
@pyqtSlot()
def loadConfigurationFromPrinter(self) -> None:
@@ -182,4 +177,3 @@ class DiscoverUM3Action(MachineAction):
# Create extra components
CuraApplication.getInstance().addAdditionalComponent("monitorButtons", self.__additional_components_view.findChild(QObject, "networkPrinterConnectButton"))
- CuraApplication.getInstance().addAdditionalComponent("machinesDetailPane", self.__additional_components_view.findChild(QObject, "networkPrinterConnectionInfo"))
diff --git a/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py b/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py
index e786840803..7d759264e5 100644
--- a/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py
+++ b/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py
@@ -1,24 +1,25 @@
from typing import List, Optional
-from UM.FileHandler.FileHandler import FileHandler
-from UM.Scene.SceneNode import SceneNode
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.PrinterOutput.NetworkCamera import NetworkCamera
+from cura.PrinterOutput.Models.PrinterOutputModel import PrinterOutputModel
+from cura.PrinterOutput.Models.PrintJobOutputModel import PrintJobOutputModel
+from cura.PrinterOutput.Models.MaterialOutputModel import MaterialOutputModel
+from cura.PrinterOutput.PrinterOutputDevice import ConnectionType
from cura.Settings.ContainerManager import ContainerManager
from cura.Settings.ExtruderManager import ExtruderManager
-from UM.Logger import Logger
-from UM.Settings.ContainerRegistry import ContainerRegistry
+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
+from PyQt5.QtCore import QTimer, QUrl
from PyQt5.QtWidgets import QMessageBox
from .LegacyUM3PrinterOutputController import LegacyUM3PrinterOutputController
@@ -44,7 +45,7 @@ i18n_catalog = i18nCatalog("cura")
# 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, parent = parent)
+ 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
@@ -76,10 +77,16 @@ class LegacyUM3OutputDevice(NetworkedPrinterOutputDevice):
self.setIconName("print")
- self._monitor_view_qml_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "../resources/qml/MonitorItem.qml")
-
self._output_controller = LegacyUM3PrinterOutputController(self)
+ def _createMonitorViewFromQML(self) -> None:
+ if self._monitor_view_qml_path is None and PluginRegistry.getInstance() is not None:
+ self._monitor_view_qml_path = os.path.join(
+ PluginRegistry.getInstance().getPluginPath("UM3NetworkPrinting"),
+ "resources", "qml", "MonitorStage.qml"
+ )
+ super()._createMonitorViewFromQML()
+
def _onAuthenticationStateChanged(self):
# We only accept commands if we are authenticated.
self._setAcceptsCommands(self._authentication_state == AuthState.Authenticated)
@@ -171,7 +178,8 @@ class LegacyUM3OutputDevice(NetworkedPrinterOutputDevice):
# 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:
+ 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 not self.activePrinter:
# No active printer. Unable to write
return
@@ -499,8 +507,8 @@ class LegacyUM3OutputDevice(NetworkedPrinterOutputDevice):
self._authentication_id = None
self.post("auth/request",
- json.dumps({"application": "Cura-" + CuraApplication.getInstance().getVersion(),
- "user": self._getUserName()}).encode(),
+ json.dumps({"application": "Cura-" + CuraApplication.getInstance().getVersion(),
+ "user": self._getUserName()}),
on_finished=self._onRequestAuthenticationFinished)
self.setAuthenticationState(AuthState.AuthenticationRequested)
@@ -568,7 +576,7 @@ class LegacyUM3OutputDevice(NetworkedPrinterOutputDevice):
# 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].setCamera(NetworkCamera("http://" + self._address + ":8080/?action=stream"))
+ 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)
diff --git a/plugins/UM3NetworkPrinting/src/LegacyUM3PrinterOutputController.py b/plugins/UM3NetworkPrinting/src/LegacyUM3PrinterOutputController.py
index 702b48ce15..9e372d4113 100644
--- a/plugins/UM3NetworkPrinting/src/LegacyUM3PrinterOutputController.py
+++ b/plugins/UM3NetworkPrinting/src/LegacyUM3PrinterOutputController.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.
from cura.PrinterOutput.PrinterOutputController import PrinterOutputController
@@ -7,8 +7,8 @@ from UM.Version import Version
MYPY = False
if MYPY:
- from cura.PrinterOutput.PrintJobOutputModel import PrintJobOutputModel
- from cura.PrinterOutput.PrinterOutputModel import PrinterOutputModel
+ from cura.PrinterOutput.Models.PrintJobOutputModel import PrintJobOutputModel
+ from cura.PrinterOutput.Models.PrinterOutputModel import PrinterOutputModel
class LegacyUM3PrinterOutputController(PrinterOutputController):
@@ -33,9 +33,9 @@ class LegacyUM3PrinterOutputController(PrinterOutputController):
data = "{\"target\": \"%s\"}" % state
self._output_device.put("print_job/state", data, on_finished=None)
- def setTargetBedTemperature(self, printer: "PrinterOutputModel", temperature: int):
+ def setTargetBedTemperature(self, printer: "PrinterOutputModel", temperature: float):
data = str(temperature)
- self._output_device.put("printer/bed/temperature/target", data, on_finished=self._onPutBedTemperatureCompleted)
+ 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"):
diff --git a/plugins/UM3NetworkPrinting/src/MeshFormatHandler.py b/plugins/UM3NetworkPrinting/src/MeshFormatHandler.py
new file mode 100644
index 0000000000..c3cd82a86d
--- /dev/null
+++ b/plugins/UM3NetworkPrinting/src/MeshFormatHandler.py
@@ -0,0 +1,115 @@
+# Copyright (c) 2018 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+import io
+from typing import Optional, Dict, Union, List, cast
+
+from UM.FileHandler.FileHandler import FileHandler
+from UM.FileHandler.FileWriter import FileWriter
+from UM.Logger import Logger
+from UM.OutputDevice import OutputDeviceError # To show that something went wrong when writing.
+from UM.Scene.SceneNode import SceneNode
+from UM.Version import Version # To check against firmware versions for support.
+from UM.i18n import i18nCatalog
+from cura.CuraApplication import CuraApplication
+
+
+I18N_CATALOG = i18nCatalog("cura")
+
+
+## This class is responsible for choosing the formats used by the connected clusters.
+class MeshFormatHandler:
+
+ def __init__(self, file_handler: Optional[FileHandler], firmware_version: str) -> None:
+ self._file_handler = file_handler or CuraApplication.getInstance().getMeshFileHandler()
+ self._preferred_format = self._getPreferredFormat(firmware_version)
+ self._writer = self._getWriter(self.mime_type) if self._preferred_format else None
+
+ @property
+ def is_valid(self) -> bool:
+ return bool(self._writer)
+
+ ## Chooses the preferred file format.
+ # \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]]]:
+ return self._preferred_format
+
+ ## Gets the file writer for the given file handler and mime type.
+ # \return A file writer.
+ @property
+ def writer(self) -> Optional[FileWriter]:
+ return self._writer
+
+ @property
+ def mime_type(self) -> str:
+ return cast(str, self._preferred_format["mime_type"])
+
+ ## Gets the file mode (FileWriter.OutputMode.TextMode or FileWriter.OutputMode.BinaryMode)
+ @property
+ def file_mode(self) -> int:
+ return cast(int, self._preferred_format["mode"])
+
+ ## Gets the file extension
+ @property
+ def file_extension(self) -> str:
+ return cast(str, self._preferred_format["extension"])
+
+ ## Creates the right kind of stream based on the preferred format.
+ def createStream(self) -> Union[io.BytesIO, io.StringIO]:
+ if self.file_mode == FileWriter.OutputMode.TextMode:
+ return io.StringIO()
+ else:
+ return io.BytesIO()
+
+ ## Writes the mesh and returns its value.
+ def getBytes(self, nodes: List[SceneNode]) -> bytes:
+ if self.writer is None:
+ raise ValueError("There is no writer for the mesh format handler.")
+ stream = self.createStream()
+ self.writer.write(stream, nodes)
+ value = stream.getvalue()
+ if isinstance(value, str):
+ value = value.encode()
+ return value
+
+ ## Chooses the preferred file format for the given file handler.
+ # \param firmware_version: The version of the firmware.
+ # \return A dict with the file format details.
+ def _getPreferredFormat(self, firmware_version: str) -> Dict[str, Union[str, int, bool]]:
+ # Formats supported by this application (file types that we can actually write).
+ application = CuraApplication.getInstance()
+
+ file_formats = self._file_handler.getSupportedFileTypesWrite()
+
+ global_stack = application.getGlobalContainerStack()
+ # Create a list from the supported file formats string.
+ if not global_stack:
+ Logger.log("e", "Missing global stack!")
+ return {}
+
+ 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
+
+ # Take the intersection between file_formats and machine_file_formats.
+ format_by_mimetype = {f["mime_type"]: f for f in file_formats}
+
+ # Keep them ordered according to the preference in machine_file_formats.
+ file_formats = [format_by_mimetype[mimetype] for mimetype in machine_file_formats]
+
+ if len(file_formats) == 0:
+ Logger.log("e", "There are no file formats available to write with!")
+ raise OutputDeviceError.WriteRequestFailedError(
+ I18N_CATALOG.i18nc("@info:status", "There are no file formats available to write with!")
+ )
+ return file_formats[0]
+
+ ## Gets the file writer for the given file handler and mime type.
+ # \param mime_type: The mine type.
+ # \return A file writer.
+ def _getWriter(self, mime_type: str) -> Optional[FileWriter]:
+ # Just take the first file format available.
+ return self._file_handler.getWriterByMimeType(mime_type)
diff --git a/plugins/UM3NetworkPrinting/src/Models.py b/plugins/UM3NetworkPrinting/src/Models.py
new file mode 100644
index 0000000000..c5b9b16665
--- /dev/null
+++ b/plugins/UM3NetworkPrinting/src/Models.py
@@ -0,0 +1,46 @@
+# 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/SendMaterialJob.py b/plugins/UM3NetworkPrinting/src/SendMaterialJob.py
index 8491e79c29..f0fde818c4 100644
--- a/plugins/UM3NetworkPrinting/src/SendMaterialJob.py
+++ b/plugins/UM3NetworkPrinting/src/SendMaterialJob.py
@@ -1,99 +1,197 @@
-# 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 #To understand the list of materials from the printer reply.
-import os #To walk over material files.
-import os.path #To filter on material files.
-from PyQt5.QtNetwork import QNetworkReply, QNetworkRequest #To listen to the reply from the printer.
-from typing import Any, Dict, Set, TYPE_CHECKING
-import urllib.parse #For getting material IDs from their file names.
+import json
+import os
+from typing import Dict, TYPE_CHECKING, Set, Optional
+from PyQt5.QtNetwork import QNetworkReply, QNetworkRequest
-from UM.Job import Job #The interface we're implementing.
+from UM.Job import Job
from UM.Logger import Logger
-from UM.MimeTypeDatabase import MimeTypeDatabase #To strip the extensions of the material profile files.
-from UM.Resources import Resources
-from UM.Settings.ContainerRegistry import ContainerRegistry #To find the GUIDs of materials.
+from cura.CuraApplication import CuraApplication
-from cura.CuraApplication import CuraApplication #For the resource types.
+# Absolute imports don't work in plugins
+from .Models import ClusterMaterial, LocalMaterial
if TYPE_CHECKING:
from .ClusterUM3OutputDevice import ClusterUM3OutputDevice
+
## Asynchronous job to send material profiles to the printer.
#
# This way it won't freeze up the interface while sending those materials.
class SendMaterialJob(Job):
+
def __init__(self, device: "ClusterUM3OutputDevice") -> None:
super().__init__()
- self.device = device #type: ClusterUM3OutputDevice
+ self.device = device # type: ClusterUM3OutputDevice
+ ## Send the request to the printer and register a callback
def run(self) -> None:
- self.device.get("materials/", on_finished = self.sendMissingMaterials)
+ self.device.get("materials/", on_finished = self._onGetRemoteMaterials)
- def sendMissingMaterials(self, reply: QNetworkReply) -> None:
- if reply.attribute(QNetworkRequest.HttpStatusCodeAttribute) != 200: #Got an error from the HTTP request.
- Logger.log("e", "Couldn't request current material storage on printer. Not syncing materials.")
+ ## 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
- remote_materials_list = reply.readAll().data().decode("utf-8")
+ # 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)
+
+ ## 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
+ }
+
+ ## 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()
+
+ for root_material_id in material_group_dict:
+ if root_material_id not in materials_to_send:
+ # If the material does not have to be sent we skip it.
+ continue
+
+ file_path = container_registry.getContainerFilePathById(root_material_id)
+ if not file_path:
+ Logger.log("w", "Cannot get file path for material container [%s]", root_material_id)
+ continue
+
+ file_name = os.path.basename(file_path)
+ 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.
+ def _sendMaterialFile(self, file_path: str, file_name: str, material_id: str) -> None:
+ parts = []
+
+ # Add the material file.
+ with open(file_path, "rb") as f:
+ parts.append(self.device.createFormPart("name=\"file\"; filename=\"{file_name}\""
+ .format(file_name = file_name), f.read()))
+
+ # Add the material signature file if needed.
+ signature_file_path = "{}.sig".format(file_path)
+ if os.path.exists(signature_file_path):
+ signature_file_name = os.path.basename(signature_file_path)
+ with open(signature_file_path, "rb") as f:
+ 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)
+
+ ## Check a reply from an upload to the printer and log an error when the call failed
+ @staticmethod
+ def sendingFinished(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_list = json.loads(remote_materials_list)
+ 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.")
- return
- try:
- remote_materials_by_guid = {material["guid"]: material for material in remote_materials_list} #Index by GUID.
- except KeyError:
- Logger.log("e", "Request material storage on printer: Printer's answer was missing GUIDs.")
- return
+ 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
- container_registry = ContainerRegistry.getInstance()
- local_materials_list = filter(lambda material: ("GUID" in material and "version" in material and "id" in material), container_registry.findContainersMetadata(type = "material"))
- local_materials_by_guid = {material["GUID"]: material for material in local_materials_list if material["id"] == material["base_file"]}
- for material in local_materials_list: #For each GUID get the material with the highest version number.
- try:
- if int(material["version"]) > local_materials_by_guid[material["GUID"]]["version"]:
- local_materials_by_guid[material["GUID"]] = material
- except ValueError:
- Logger.log("e", "Material {material_id} has invalid version number {number}.".format(material_id = material["id"], number = material["version"]))
- continue
+ ## 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]:
+ result = {} # type: Dict[str, LocalMaterial]
+ material_manager = CuraApplication.getInstance().getMaterialManager()
+
+ material_group_dict = material_manager.getAllMaterialGroups()
+
+ # 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()
- materials_to_send = set() #type: Set[Dict[str, Any]]
- for guid, material in local_materials_by_guid.items():
- if guid not in remote_materials_by_guid:
- materials_to_send.add(material["id"])
- continue
try:
- if int(material["version"]) > remote_materials_by_guid[guid]["version"]:
- materials_to_send.add(material["id"])
- continue
+ # 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
+
+ if local_material.GUID not in result or \
+ local_material.GUID not in result or \
+ local_material.version > result[local_material.GUID].version:
+ result[local_material.GUID] = local_material
+
except KeyError:
- Logger.log("e", "Current material storage on printer was an invalid reply (missing version).")
- return
+ Logger.logException("w", "Local material {} has missing values.".format(material_metadata["id"]))
+ except ValueError:
+ Logger.logException("w", "Local material {} has invalid values.".format(material_metadata["id"]))
+ except TypeError:
+ Logger.logException("w", "Local material {} has invalid values.".format(material_metadata["id"]))
- for file_path in Resources.getAllResourcesOfType(CuraApplication.ResourceTypes.MaterialInstanceContainer):
- try:
- mime_type = MimeTypeDatabase.getMimeTypeForFile(file_path)
- except MimeTypeDatabase.MimeTypeNotFoundError:
- continue #Not the sort of file we'd like to send then.
- _, file_name = os.path.split(file_path)
- material_id = urllib.parse.unquote_plus(mime_type.stripExtension(file_name))
- if material_id not in materials_to_send:
- continue
-
- parts = []
- with open(file_path, "rb") as f:
- parts.append(self.device._createFormPart("name=\"file\"; filename=\"{file_name}\"".format(file_name = file_name), f.read()))
- signature_file_path = file_path + ".sig"
- if os.path.exists(signature_file_path):
- _, signature_file_name = os.path.split(signature_file_path)
- with open(signature_file_path, "rb") as f:
- 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)
-
- def sendingFinished(self, reply: QNetworkReply):
- if reply.attribute(QNetworkRequest.HttpStatusCodeAttribute) != 200:
- Logger.log("e", "Received error code from printer when syncing material: {code}".format(code = reply.attribute(QNetworkRequest.HttpStatusCodeAttribute)))
- Logger.log("e", reply.readAll().data().decode("utf-8"))
\ No newline at end of file
+ return result
diff --git a/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py b/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py
index 9c070f2de2..f1607334eb 100644
--- a/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py
+++ b/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py
@@ -1,23 +1,58 @@
-# Copyright (c) 2017 Ultimaker B.V.
+# Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
+import json
+import os
+from queue import Queue
+from threading import Event, Thread
+from time import time
+from typing import Optional, TYPE_CHECKING, Dict, Callable, Union, Any
-from UM.OutputDevice.OutputDevicePlugin import OutputDevicePlugin
+from zeroconf import Zeroconf, ServiceBrowser, ServiceStateChange, ServiceInfo
+
+from PyQt5.QtNetwork import QNetworkRequest, QNetworkReply, QNetworkAccessManager
+from PyQt5.QtCore import QUrl
+from PyQt5.QtGui import QDesktopServices
+
+from cura.CuraApplication import CuraApplication
+from cura.PrinterOutput.PrinterOutputDevice import ConnectionType
+
+from UM.i18n import i18nCatalog
from UM.Logger import Logger
-from UM.Application import Application
+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 .Cloud.CloudOutputDeviceManager import CloudOutputDeviceManager
+from .Cloud.CloudOutputDevice import CloudOutputDevice # typing
-from PyQt5.QtNetwork import QNetworkRequest, QNetworkAccessManager
-from PyQt5.QtCore import QUrl
+if TYPE_CHECKING:
+ from PyQt5.QtNetwork import QNetworkReply
+ from UM.OutputDevice.OutputDevicePlugin import OutputDevicePlugin
+ from cura.PrinterOutput.PrinterOutputDevice import PrinterOutputDevice
+ from cura.Settings.GlobalStack import GlobalStack
-from zeroconf import Zeroconf, ServiceBrowser, ServiceStateChange, ServiceInfo
-from queue import Queue
-from threading import Event, Thread
-from time import time
-import json
+i18n_catalog = i18nCatalog("cura")
+
+
+#
+# Represents a request for adding a manual printer. It has the following fields:
+# - address: The string of the (IP) address of the manual printer
+# - callback: (Optional) Once the HTTP request to the printer to get printer information is done, whether successful
+# or not, this callback will be invoked to notify about the result. The callback must have a signature of
+# func(success: bool, address: str) -> None
+# - network_reply: This is the QNetworkReply instance for this request if the request has been issued and still in
+# progress. It is kept here so we can cancel a request when needed.
+#
+class ManualPrinterRequest:
+ def __init__(self, address: str, callback: Optional[Callable[[bool, str], None]] = None) -> None:
+ self.address = address
+ self.callback = callback
+ self.network_reply = None # type: Optional["QNetworkReply"]
## This plugin handles the connection detection & creation of output device objects for the UM3 printer.
@@ -25,27 +60,35 @@ import json
# If we discover a printer that has the same key as the active machine instance a connection is made.
@signalemitter
class UM3OutputDevicePlugin(OutputDevicePlugin):
- addDeviceSignal = Signal()
- removeDeviceSignal = Signal()
+ addDeviceSignal = Signal() # Called '...Signal' to avoid confusion with function-names.
+ removeDeviceSignal = Signal() # Ditto ^^^.
discoveredDevicesChanged = Signal()
+ cloudFlowIsPossible = Signal()
def __init__(self):
super().__init__()
+
self._zero_conf = None
self._zero_conf_browser = None
+ self._application = CuraApplication.getInstance()
+
+ # 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)
- Application.getInstance().globalContainerStackChanged.connect(self.reCheckConnections)
+ self._application.globalContainerStackChanged.connect(self.refreshConnections)
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 + "/"
@@ -53,14 +96,16 @@ class UM3OutputDevicePlugin(OutputDevicePlugin):
self._cluster_api_prefix = "/cluster-api/v" + self._cluster_api_version + "/"
# Get list of manual instances from preferences
- self._preferences = Application.getInstance().getPreferences()
+ 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(",")
+ manual_instances = self._preferences.getValue("um3networkprinting/manual_instances").split(",")
+ self._manual_instances = {address: ManualPrinterRequest(address)
+ for address in manual_instances} # type: Dict[str, ManualPrinterRequest]
# Store the last manual entry key
- self._last_manual_entry_key = "" # type: str
+ 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.
@@ -71,6 +116,26 @@ class UM3OutputDevicePlugin(OutputDevicePlugin):
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
@@ -83,6 +148,7 @@ class UM3OutputDevicePlugin(OutputDevicePlugin):
## Start looking for devices on network.
def start(self):
self.startDiscovery()
+ self._cloud_output_device_manager.start()
def startDiscovery(self):
self.stop()
@@ -103,8 +169,9 @@ class UM3OutputDevicePlugin(OutputDevicePlugin):
self.addManualDevice(address)
self.resetLastManualDevice()
- def reCheckConnections(self):
- active_machine = Application.getInstance().getGlobalContainerStack()
+ # TODO: CHANGE TO HOSTNAME
+ def refreshConnections(self):
+ active_machine = CuraApplication.getInstance().getGlobalContainerStack()
if not active_machine:
return
@@ -114,6 +181,8 @@ class UM3OutputDevicePlugin(OutputDevicePlugin):
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:
@@ -129,9 +198,10 @@ class UM3OutputDevicePlugin(OutputDevicePlugin):
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 = Application.getInstance().getGlobalContainerStack().getMetaDataEntry("um_network_key")
+ um_network_key = CuraApplication.getInstance().getGlobalContainerStack().getMetaDataEntry("um_network_key")
if key == um_network_key:
self.getOutputDeviceManager().addOutputDevice(self._discovered_devices[key])
+ self.checkCloudFlowIsPossible(None)
else:
self.getOutputDeviceManager().removeOutputDevice(key)
@@ -139,8 +209,16 @@ class UM3OutputDevicePlugin(OutputDevicePlugin):
if self._zero_conf is not None:
Logger.log("d", "zeroconf close...")
self._zero_conf.close()
+ self._cloud_output_device_manager.stop()
+
+ def canAddManualDevice(self, address: str = "") -> ManualDeviceAdditionAttempt:
+ # This plugin should always be the fallback option (at least try it):
+ return ManualDeviceAdditionAttempt.POSSIBLE
+
+ def removeManualDevice(self, key: str, address: Optional[str] = None) -> None:
+ if key not in self._discovered_devices and address is not None:
+ key = "manual:%s" % address
- def removeManualDevice(self, key, address = None):
if key in self._discovered_devices:
if not address:
address = self._discovered_devices[key].ipAddress
@@ -148,13 +226,18 @@ class UM3OutputDevicePlugin(OutputDevicePlugin):
self.resetLastManualDevice()
if address in self._manual_instances:
- self._manual_instances.remove(address)
- self._preferences.setValue("um3networkprinting/manual_instances", ",".join(self._manual_instances))
+ manual_printer_request = self._manual_instances.pop(address)
+ self._preferences.setValue("um3networkprinting/manual_instances", ",".join(self._manual_instances.keys()))
- 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))
+ if manual_printer_request.network_reply is not None:
+ manual_printer_request.network_reply.abort()
+
+ if manual_printer_request.callback is not None:
+ self._application.callLater(manual_printer_request.callback, False, address)
+
+ def addManualDevice(self, address: str, callback: Optional[Callable[[bool, str], None]] = None) -> None:
+ self._manual_instances[address] = ManualPrinterRequest(address, callback = callback)
+ self._preferences.setValue("um3networkprinting/manual_instances", ",".join(self._manual_instances.keys()))
instance_name = "manual:%s" % address
properties = {
@@ -170,31 +253,92 @@ class UM3OutputDevicePlugin(OutputDevicePlugin):
self._onAddDevice(instance_name, address, properties)
self._last_manual_entry_key = instance_name
- self._checkManualDevice(address)
+ reply = self._checkManualDevice(address)
+ self._manual_instances[address].network_reply = reply
- def _checkManualDevice(self, address):
+ def _createMachineFromDiscoveredPrinter(self, key: str) -> None:
+ discovered_device = self._discovered_devices.get(key)
+ if discovered_device is None:
+ Logger.log("e", "Could not find discovered device with key [%s]", key)
+ return
+
+ group_name = discovered_device.getProperty("name")
+ machine_type_id = discovered_device.getProperty("printer_type")
+
+ Logger.log("i", "Creating machine from network device with key = [%s], group name = [%s], printer type = [%s]",
+ key, group_name, machine_type_id)
+
+ self._application.getMachineManager().addMachine(machine_type_id, group_name)
+ # connect the new machine to that network printer
+ self.associateActiveMachineWithPrinterDevice(discovered_device)
+ # ensure that the connection states are refreshed.
+ self.refreshConnections()
+
+ 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)
+
+ machine_manager = CuraApplication.getInstance().getMachineManager()
+ global_container_stack = machine_manager.activeMachine
+ if not global_container_stack:
+ return
+
+ for machine in machine_manager.getMachinesInGroup(global_container_stack.getMetaDataEntry("group_id")):
+ machine.setMetaDataEntry("um_network_key", printer_device.key)
+ machine.setMetaDataEntry("group_name", printer_device.name)
+
+ # 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)
+
+ machine.removeMetaDataEntry("network_authentication_id")
+ machine.removeMetaDataEntry("network_authentication_key")
+
+ # Ensure that these containers do know that they are configured for network connection
+ machine.addConfiguredConnectionType(printer_device.connectionType.value)
+
+ self.refreshConnections()
+
+ def _checkManualDevice(self, address: str) -> "QNetworkReply":
# 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)
+ return self._network_manager.get(name_request)
- def _onNetworkRequestFinished(self, reply):
+ def _onNetworkRequestFinished(self, reply: "QNetworkReply") -> None:
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
+ address = reply.url().host()
+ device = None
+ properties = {} # type: Dict[bytes, bytes]
+ if reply.attribute(QNetworkRequest.HttpStatusCodeAttribute) != 200:
+ # Either:
+ # - Something went wrong with checking the firmware version!
+ # - Something went wrong with checking the amount of printers the cluster has!
+ # - Couldn't find printer at the address when trying to add it manually.
+ if address in self._manual_instances:
+ key = "manual:" + address
+ self.removeManualDevice(key, address)
+ return
+
+ if "system" in reply_url:
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()
+ if address in self._manual_instances:
+ manual_printer_request = self._manual_instances[address]
+ manual_printer_request.network_reply = None
+ if manual_printer_request.callback is not None:
+ self._application.callLater(manual_printer_request.callback, True, address)
+
has_cluster_capable_firmware = Version(system_info["firmware"]) > self._min_cluster_version
instance_name = "manual:%s" % address
properties = {
@@ -222,27 +366,23 @@ class UM3OutputDevicePlugin(OutputDevicePlugin):
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)
+ properties[b"cluster_size"] = str(len(cluster_printers_list)).encode("utf-8")
self._onRemoveDevice(instance_name)
self._onAddDevice(instance_name, address, properties)
- def _onRemoveDevice(self, device_id):
+ def _onRemoveDevice(self, device_id: str) -> None:
device = self._discovered_devices.pop(device_id, None)
if device:
if device.isConnected():
@@ -252,20 +392,31 @@ class UM3OutputDevicePlugin(OutputDevicePlugin):
except TypeError:
# Disconnect already happened.
pass
-
+ self._application.getDiscoveredPrintersModel().removeDiscoveredPrinter(device.address)
self.discoveredDevicesChanged.emit()
+ ## 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.
+ def _getPrinterTypeIdentifiers(self) -> Dict[str, str]:
+ container_registry = self._application.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_bom_number = machine.get("firmware_update_info", {}).get("id", None)
+ machine_type = machine.get("id", None)
+ if machine_bom_number and machine_type:
+ found_machine_type_identifiers[str(machine_bom_number)] = machine_type
+
+ return found_machine_type_identifiers
+
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"
- }
+ printer_type_identifiers = self._getPrinterTypeIdentifiers()
for key, value in printer_type_identifiers.items():
if printer_type.startswith(key):
@@ -277,12 +428,16 @@ class UM3OutputDevicePlugin(OutputDevicePlugin):
device = ClusterUM3OutputDevice.ClusterUM3OutputDevice(name, address, properties)
else:
device = LegacyUM3OutputDevice.LegacyUM3OutputDevice(name, address, properties)
-
+ self._application.getDiscoveredPrintersModel().addDiscoveredPrinter(
+ address, device.getId(), properties[b"name"].decode("utf-8"), self._createMachineFromDiscoveredPrinter,
+ properties[b"printer_type"].decode("utf-8"), device)
self._discovered_devices[device.getId()] = device
self.discoveredDevicesChanged.emit()
- global_container_stack = Application.getInstance().getGlobalContainerStack()
+ 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)
@@ -299,7 +454,7 @@ class UM3OutputDevicePlugin(OutputDevicePlugin):
self._service_changed_request_event.wait(timeout = 5.0)
# Stop if the application is shutting down
- if Application.getInstance().isShuttingDown():
+ if CuraApplication.getInstance().isShuttingDown():
return
self._service_changed_request_event.clear()
@@ -325,13 +480,12 @@ class UM3OutputDevicePlugin(OutputDevicePlugin):
## 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 carefull calling it from the main thread.
+ # 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:
- Logger.log("d", "Bonjour service added: %s" % name)
-
# First try getting info from zero-conf cache
- info = ServiceInfo(service_type, name, properties={})
+ info = ServiceInfo(service_type, name, properties = {})
for record in zero_conf.cache.entries_with_name(name.lower()):
info.update_record(zero_conf, time(), record)
@@ -342,7 +496,6 @@ class UM3OutputDevicePlugin(OutputDevicePlugin):
# Request more data if info is not complete
if not info.address:
- Logger.log("d", "Trying to get address of %s", name)
info = zero_conf.get_service_info(service_type, name)
if info:
@@ -362,4 +515,143 @@ class UM3OutputDevicePlugin(OutputDevicePlugin):
Logger.log("d", "Bonjour service removed: %s" % name)
self.removeDeviceSignal.emit(str(name))
- return True
\ No newline at end of file
+ return True
+
+ ## Check if the prerequsites are in place to start the cloud flow
+ def checkCloudFlowIsPossible(self, cluster: Optional[CloudOutputDevice]) -> 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
+
+ # 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
+
+ # 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._createCloudFlowStartMessage()
+ if self._start_cloud_flow_message and not self._start_cloud_flow_message.visible:
+ self._start_cloud_flow_message.show()
+
+ def _onCloudPrintingConfigured(self, device) -> None:
+ # Hide the cloud flow start message if it was hanging around already
+ # For example: if the user already had the browser openen and made the association themselves
+ if self._start_cloud_flow_message and self._start_cloud_flow_message.visible:
+ self._start_cloud_flow_message.hide()
+
+ # Cloud flow is complete, so show the message
+ if not self._cloud_flow_complete_message:
+ self._createCloudFlowCompleteMessage()
+ if self._cloud_flow_complete_message and not self._cloud_flow_complete_message.visible:
+ 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:
+
+ # The active machine _might_ not be the machine that was in the added cloud cluster and
+ # then this will hide the cloud message for the wrong machine. So we only set it if the
+ # host names match between the active machine and the newly added cluster
+ saved_host_name = active_machine.getMetaDataEntry("um_network_key", "").split('.')[0]
+ added_host_name = device.toDict()["host_name"]
+
+ if added_host_name == saved_host_name:
+ 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:
+ # Hide any left over messages
+ if self._start_cloud_flow_message is not None and self._start_cloud_flow_message.visible:
+ self._start_cloud_flow_message.hide()
+ if self._cloud_flow_complete_message is not None and self._cloud_flow_complete_message.visible:
+ self._cloud_flow_complete_message.hide()
+
+ # Check for cloud flow again with newly selected machine
+ self.checkCloudFlowIsPossible(None)
+
+ def _createCloudFlowStartMessage(self):
+ 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 Ultimaker Cloud is a brand name and shouldn't be translated.", "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)
+
+ def _createCloudFlowCompleteMessage(self):
+ 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!")
+ )
+ 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)
diff --git a/plugins/UM3NetworkPrinting/src/UM3PrintJobOutputModel.py b/plugins/UM3NetworkPrinting/src/UM3PrintJobOutputModel.py
new file mode 100644
index 0000000000..b627b6e9c8
--- /dev/null
+++ b/plugins/UM3NetworkPrinting/src/UM3PrintJobOutputModel.py
@@ -0,0 +1,28 @@
+# Copyright (c) 2018 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 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:
+ super().__init__(output_controller, key, name, parent)
+ self._configuration_changes = [] # type: List[ConfigurationChangeModel]
+
+ @pyqtProperty("QVariantList", notify=configurationChangesChanged)
+ def configurationChanges(self) -> List[ConfigurationChangeModel]:
+ return self._configuration_changes
+
+ def updateConfigurationChanges(self, changes: List[ConfigurationChangeModel]) -> None:
+ if len(self._configuration_changes) == 0 and len(changes) == 0:
+ return
+ self._configuration_changes = changes
+ self.configurationChangesChanged.emit()
diff --git a/plugins/UM3NetworkPrinting/src/__init__.py b/plugins/UM3NetworkPrinting/src/__init__.py
new file mode 100644
index 0000000000..659263c0d6
--- /dev/null
+++ b/plugins/UM3NetworkPrinting/src/__init__.py
@@ -0,0 +1,9 @@
+# Copyright (c) 2019 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+
+# Workaround for a race condition on certain systems where there
+# is a race condition between Arcus and PyQt. Importing Arcus
+# first seems to prevent Sip from going into a state where it
+# tries to create PyQt objects on a non-main thread.
+import Arcus #@UnusedImport
+import Savitar #@UnusedImport
\ No newline at end of file
diff --git a/plugins/UM3NetworkPrinting/tests/Cloud/Fixtures/__init__.py b/plugins/UM3NetworkPrinting/tests/Cloud/Fixtures/__init__.py
new file mode 100644
index 0000000000..777afc92c2
--- /dev/null
+++ b/plugins/UM3NetworkPrinting/tests/Cloud/Fixtures/__init__.py
@@ -0,0 +1,12 @@
+# 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
new file mode 100644
index 0000000000..4f9f47fc75
--- /dev/null
+++ b/plugins/UM3NetworkPrinting/tests/Cloud/Fixtures/getClusterStatusResponse.json
@@ -0,0 +1,95 @@
+{
+ "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
new file mode 100644
index 0000000000..5200e3b971
--- /dev/null
+++ b/plugins/UM3NetworkPrinting/tests/Cloud/Fixtures/getClusters.json
@@ -0,0 +1,17 @@
+{
+ "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
new file mode 100644
index 0000000000..caedcd8732
--- /dev/null
+++ b/plugins/UM3NetworkPrinting/tests/Cloud/Fixtures/postJobPrintResponse.json
@@ -0,0 +1,8 @@
+{
+ "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
new file mode 100644
index 0000000000..1304f3a9f6
--- /dev/null
+++ b/plugins/UM3NetworkPrinting/tests/Cloud/Fixtures/putJobUploadResponse.json
@@ -0,0 +1,9 @@
+{
+ "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
new file mode 100644
index 0000000000..f3f6970c54
--- /dev/null
+++ b/plugins/UM3NetworkPrinting/tests/Cloud/Models/__init__.py
@@ -0,0 +1,2 @@
+# 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
new file mode 100644
index 0000000000..e504509d67
--- /dev/null
+++ b/plugins/UM3NetworkPrinting/tests/Cloud/NetworkManagerMock.py
@@ -0,0 +1,105 @@
+# 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
new file mode 100644
index 0000000000..b79d009c31
--- /dev/null
+++ b/plugins/UM3NetworkPrinting/tests/Cloud/TestCloudApiClient.py
@@ -0,0 +1,117 @@
+# 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
new file mode 100644
index 0000000000..352efb292e
--- /dev/null
+++ b/plugins/UM3NetworkPrinting/tests/Cloud/TestCloudOutputDevice.py
@@ -0,0 +1,157 @@
+# 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.Models.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"
+ FRIENDLY_NAME = "My Friendly Printer"
+
+ 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,
+ friendly_name=self.FRIENDLY_NAME)
+
+ 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.FRIENDLY_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": True,
+ "can_control_manually": False,
+ "can_pause": True,
+ "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
new file mode 100644
index 0000000000..869b39440c
--- /dev/null
+++ b/plugins/UM3NetworkPrinting/tests/Cloud/TestCloudOutputDeviceManager.py
@@ -0,0 +1,126 @@
+# 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 ...src.Cloud.Models.CloudClusterResponse import CloudClusterResponse
+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 = []
+ for cluster in self.clusters_response.get("data", []):
+ response_clusters.append(CloudClusterResponse(**cluster).toDict())
+ 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.assertEqual([], 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
new file mode 100644
index 0000000000..f3f6970c54
--- /dev/null
+++ b/plugins/UM3NetworkPrinting/tests/Cloud/__init__.py
@@ -0,0 +1,2 @@
+# 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
new file mode 100644
index 0000000000..2cab110861
--- /dev/null
+++ b/plugins/UM3NetworkPrinting/tests/TestSendMaterialJob.py
@@ -0,0 +1,244 @@
+# 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.assertEqual(
+ [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.assertEqual(
+ [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
new file mode 100644
index 0000000000..f3f6970c54
--- /dev/null
+++ b/plugins/UM3NetworkPrinting/tests/__init__.py
@@ -0,0 +1,2 @@
+# Copyright (c) 2018 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
diff --git a/plugins/USBPrinting/AutoDetectBaudJob.py b/plugins/USBPrinting/AutoDetectBaudJob.py
index 8b37c4b29d..36e9637c47 100644
--- a/plugins/USBPrinting/AutoDetectBaudJob.py
+++ b/plugins/USBPrinting/AutoDetectBaudJob.py
@@ -4,6 +4,7 @@
from UM.Job import Job
from UM.Logger import Logger
+from .avr_isp import ispBase
from .avr_isp.stk500v2 import Stk500v2
from time import time, sleep
@@ -14,12 +15,12 @@ from serial import Serial, SerialException
# It tries a pre-set list of baud rates. All these baud rates are validated by requesting the temperature a few times
# and checking if the results make sense. If getResult() is not None, it was able to find a correct baud rate.
class AutoDetectBaudJob(Job):
- def __init__(self, serial_port):
+ def __init__(self, serial_port: int) -> None:
super().__init__()
self._serial_port = serial_port
- self._all_baud_rates = [115200, 250000, 230400, 57600, 38400, 19200, 9600]
+ self._all_baud_rates = [115200, 250000, 500000, 230400, 57600, 38400, 19200, 9600]
- def run(self):
+ def run(self) -> None:
Logger.log("d", "Auto detect baud rate started.")
wait_response_timeouts = [3, 15, 30]
wait_bootloader_times = [1.5, 5, 15]
@@ -32,7 +33,7 @@ class AutoDetectBaudJob(Job):
try:
programmer.connect(self._serial_port)
serial = programmer.leaveISP()
- except:
+ except ispBase.IspError:
programmer.close()
for retry in range(tries):
@@ -58,7 +59,7 @@ class AutoDetectBaudJob(Job):
# We already have a serial connection, just change the baud rate.
try:
serial.baudrate = baud_rate
- except:
+ except ValueError:
continue
sleep(wait_bootloader) # Ensure that we are not talking to the boot loader. 1.5 seconds seems to be the magic number
successful_responses = 0
@@ -71,9 +72,9 @@ class AutoDetectBaudJob(Job):
while timeout_time > time():
line = serial.readline()
- if b"ok " in line and b"T:" in line:
+ if b"ok" in line and b"T:" in line:
successful_responses += 1
- if successful_responses >= 3:
+ if successful_responses >= 1:
self.setResult(baud_rate)
Logger.log("d", "Detected baud rate {baud_rate} on serial {serial} on retry {retry} with after {time_elapsed:0.2f} seconds.".format(
serial = self._serial_port, baud_rate = baud_rate, retry = retry, time_elapsed = time() - start_timeout_time))
@@ -81,5 +82,5 @@ class AutoDetectBaudJob(Job):
return
serial.write(b"M105\n")
- sleep(15) # Give the printer some time to init and try again.
+ sleep(15) # Give the printer some time to init and try again.
self.setResult(None) # Unable to detect the correct baudrate.
diff --git a/plugins/USBPrinting/AvrFirmwareUpdater.py b/plugins/USBPrinting/AvrFirmwareUpdater.py
new file mode 100644
index 0000000000..0f7146560d
--- /dev/null
+++ b/plugins/USBPrinting/AvrFirmwareUpdater.py
@@ -0,0 +1,68 @@
+# Copyright (c) 2018 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+
+from UM.Logger import Logger
+
+from cura.CuraApplication import CuraApplication
+from cura.PrinterOutput.FirmwareUpdater import FirmwareUpdater, FirmwareUpdateState
+
+from .avr_isp import stk500v2, intelHex
+from serial import SerialException
+
+from time import sleep
+
+MYPY = False
+if MYPY:
+ from cura.PrinterOutput.PrinterOutputDevice import PrinterOutputDevice
+
+
+class AvrFirmwareUpdater(FirmwareUpdater):
+ def __init__(self, output_device: "PrinterOutputDevice") -> None:
+ super().__init__(output_device)
+
+ def _updateFirmware(self) -> None:
+ try:
+ hex_file = intelHex.readHex(self._firmware_file)
+ assert len(hex_file) > 0
+ except (FileNotFoundError, AssertionError):
+ Logger.log("e", "Unable to read provided hex file. Could not update firmware.")
+ self._setFirmwareUpdateState(FirmwareUpdateState.firmware_not_found_error)
+ return
+
+ programmer = stk500v2.Stk500v2()
+ programmer.progress_callback = self._onFirmwareProgress
+
+ # Ensure that other connections are closed.
+ if self._output_device.isConnected():
+ self._output_device.close()
+
+ try:
+ programmer.connect(self._output_device._serial_port)
+ except:
+ programmer.close()
+ Logger.logException("e", "Failed to update firmware")
+ self._setFirmwareUpdateState(FirmwareUpdateState.communication_error)
+ return
+
+ # Give programmer some time to connect. Might need more in some cases, but this worked in all tested cases.
+ sleep(1)
+ if not programmer.isConnected():
+ Logger.log("e", "Unable to connect with serial. Could not update firmware")
+ self._setFirmwareUpdateState(FirmwareUpdateState.communication_error)
+ try:
+ programmer.programChip(hex_file)
+ except SerialException as e:
+ Logger.log("e", "A serial port exception occured during firmware update: %s" % e)
+ self._setFirmwareUpdateState(FirmwareUpdateState.io_error)
+ return
+ except Exception as e:
+ Logger.log("e", "An unknown exception occured during firmware update: %s" % e)
+ self._setFirmwareUpdateState(FirmwareUpdateState.unknown_error)
+ return
+
+ programmer.close()
+
+ # Try to re-connect with the machine again, which must be done on the Qt thread, so we use call later.
+ CuraApplication.getInstance().callLater(self._output_device.connect)
+
+ self._cleanupAfterUpdate()
diff --git a/plugins/USBPrinting/FirmwareUpdateWindow.qml b/plugins/USBPrinting/FirmwareUpdateWindow.qml
deleted file mode 100644
index e0f9de314e..0000000000
--- a/plugins/USBPrinting/FirmwareUpdateWindow.qml
+++ /dev/null
@@ -1,89 +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.Window 2.2
-import QtQuick.Controls 1.2
-
-import UM 1.1 as UM
-
-UM.Dialog
-{
- id: base;
-
- width: minimumWidth;
- minimumWidth: 500 * screenScaleFactor;
- height: minimumHeight;
- minimumHeight: 100 * screenScaleFactor;
-
- visible: true;
- modality: Qt.ApplicationModal;
-
- title: catalog.i18nc("@title:window","Firmware Update");
-
- Column
- {
- anchors.fill: parent;
-
- Label
- {
- anchors
- {
- left: parent.left;
- right: parent.right;
- }
-
- text: {
- switch (manager.firmwareUpdateState)
- {
- case 0:
- return "" //Not doing anything (eg; idling)
- case 1:
- return catalog.i18nc("@label","Updating firmware.")
- case 2:
- return catalog.i18nc("@label","Firmware update completed.")
- case 3:
- return catalog.i18nc("@label","Firmware update failed due to an unknown error.")
- case 4:
- return catalog.i18nc("@label","Firmware update failed due to an communication error.")
- case 5:
- return catalog.i18nc("@label","Firmware update failed due to an input/output error.")
- case 6:
- return catalog.i18nc("@label","Firmware update failed due to missing firmware.")
- }
- }
-
- wrapMode: Text.Wrap;
- }
-
- ProgressBar
- {
- id: prog
- value: manager.firmwareProgress
- minimumValue: 0
- maximumValue: 100
- indeterminate: manager.firmwareProgress < 1 && manager.firmwareProgress > 0
- anchors
- {
- left: parent.left;
- right: parent.right;
- }
- }
-
- SystemPalette
- {
- id: palette;
- }
-
- UM.I18nCatalog { id: catalog; name: "cura"; }
- }
-
- rightButtons: [
- Button
- {
- text: catalog.i18nc("@action:button","Close");
- enabled: manager.firmwareUpdateCompleteStatus;
- onClicked: base.visible = false;
- }
- ]
-}
diff --git a/plugins/USBPrinting/MonitorItem.qml b/plugins/USBPrinting/MonitorItem.qml
new file mode 100644
index 0000000000..c86353f814
--- /dev/null
+++ b/plugins/USBPrinting/MonitorItem.qml
@@ -0,0 +1,48 @@
+// Copyright (c) 2018 Ultimaker B.V.
+// Cura is released under the terms of the LGPLv3 or higher.
+
+import QtQuick 2.10
+import QtQuick.Controls 2.0
+import QtQuick.Layouts 1.3
+
+import UM 1.2 as UM
+import Cura 1.0 as Cura
+Component
+{
+ Item
+ {
+ Rectangle
+ {
+ color: UM.Theme.getColor("main_background")
+
+ anchors.right: parent.right
+ width: parent.width * 0.3
+ anchors.top: parent.top
+ anchors.bottom: parent.bottom
+
+ Cura.PrintMonitor
+ {
+ anchors.fill: parent
+ }
+
+ Rectangle
+ {
+ id: footerSeparator
+ width: parent.width
+ height: UM.Theme.getSize("wide_lining").height
+ color: UM.Theme.getColor("wide_lining")
+ anchors.bottom: monitorButton.top
+ anchors.bottomMargin: UM.Theme.getSize("thick_margin").height
+ }
+
+ // MonitorButton is actually the bottom footer panel.
+ Cura.MonitorButton
+ {
+ id: monitorButton
+ anchors.bottom: parent.bottom
+ anchors.left: parent.left
+ anchors.right: parent.right
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/plugins/USBPrinting/USBPrinterOutputDevice.py b/plugins/USBPrinting/USBPrinterOutputDevice.py
index 36c5321180..e32e4c8745 100644
--- a/plugins/USBPrinting/USBPrinterOutputDevice.py
+++ b/plugins/USBPrinting/USBPrinterOutputDevice.py
@@ -1,42 +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 UM.Logger import Logger
+import os
+
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 UM.PluginRegistry import PluginRegistry
from cura.CuraApplication import CuraApplication
-from cura.PrinterOutputDevice import PrinterOutputDevice, ConnectionState
-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 .avr_isp import stk500v2, intelHex
-
-from PyQt5.QtCore import pyqtSlot, pyqtSignal, pyqtProperty, QUrl
+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, sleep
-from queue import Queue
-from enum import IntEnum
-from typing import Union, Optional, List, cast
+from time import time
+from typing import Union, Optional, List, cast, TYPE_CHECKING
import re
import functools # Used for reduce
-import os
+
+if TYPE_CHECKING:
+ from UM.FileHandler.FileHandler import FileHandler
+ from UM.Scene.SceneNode import SceneNode
catalog = i18nCatalog("cura")
class USBPrinterOutputDevice(PrinterOutputDevice):
- firmwareProgressChanged = pyqtSignal()
- firmwareUpdateStateChanged = pyqtSignal()
-
def __init__(self, serial_port: str, baud_rate: Optional[int] = None) -> None:
- super().__init__(serial_port)
+ super().__init__(serial_port, connection_type = ConnectionType.UsbConnection)
self.setName(catalog.i18nc("@item:inmenu", "USB printing"))
self.setShortDescription(catalog.i18nc("@action:button Preceded by 'Ready to'.", "Print via USB"))
self.setDescription(catalog.i18nc("@info:tooltip", "Print via USB"))
@@ -56,14 +58,13 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
self._baud_rate = baud_rate
- self._all_baud_rates = [115200, 250000, 230400, 57600, 38400, 19200, 9600]
+ 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_firmware_thread = Thread(target=self._updateFirmware, daemon = True)
+ self._update_thread = Thread(target = self._update, daemon = True)
self._last_temperature_request = None # type: Optional[int]
+ self._firmware_idle_count = 0
self._is_printing = False # A print is being sent.
@@ -74,11 +75,7 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
self._accepts_commands = True
self._paused = False
-
- self._firmware_view = None
- self._firmware_location = None
- self._firmware_progress = 0
- self._firmware_update_state = FirmwareUpdateState.idle
+ self._printer_busy = False # When printer is preheating and waiting (M190/M109), or when waiting for action on the printer
self.setConnectionText(catalog.i18nc("@info:status", "Connected via USB"))
@@ -88,6 +85,11 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
self._command_received = Event()
self._command_received.set()
+ self._firmware_name_requested = False
+ self._firmware_updater = AvrFirmwareUpdater(self)
+
+ self._monitor_view_qml_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "MonitorItem.qml")
+
CuraApplication.getInstance().getOnExitCallbackManager().addCallback(self._checkActivePrintingUponAppExit)
# This is a callback function that checks if there is any printing in progress via USB when the application tries
@@ -109,127 +111,45 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
## Reset USB device settings
#
- def resetDeviceSettings(self):
+ def resetDeviceSettings(self) -> None:
self._firmware_name = None
## 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]
-
- self._printGCode(gcode_list)
-
- ## Show firmware interface.
- # This will create the view if its not already created.
- def showFirmwareInterface(self):
- if self._firmware_view is None:
- path = os.path.join(PluginRegistry.getInstance().getPluginPath("USBPrinting"), "FirmwareUpdateWindow.qml")
- self._firmware_view = CuraApplication.getInstance().createQmlComponent(path, {"manager": self})
-
- self._firmware_view.show()
-
- @pyqtSlot(str)
- def updateFirmware(self, file):
- # the file path could be url-encoded.
- if file.startswith("file://"):
- self._firmware_location = QUrl(file).toLocalFile()
- else:
- self._firmware_location = file
- self.showFirmwareInterface()
- self.setFirmwareUpdateState(FirmwareUpdateState.updating)
- self._update_firmware_thread.start()
-
- def _updateFirmware(self):
- # Ensure that other connections are closed.
- if self._connection_state != ConnectionState.closed:
- self.close()
-
- try:
- hex_file = intelHex.readHex(self._firmware_location)
- assert len(hex_file) > 0
- except (FileNotFoundError, AssertionError):
- Logger.log("e", "Unable to read provided hex file. Could not update firmware.")
- self.setFirmwareUpdateState(FirmwareUpdateState.firmware_not_found_error)
+ #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
- programmer = stk500v2.Stk500v2()
- programmer.progress_callback = self._onFirmwareProgress
-
- try:
- programmer.connect(self._serial_port)
- except:
- programmer.close()
- Logger.logException("e", "Failed to update firmware")
- self.setFirmwareUpdateState(FirmwareUpdateState.communication_error)
- return
-
- # Give programmer some time to connect. Might need more in some cases, but this worked in all tested cases.
- sleep(1)
- if not programmer.isConnected():
- Logger.log("e", "Unable to connect with serial. Could not update firmware")
- self.setFirmwareUpdateState(FirmwareUpdateState.communication_error)
- try:
- programmer.programChip(hex_file)
- except SerialException:
- self.setFirmwareUpdateState(FirmwareUpdateState.io_error)
- return
- except:
- self.setFirmwareUpdateState(FirmwareUpdateState.unknown_error)
- return
-
- programmer.close()
-
- # Clean up for next attempt.
- self._update_firmware_thread = Thread(target=self._updateFirmware, daemon=True)
- self._firmware_location = ""
- self._onFirmwareProgress(100)
- self.setFirmwareUpdateState(FirmwareUpdateState.completed)
-
- # Try to re-connect with the machine again, which must be done on the Qt thread, so we use call later.
- CuraApplication.getInstance().callLater(self.connect)
-
- @pyqtProperty(float, notify = firmwareProgressChanged)
- def firmwareProgress(self):
- return self._firmware_progress
-
- @pyqtProperty(int, notify=firmwareUpdateStateChanged)
- def firmwareUpdateState(self):
- return self._firmware_update_state
-
- def setFirmwareUpdateState(self, state):
- if self._firmware_update_state != state:
- self._firmware_update_state = state
- self.firmwareUpdateStateChanged.emit()
-
- # Callback function for firmware update progress.
- def _onFirmwareProgress(self, progress, max_progress = 100):
- self._firmware_progress = (progress / max_progress) * 100 # Convert to scale of 0-100
- self.firmwareProgressChanged.emit()
+ 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")
@@ -258,7 +178,7 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
self._baud_rate = baud_rate
def connect(self):
- self._firmware_name = None # after each connection ensure that the firmware name is removed
+ self._firmware_name = None # after each connection ensure that the firmware name is removed
if self._baud_rate is None:
if self._use_auto_detect:
@@ -270,15 +190,21 @@ 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()
+ self.setConnectionState(ConnectionState.Connected)
+ self._update_thread.start()
+
+ def _onGlobalContainerStackChanged(self):
container_stack = CuraApplication.getInstance().getGlobalContainerStack()
num_extruders = container_stack.getProperty("machine_extruder_count", "value")
# Ensure that a printer is created.
- self._printers = [PrinterOutputModel(output_controller=GenericOutputController(self), number_of_extruders=num_extruders)]
+ controller = GenericOutputController(self)
+ controller.setCanUpdateFirmware(True)
+ self._printers = [PrinterOutputModel(output_controller = controller, number_of_extruders = num_extruders)]
self._printers[0].updateName(container_stack.getName())
- self.setConnectionState(ConnectionState.connected)
- self._update_thread.start()
def close(self):
super().close()
@@ -295,8 +221,9 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
self._command_queue.put(command)
else:
self._sendCommand(command)
+
def _sendCommand(self, command: Union[str, bytes]):
- if self._serial is None or self._connection_state != ConnectionState.connected:
+ if self._serial is None or self._connection_state != ConnectionState.Connected:
return
new_command = cast(bytes, command) if type(command) is bytes else cast(str, command).encode() # type: bytes
@@ -308,26 +235,32 @@ 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:
+ while self._connection_state == ConnectionState.Connected and self._serial is not None:
try:
line = self._serial.readline()
except:
continue
+ if not self._firmware_name_requested:
+ self._firmware_name_requested = True
+ self.sendCommand("M115")
+
+ if b"FIRMWARE_NAME:" in line:
+ self._setFirmwareName(line)
+
if self._last_temperature_request is None or time() > self._last_temperature_request + self._timeout:
# Timeout, or no request has been sent at all.
- self._command_received.set() # We haven't really received the ok, but we need to send a new command
-
- self.sendCommand("M105")
- self._last_temperature_request = time()
-
- if self._firmware_name is None:
- self.sendCommand("M115")
+ if not self._printer_busy: # Don't flood the printer with temperature requests while it is busy
+ self.sendCommand("M105")
+ self._last_temperature_request = time()
if re.search(b"[B|T\d*]: ?\d+\.?\d*", line): # Temperature message. 'T:' for extruder and 'B:' for bed
- extruder_temperature_matches = re.findall(b"T(\d*): ?(\d+\.?\d*) ?\/?(\d+\.?\d*)?", line)
+ extruder_temperature_matches = re.findall(b"T(\d*): ?(\d+\.?\d*)\s*\/?(\d+\.?\d*)?", line)
# Update all temperature values
matched_extruder_nrs = []
for match in extruder_temperature_matches:
@@ -349,7 +282,7 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
if match[2]:
extruder.updateTargetHotendTemperature(float(match[2]))
- bed_temperature_matches = re.findall(b"B: ?(\d+\.?\d*) ?\/?(\d+\.?\d*) ?", line)
+ bed_temperature_matches = re.findall(b"B: ?(\d+\.?\d*)\s*\/?(\d+\.?\d*)?", line)
if bed_temperature_matches:
match = bed_temperature_matches[0]
if match[0]:
@@ -357,29 +290,39 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
if match[1]:
self._printers[0].updateTargetBedTemperature(float(match[1]))
- if b"FIRMWARE_NAME:" in line:
- self._setFirmwareName(line)
+ if line == b"":
+ # An empty line means that the firmware is idle
+ # Multiple empty lines probably means that the firmware and Cura are waiting
+ # for eachother due to a missed "ok", so we keep track of empty lines
+ self._firmware_idle_count += 1
+ else:
+ self._firmware_idle_count = 0
+
+ if line.startswith(b"ok") or self._firmware_idle_count > 1:
+ self._printer_busy = False
- if b"ok" in line:
self._command_received.set()
if not self._command_queue.empty():
self._sendCommand(self._command_queue.get())
- if self._is_printing:
+ elif self._is_printing:
if self._paused:
pass # Nothing to do!
else:
self._sendNextGcodeLine()
+ if line.startswith(b"echo:busy:"):
+ self._printer_busy = True
+
if self._is_printing:
if line.startswith(b'!!'):
Logger.log('e', "Printer signals fatal error. Cancelling print. {}".format(line))
self.cancelPrint()
- elif b"resend" in line.lower() or b"rs" in line:
+ elif line.lower().startswith(b"resend") or line.startswith(b"rs"):
# A resend can be requested either by Resend, resend or rs.
try:
self._gcode_position = int(line.replace(b"N:", b" ").replace(b"N", b" ").replace(b":", b" ").split()[-1])
except:
- if b"rs" in line:
+ if line.startswith(b"rs"):
# In some cases of the RS command it needs to be handled differently.
self._gcode_position = int(line.split()[1])
@@ -440,12 +383,21 @@ 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:
- print_job = PrintJobOutputModel(output_controller = GenericOutputController(self), name= CuraApplication.getInstance().getPrintInformation().jobName)
+ controller = GenericOutputController(self)
+ controller.setCanUpdateFirmware(True)
+ print_job = PrintJobOutputModel(output_controller=controller, name=CuraApplication.getInstance().getPrintInformation().jobName)
print_job.updateState("printing")
self._printers[0].updateActivePrintJob(print_job)
@@ -456,13 +408,3 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
print_job.updateTimeTotal(estimated_time)
self._gcode_position += 1
-
-
-class FirmwareUpdateState(IntEnum):
- idle = 0
- updating = 1
- completed = 2
- unknown_error = 3
- communication_error = 4
- io_error = 5
- firmware_not_found_error = 6
diff --git a/plugins/USBPrinting/USBPrinterOutputDeviceManager.py b/plugins/USBPrinting/USBPrinterOutputDeviceManager.py
index 2ee85187ee..56f53145b0 100644
--- a/plugins/USBPrinting/USBPrinterOutputDeviceManager.py
+++ b/plugins/USBPrinting/USBPrinterOutputDeviceManager.py
@@ -2,20 +2,18 @@
# Cura is released under the terms of the LGPLv3 or higher.
import threading
-import platform
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.Resources import Resources
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
@@ -68,7 +66,7 @@ class USBPrinterOutputDeviceManager(QObject, OutputDevicePlugin):
return
changed_device = self._usb_output_devices[serial_port]
- if changed_device.connectionState == ConnectionState.connected:
+ if changed_device.connectionState == ConnectionState.Connected:
self.getOutputDeviceManager().addOutputDevice(changed_device)
else:
self.getOutputDeviceManager().removeOutputDevice(serial_port)
@@ -87,65 +85,6 @@ class USBPrinterOutputDeviceManager(QObject, OutputDevicePlugin):
self._addRemovePorts(port_list)
time.sleep(5)
- @pyqtSlot(result = str)
- def getDefaultFirmwareName(self):
- # Check if there is a valid global container stack
- global_container_stack = self._application.getGlobalContainerStack()
- if not global_container_stack:
- Logger.log("e", "There is no global container stack. Can not update firmware.")
- self._firmware_view.close()
- return ""
-
- # The bottom of the containerstack is the machine definition
- machine_id = global_container_stack.getBottom().id
-
- machine_has_heated_bed = global_container_stack.getProperty("machine_heated_bed", "value")
-
- if platform.system() == "Linux":
- baudrate = 115200
- else:
- baudrate = 250000
-
- # NOTE: The keyword used here is the id of the machine. You can find the id of your machine in the *.json file, eg.
- # https://github.com/Ultimaker/Cura/blob/master/resources/machines/ultimaker_original.json#L2
- # The *.hex files are stored at a seperate repository:
- # https://github.com/Ultimaker/cura-binary-data/tree/master/cura/resources/firmware
- machine_without_extras = {"bq_witbox" : "MarlinWitbox.hex",
- "bq_hephestos_2" : "MarlinHephestos2.hex",
- "ultimaker_original" : "MarlinUltimaker-{baudrate}.hex",
- "ultimaker_original_plus" : "MarlinUltimaker-UMOP-{baudrate}.hex",
- "ultimaker_original_dual" : "MarlinUltimaker-{baudrate}-dual.hex",
- "ultimaker2" : "MarlinUltimaker2.hex",
- "ultimaker2_go" : "MarlinUltimaker2go.hex",
- "ultimaker2_plus" : "MarlinUltimaker2plus.hex",
- "ultimaker2_extended" : "MarlinUltimaker2extended.hex",
- "ultimaker2_extended_plus" : "MarlinUltimaker2extended-plus.hex",
- }
- machine_with_heated_bed = {"ultimaker_original" : "MarlinUltimaker-HBK-{baudrate}.hex",
- "ultimaker_original_dual" : "MarlinUltimaker-HBK-{baudrate}-dual.hex",
- }
- ##TODO: Add check for multiple extruders
- hex_file = None
- if machine_id in machine_without_extras.keys(): # The machine needs to be defined here!
- if machine_id in machine_with_heated_bed.keys() and machine_has_heated_bed:
- Logger.log("d", "Choosing firmware with heated bed enabled for machine %s.", machine_id)
- hex_file = machine_with_heated_bed[machine_id] # Return firmware with heated bed enabled
- else:
- Logger.log("d", "Choosing basic firmware for machine %s.", machine_id)
- hex_file = machine_without_extras[machine_id] # Return "basic" firmware
- else:
- Logger.log("w", "There is no firmware for machine %s.", machine_id)
-
- if hex_file:
- try:
- return Resources.getPath(CuraApplication.ResourceTypes.Firmware, hex_file.format(baudrate=baudrate))
- except FileNotFoundError:
- Logger.log("w", "Could not find any firmware for machine %s.", machine_id)
- return ""
- else:
- Logger.log("w", "Could not find any firmware for machine %s.", machine_id)
- return ""
-
## Helper to identify serial ports (and scan for them)
def _addRemovePorts(self, serial_ports):
# First, find and add all new or changed keys
@@ -175,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/__init__.py b/plugins/USBPrinting/__init__.py
index fd5488eead..075ad2943b 100644
--- a/plugins/USBPrinting/__init__.py
+++ b/plugins/USBPrinting/__init__.py
@@ -2,9 +2,6 @@
# Cura is released under the terms of the LGPLv3 or higher.
from . import USBPrinterOutputDeviceManager
-from PyQt5.QtQml import qmlRegisterSingletonType
-from UM.i18n import i18nCatalog
-i18n_catalog = i18nCatalog("cura")
def getMetaData():
@@ -14,5 +11,4 @@ def getMetaData():
def register(app):
# We are violating the QT API here (as we use a factory, which is technically not allowed).
# but we don't really have another means for doing this (and it seems to you know -work-)
- qmlRegisterSingletonType(USBPrinterOutputDeviceManager.USBPrinterOutputDeviceManager, "Cura", 1, 0, "USBPrinterManager", USBPrinterOutputDeviceManager.USBPrinterOutputDeviceManager.getInstance)
return {"output_device": USBPrinterOutputDeviceManager.USBPrinterOutputDeviceManager(app)}
diff --git a/plugins/USBPrinting/plugin.json b/plugins/USBPrinting/plugin.json
index 3484c8a48a..45971d858b 100644
--- a/plugins/USBPrinting/plugin.json
+++ b/plugins/USBPrinting/plugin.json
@@ -1,8 +1,8 @@
{
"name": "USB printing",
"author": "Ultimaker B.V.",
- "version": "1.0.0",
- "api": 5,
+ "version": "1.0.2",
+ "api": "6.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
index 6ff3f0b629..999cb1d35a 100644
--- a/plugins/UltimakerMachineActions/UM2UpgradeSelection.py
+++ b/plugins/UltimakerMachineActions/UM2UpgradeSelection.py
@@ -1,13 +1,15 @@
# 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 PyQt5.QtCore import pyqtSignal, pyqtProperty
+from UM.Settings.ContainerRegistry import ContainerRegistry
from UM.i18n import i18nCatalog
from UM.Application import Application
from UM.Util import parseBool
+
+from cura.MachineAction import MachineAction
+
catalog = i18nCatalog("cura")
diff --git a/plugins/UltimakerMachineActions/UM2UpgradeSelectionMachineAction.qml b/plugins/UltimakerMachineActions/UM2UpgradeSelectionMachineAction.qml
index 793f3f00a8..13525f6eb3 100644
--- a/plugins/UltimakerMachineActions/UM2UpgradeSelectionMachineAction.qml
+++ b/plugins/UltimakerMachineActions/UM2UpgradeSelectionMachineAction.qml
@@ -1,49 +1,46 @@
-// 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 2.");
+ text: catalog.i18nc("@label", "Please select any upgrades made to this Ultimaker 2.")
+ font: UM.Theme.getFont("medium")
+ color: UM.Theme.getColor("text")
+ renderType: Text.NativeRendering
}
- CheckBox
+ Cura.CheckBox
{
id: olssonBlockCheckBox
anchors.top: pageDescription.bottom
anchors.topMargin: UM.Theme.getSize("default_margin").height
+ height: UM.Theme.getSize("setting_control").height
+
text: catalog.i18nc("@label", "Olsson Block")
checked: manager.hasVariants
onClicked: manager.hasVariants = checked
@@ -54,7 +51,5 @@ Cura.MachineAction
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 b92638aa12..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 usbConnected: Cura.USBPrinterManager.connectedPrinterList.rowCount() > 0
-
- 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.usbConnected ? 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.usbConnected
- }
- 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.usbConnected
- }
- //////////////////////////////////////////////////////////////
- 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.usbConnected
- }
- 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.usbConnected
- }
- /////////////////////////////////////////////////////////////////////
- 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.usbConnected
- }
- 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.usbConnected
- }
- ////////////////////////////////////////////////////////////
- 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.usbConnected
- }
- 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.usbConnected
- }
- 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.usbConnected
- 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.usbConnected
- }
- /////////////////////////////////////////////////////////////////////////////
- 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.usbConnected && 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.usbConnected && 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.usbConnected && 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.usbConnected && 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/UpgradeFirmwareMachineAction.py b/plugins/UltimakerMachineActions/UpgradeFirmwareMachineAction.py
deleted file mode 100644
index 1f0e640f04..0000000000
--- a/plugins/UltimakerMachineActions/UpgradeFirmwareMachineAction.py
+++ /dev/null
@@ -1,19 +0,0 @@
-from UM.Application import Application
-from UM.Settings.DefinitionContainer import DefinitionContainer
-from cura.MachineAction import MachineAction
-from UM.i18n import i18nCatalog
-from UM.Settings.ContainerRegistry import ContainerRegistry
-
-catalog = i18nCatalog("cura")
-
-## Upgrade the firmware of a machine by USB with this action.
-class UpgradeFirmwareMachineAction(MachineAction):
- def __init__(self):
- super().__init__("UpgradeFirmware", catalog.i18nc("@action", "Upgrade Firmware"))
- self._qml_url = "UpgradeFirmwareMachineAction.qml"
- ContainerRegistry.getInstance().containerAdded.connect(self._onContainerAdded)
-
- def _onContainerAdded(self, container):
- # Add this action as a supported action to all machine definitions if they support USB connection
- if isinstance(container, DefinitionContainer) and container.getMetaDataEntry("type") == "machine" and container.getMetaDataEntry("supports_usb_connection"):
- Application.getInstance().getMachineActionManager().addSupportedAction(container.getId(), self.getKey())
diff --git a/plugins/UltimakerMachineActions/UpgradeFirmwareMachineAction.qml b/plugins/UltimakerMachineActions/UpgradeFirmwareMachineAction.qml
deleted file mode 100644
index ed771d2a04..0000000000
--- a/plugins/UltimakerMachineActions/UpgradeFirmwareMachineAction.qml
+++ /dev/null
@@ -1,93 +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 QtQuick.Dialogs 1.2 // For filedialog
-
-import UM 1.2 as UM
-import Cura 1.0 as Cura
-
-
-Cura.MachineAction
-{
- anchors.fill: parent;
- property bool printerConnected: Cura.MachineManager.printerConnected
- property var activeOutputDevice: printerConnected ? Cura.MachineManager.printerOutputDevices[0] : null
-
- Item
- {
- id: upgradeFirmwareMachineAction
- anchors.fill: parent;
- UM.I18nCatalog { id: catalog; name:"cura"}
-
- Label
- {
- id: pageTitle
- width: parent.width
- text: catalog.i18nc("@title", "Upgrade Firmware")
- 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", "Firmware is the piece of software running directly on your 3D printer. This firmware controls the step motors, regulates the temperature and ultimately makes your printer work.")
- }
-
- Label
- {
- id: upgradeText1
- anchors.top: pageDescription.bottom
- anchors.topMargin: UM.Theme.getSize("default_margin").height
- width: parent.width
- wrapMode: Text.WordWrap
- text: catalog.i18nc("@label", "The firmware shipping with new printers works, but new versions tend to have more features and improvements.");
- }
-
- Row
- {
- anchors.top: upgradeText1.bottom
- anchors.topMargin: UM.Theme.getSize("default_margin").height
- anchors.horizontalCenter: parent.horizontalCenter
- width: childrenRect.width
- spacing: UM.Theme.getSize("default_margin").width
- property var firmwareName: Cura.USBPrinterManager.getDefaultFirmwareName()
- Button
- {
- id: autoUpgradeButton
- text: catalog.i18nc("@action:button", "Automatically upgrade Firmware");
- enabled: parent.firmwareName != "" && activeOutputDevice
- onClicked:
- {
- activeOutputDevice.updateFirmware(parent.firmwareName)
- }
- }
- Button
- {
- id: manualUpgradeButton
- text: catalog.i18nc("@action:button", "Upload custom Firmware");
- enabled: activeOutputDevice != null
- onClicked:
- {
- customFirmwareDialog.open()
- }
- }
- }
-
- FileDialog
- {
- id: customFirmwareDialog
- title: catalog.i18nc("@title:window", "Select custom firmware")
- nameFilters: "Firmware image files (*.hex)"
- selectExisting: true
- onAccepted: activeOutputDevice.updateFirmware(fileUrl)
- }
- }
-}
\ No newline at end of file
diff --git a/plugins/UltimakerMachineActions/__init__.py b/plugins/UltimakerMachineActions/__init__.py
index 495f212736..e87949580a 100644
--- a/plugins/UltimakerMachineActions/__init__.py
+++ b/plugins/UltimakerMachineActions/__init__.py
@@ -1,22 +1,16 @@
-# Copyright (c) 2016 Ultimaker B.V.
+# Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
from . import BedLevelMachineAction
-from . import UpgradeFirmwareMachineAction
from . import UMOUpgradeSelection
from . import UM2UpgradeSelection
-from UM.i18n import i18nCatalog
-catalog = i18nCatalog("cura")
-
def getMetaData():
- return {
- }
+ return {}
def register(app):
return { "machine_action": [
BedLevelMachineAction.BedLevelMachineAction(),
- UpgradeFirmwareMachineAction.UpgradeFirmwareMachineAction(),
UMOUpgradeSelection.UMOUpgradeSelection(),
UM2UpgradeSelection.UM2UpgradeSelection()
]}
diff --git a/plugins/UltimakerMachineActions/plugin.json b/plugins/UltimakerMachineActions/plugin.json
index b60c7df88e..3e3e0af9b0 100644
--- a/plugins/UltimakerMachineActions/plugin.json
+++ b/plugins/UltimakerMachineActions/plugin.json
@@ -1,8 +1,8 @@
{
"name": "Ultimaker machine actions",
"author": "Ultimaker B.V.",
- "version": "1.0.0",
+ "version": "1.0.1",
"description": "Provides machine actions for Ultimaker machines (such as bed leveling wizard, selecting upgrades, etc.).",
- "api": 5,
+ "api": "6.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 4ee03f4ad5..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 50a2aa0441..0000000000
--- a/plugins/UserAgreement/plugin.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "name": "UserAgreement",
- "author": "Ultimaker B.V.",
- "version": "1.0.0",
- "description": "Ask the user once if he/she agrees with our license.",
- "api": 5,
- "i18n-catalog": "cura"
-}
diff --git a/plugins/VersionUpgrade/VersionUpgrade21to22/MachineInstance.py b/plugins/VersionUpgrade/VersionUpgrade21to22/MachineInstance.py
index 37b6989add..ff5c33517d 100644
--- a/plugins/VersionUpgrade/VersionUpgrade21to22/MachineInstance.py
+++ b/plugins/VersionUpgrade/VersionUpgrade21to22/MachineInstance.py
@@ -1,14 +1,16 @@
-# Copyright (c) 2016 Ultimaker B.V.
+# Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
-import UM.VersionUpgrade #To indicate that a file is of incorrect format.
-import UM.VersionUpgradeManager #To schedule more files to be upgraded.
-from UM.Resources import Resources #To get the config storage path.
-
import configparser #To read config files.
import io #To write config files to strings as if they were files.
import os.path #To get the path to write new user profiles to.
+from typing import Dict, List, Optional, Set, Tuple
import urllib #To serialise the user container file name properly.
+import urllib.parse
+
+import UM.VersionUpgrade #To indicate that a file is of incorrect format.
+import UM.VersionUpgradeManager #To schedule more files to be upgraded.
+from UM.Resources import Resources #To get the config storage path.
## Creates a new machine instance instance by parsing a serialised machine
# instance in version 1 of the file format.
@@ -18,7 +20,7 @@ import urllib #To serialise the user container file name properly.
# extension.
# \return A machine instance instance, or None if the file format is
# incorrect.
-def importFrom(serialised, filename):
+def importFrom(serialised: str, filename: str) -> Optional["MachineInstance"]:
try:
return MachineInstance(serialised, filename)
except (configparser.Error, UM.VersionUpgrade.FormatException, UM.VersionUpgrade.InvalidVersionException):
@@ -32,7 +34,7 @@ class MachineInstance:
# \param serialised A string with the contents of a machine instance file,
# without extension.
# \param filename The supposed file name of this machine instance.
- def __init__(self, serialised, filename):
+ def __init__(self, serialised: str, filename: str) -> None:
self._filename = filename
config = configparser.ConfigParser(interpolation = None)
@@ -53,11 +55,11 @@ class MachineInstance:
self._type_name = config.get("general", "type")
self._variant_name = config.get("general", "variant", fallback = "empty_variant")
self._name = config.get("general", "name", fallback = "")
- self._key = config.get("general", "key", fallback = None)
+ self._key = config.get("general", "key", fallback = "")
self._active_profile_name = config.get("general", "active_profile", fallback = "empty_quality")
self._active_material_name = config.get("general", "material", fallback = "empty_material")
- self._machine_setting_overrides = {}
+ self._machine_setting_overrides = {} # type: Dict[str, str]
for key, value in config["machine_settings"].items():
self._machine_setting_overrides[key] = value
@@ -67,7 +69,7 @@ class MachineInstance:
#
# \return A tuple containing the new filename and a serialised form of
# this machine instance, serialised in version 2 of the file format.
- def export(self):
+ def export(self) -> Tuple[List[str], List[str]]:
config = configparser.ConfigParser(interpolation = None) # Build a config file in the form of version 2.
config.add_section("general")
@@ -108,7 +110,7 @@ class MachineInstance:
version_upgrade_manager = UM.VersionUpgradeManager.VersionUpgradeManager.getInstance()
user_version_to_paths_dict = version_upgrade_manager.getStoragePaths("user")
- paths_set = set()
+ paths_set = set() # type: Set[str]
for paths in user_version_to_paths_dict.values():
paths_set |= paths
diff --git a/plugins/VersionUpgrade/VersionUpgrade21to22/Preferences.py b/plugins/VersionUpgrade/VersionUpgrade21to22/Preferences.py
index 842499da86..953837b863 100644
--- a/plugins/VersionUpgrade/VersionUpgrade21to22/Preferences.py
+++ b/plugins/VersionUpgrade/VersionUpgrade21to22/Preferences.py
@@ -1,8 +1,9 @@
-# Copyright (c) 2016 Ultimaker B.V.
+# Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
import configparser #To read config files.
import io #To output config files to string.
+from typing import List, Optional, Tuple
import UM.VersionUpgrade #To indicate that a file is of the wrong format.
@@ -14,7 +15,7 @@ import UM.VersionUpgrade #To indicate that a file is of the wrong format.
# extension.
# \return A representation of those preferences, or None if the file format is
# incorrect.
-def importFrom(serialised, filename):
+def importFrom(serialised: str, filename: str) -> Optional["Preferences"]:
try:
return Preferences(serialised, filename)
except (configparser.Error, UM.VersionUpgrade.FormatException, UM.VersionUpgrade.InvalidVersionException):
@@ -28,7 +29,7 @@ class Preferences:
# \param serialised A serialised version 2 preferences file.
# \param filename The supposed filename of the preferences file, without
# extension.
- def __init__(self, serialised, filename):
+ def __init__(self, serialised: str, filename: str) -> None:
self._filename = filename
self._config = configparser.ConfigParser(interpolation = None)
@@ -50,7 +51,7 @@ class Preferences:
#
# \return A tuple containing the new filename and a serialised version of
# a preferences file in version 3.
- def export(self):
+ def export(self) -> Tuple[List[str], List[str]]:
#Reset the cura/categories_expanded property since it works differently now.
if self._config.has_section("cura") and self._config.has_option("cura", "categories_expanded"):
self._config.remove_option("cura", "categories_expanded")
@@ -58,11 +59,11 @@ class Preferences:
#Translate the setting names in the visible settings.
if self._config.has_section("machines") and self._config.has_option("machines", "setting_visibility"):
visible_settings = self._config.get("machines", "setting_visibility")
- visible_settings = visible_settings.split(",")
+ visible_settings_list = visible_settings.split(",")
import VersionUpgrade21to22 #Import here to prevent a circular dependency.
- visible_settings = [VersionUpgrade21to22.VersionUpgrade21to22.VersionUpgrade21to22.translateSettingName(setting_name)
- for setting_name in visible_settings]
- visible_settings = ",".join(visible_settings)
+ visible_settings_list = [VersionUpgrade21to22.VersionUpgrade21to22.VersionUpgrade21to22.translateSettingName(setting_name)
+ for setting_name in visible_settings_list]
+ visible_settings = ",".join(visible_settings_list)
self._config.set("machines", "setting_visibility", value = visible_settings)
#Translate the active_instance key.
diff --git a/plugins/VersionUpgrade/VersionUpgrade21to22/Profile.py b/plugins/VersionUpgrade/VersionUpgrade21to22/Profile.py
index 161edcb67c..af9635d384 100644
--- a/plugins/VersionUpgrade/VersionUpgrade21to22/Profile.py
+++ b/plugins/VersionUpgrade/VersionUpgrade21to22/Profile.py
@@ -1,10 +1,9 @@
-# Copyright (c) 2016 Ultimaker B.V.
+# Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
import configparser #To read config files.
import io #To write config files to strings as if they were files.
-from typing import Dict
-from typing import List
+from typing import Dict, List, Optional, Tuple
import UM.VersionUpgrade
from UM.Logger import Logger
@@ -15,7 +14,7 @@ from UM.Logger import Logger
# \param serialised The serialised form of a profile in version 1.
# \param filename The supposed filename of the profile, without extension.
# \return A profile instance, or None if the file format is incorrect.
-def importFrom(serialised, filename):
+def importFrom(serialised: str, filename: str) -> Optional["Profile"]:
try:
return Profile(serialised, filename)
except (configparser.Error, UM.VersionUpgrade.FormatException, UM.VersionUpgrade.InvalidVersionException):
@@ -77,11 +76,11 @@ class Profile:
#
# \return A tuple containing the new filename and a serialised form of
# this profile, serialised in version 2 of the file format.
- def export(self):
+ def export(self) -> Optional[Tuple[List[str], List[str]]]:
import VersionUpgrade21to22 # Import here to prevent circular dependencies.
if self._name == "Current settings":
- return None, None #Can't upgrade these, because the new current profile needs to specify the definition ID and the old file only had the machine instance, not the definition.
+ return None #Can't upgrade these, because the new current profile needs to specify the definition ID and the old file only had the machine instance, not the definition.
config = configparser.ConfigParser(interpolation = None)
diff --git a/plugins/VersionUpgrade/VersionUpgrade21to22/VersionUpgrade21to22.py b/plugins/VersionUpgrade/VersionUpgrade21to22/VersionUpgrade21to22.py
index d8036491bf..536385b19d 100644
--- a/plugins/VersionUpgrade/VersionUpgrade21to22/VersionUpgrade21to22.py
+++ b/plugins/VersionUpgrade/VersionUpgrade21to22/VersionUpgrade21to22.py
@@ -1,7 +1,8 @@
-# Copyright (c) 2017 Ultimaker B.V.
+# Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
import configparser #To get version numbers from config files.
+from typing import Dict, Iterable, List, Optional, Set, Tuple
from UM.VersionUpgrade import VersionUpgrade # Superclass of the plugin.
@@ -30,7 +31,7 @@ _machines_with_machine_quality = {
"materials": { "generic_abs", "generic_cpe", "generic_pla", "generic_pva", "generic_cpe_plus", "generic_nylon", "generic_pc", "generic_tpu" },
"variants": { "0.25 mm", "0.4 mm", "0.6 mm", "0.8 mm" }
}
-}
+} # type: Dict[str, Dict[str, Set[str]]]
## How to translate material names from the old version to the new.
_material_translations = {
@@ -41,7 +42,7 @@ _material_translations = {
"Nylon": "generic_nylon",
"PC": "generic_pc",
"TPU": "generic_tpu",
-}
+} # type: Dict[str, str]
## How to translate material names for in the profile names.
_material_translations_profiles = {
@@ -52,17 +53,17 @@ _material_translations_profiles = {
"Nylon": "nylon",
"PC": "pc",
"TPU": "tpu",
-}
+} # type: Dict[str, str]
## How to translate printer names from the old version to the new.
_printer_translations = {
"ultimaker2plus": "ultimaker2_plus"
-}
+} # type: Dict[str, str]
_printer_translations_profiles = {
"ultimaker2plus": "um2p", #Does NOT get included in PLA profiles!
"ultimaker2_extended_plus": "um2ep" #Has no profiles for CPE+, Nylon, PC and TPU!
-}
+} # type: Dict[str, str]
## How to translate profile names from the old version to the new.
#
@@ -116,13 +117,13 @@ _profile_translations = {
"tpu_0.25_high": "um2p_tpu_0.25_high",
"tpu_0.4_normal": "um2p_tpu_0.4_normal",
"tpu_0.6_fast": "um2p_tpu_0.6_fast"
-}
+} # type: Dict[str, str]
## Settings that are no longer in the new version.
_removed_settings = {
"fill_perimeter_gaps",
"support_area_smoothing"
-}
+} # type: Set[str]
## How to translate setting names from the old version to the new.
_setting_name_translations = {
@@ -142,7 +143,7 @@ _setting_name_translations = {
"support_roof_line_distance": "support_interface_line_distance",
"support_roof_line_width": "support_interface_line_width",
"support_roof_pattern": "support_interface_pattern"
-}
+} # type: Dict[str, str]
## Custom profiles become quality_changes. This dictates which quality to base
# the quality_changes profile on.
@@ -190,7 +191,7 @@ _quality_fallbacks = {
#No TPU.
}
}
-}
+} # type: Dict[str, Dict[str, Dict[str, str]]]
## How to translate variants of specific machines from the old version to the
# new.
@@ -207,7 +208,7 @@ _variant_translations = {
"0.6 mm": "ultimaker2_extended_plus_0.6",
"0.8 mm": "ultimaker2_extended_plus_0.8"
}
-}
+} # type: Dict[str, Dict[str, str]]
## How to translate variant names for in the profile names.
_variant_translations_profiles = {
@@ -215,7 +216,7 @@ _variant_translations_profiles = {
"0.4 mm": "0.4",
"0.6 mm": "0.6",
"0.8 mm": "0.8"
-}
+} # type: Dict[str, str]
## Cura 2.2's material profiles use a different naming scheme for variants.
#
@@ -233,7 +234,7 @@ _variant_translations_materials = {
"0.6 mm": "ultimaker2_plus_0.6_mm",
"0.8 mm": "ultimaker2_plus_0.8_mm"
}
-}
+} # type: Dict[str, Dict[str, str]]
## Converts configuration from Cura 2.1's file formats to Cura 2.2's.
#
@@ -245,12 +246,12 @@ class VersionUpgrade21to22(VersionUpgrade):
# number is stored in general/version, so get the data from that key.
#
# \param serialised The contents of a config file.
- # \return \type{int} The version number of that config file.
- def getCfgVersion(self, serialised):
+ # \return The version number of that config file.
+ 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))
+ setting_version = int(parser.get("metadata", "setting_version", fallback = "0"))
return format_version * 1000000 + setting_version
## Gets the fallback quality to use for a specific machine-variant-material
@@ -263,7 +264,7 @@ class VersionUpgrade21to22(VersionUpgrade):
# \param variant The variant ID of the user's configuration in 2.2.
# \param material The material ID of the user's configuration in 2.2.
@staticmethod
- def getQualityFallback(machine, variant, material):
+ def getQualityFallback(machine: str, variant: str, material: str) -> str:
if machine not in _quality_fallbacks:
return "normal"
if variant not in _quality_fallbacks[machine]:
@@ -277,14 +278,14 @@ class VersionUpgrade21to22(VersionUpgrade):
# This is required to test if profiles should be converted to a quality
# profile or a quality-changes profile.
@staticmethod
- def builtInProfiles():
+ def builtInProfiles() -> Iterable[str]:
return _profile_translations.keys()
## Gets a set of the machines which now have per-material quality profiles.
#
# \return A set of machine identifiers.
@staticmethod
- def machinesWithMachineQuality():
+ def machinesWithMachineQuality() -> Dict[str, Dict[str, Set[str]]]:
return _machines_with_machine_quality
## Converts machine instances from format version 1 to version 2.
@@ -295,10 +296,10 @@ class VersionUpgrade21to22(VersionUpgrade):
# \return A tuple containing the new filename and the serialised machine
# instance in version 2, or None if the input was not of the correct
# format.
- def upgradeMachineInstance(self, serialised, filename):
+ def upgradeMachineInstance(self, serialised: str, filename: str) -> Optional[Tuple[List[str], List[str]]]:
machine_instance = MachineInstance.importFrom(serialised, filename)
if not machine_instance: #Invalid file format.
- return filename, None
+ return None
return machine_instance.export()
## Converts preferences from format version 2 to version 3.
@@ -309,10 +310,10 @@ class VersionUpgrade21to22(VersionUpgrade):
# \return A tuple containing the new filename and the serialised
# preferences in version 3, or None if the input was not of the correct
# format.
- def upgradePreferences(self, serialised, filename):
+ def upgradePreferences(self, serialised: str, filename: str) -> Optional[Tuple[List[str], List[str]]]:
preferences = Preferences.importFrom(serialised, filename)
if not preferences: #Invalid file format.
- return filename, None
+ return None
return preferences.export()
## Converts profiles from format version 1 to version 2.
@@ -322,10 +323,10 @@ class VersionUpgrade21to22(VersionUpgrade):
# extension.
# \return A tuple containing the new filename and the serialised profile
# in version 2, or None if the input was not of the correct format.
- def upgradeProfile(self, serialised, filename):
+ def upgradeProfile(self, serialised: str, filename: str) -> Optional[Tuple[List[str], List[str]]]:
profile = Profile.importFrom(serialised, filename)
if not profile: # Invalid file format.
- return filename, None
+ return None
return profile.export()
## Translates a material name for the change from Cura 2.1 to 2.2.
@@ -333,7 +334,7 @@ class VersionUpgrade21to22(VersionUpgrade):
# \param material A material name in Cura 2.1.
# \return The name of the corresponding material in Cura 2.2.
@staticmethod
- def translateMaterial(material):
+ def translateMaterial(material: str) -> str:
if material in _material_translations:
return _material_translations[material]
return material
@@ -345,7 +346,7 @@ class VersionUpgrade21to22(VersionUpgrade):
# \return The name of the corresponding material in the quality profiles
# in Cura 2.2.
@staticmethod
- def translateMaterialForProfiles(material):
+ def translateMaterialForProfiles(material: str) -> str:
if material in _material_translations_profiles:
return _material_translations_profiles[material]
return material
@@ -356,7 +357,7 @@ class VersionUpgrade21to22(VersionUpgrade):
# \param printer A printer name in Cura 2.1.
# \return The name of the corresponding printer in Cura 2.2.
@staticmethod
- def translatePrinter(printer):
+ def translatePrinter(printer: str) -> str:
if printer in _printer_translations:
return _printer_translations[printer]
return printer #Doesn't need to be translated.
@@ -367,7 +368,7 @@ class VersionUpgrade21to22(VersionUpgrade):
# \param printer A printer name in 2.1.
# \return The name of the corresponding printer in Cura 2.2.
@staticmethod
- def translatePrinterForProfile(printer):
+ def translatePrinterForProfile(printer: str) -> str:
if printer in _printer_translations_profiles:
return _printer_translations_profiles[printer]
return printer
@@ -378,7 +379,7 @@ class VersionUpgrade21to22(VersionUpgrade):
# \param profile A profile name in the old version.
# \return The corresponding profile name in the new version.
@staticmethod
- def translateProfile(profile):
+ def translateProfile(profile: str) -> str:
if profile in _profile_translations:
return _profile_translations[profile]
return profile #Doesn't need to be translated.
@@ -392,7 +393,7 @@ class VersionUpgrade21to22(VersionUpgrade):
# \param settings A dictionary of settings (as key-value pairs) to update.
# \return The same dictionary.
@staticmethod
- def translateSettings(settings):
+ def translateSettings(settings: Dict[str, str]) -> Dict[str, str]:
new_settings = {}
for key, value in settings.items():
if key in _removed_settings:
@@ -414,7 +415,7 @@ class VersionUpgrade21to22(VersionUpgrade):
# \param setting The name of a setting in Cura 2.1.
# \return The name of the corresponding setting in Cura 2.2.
@staticmethod
- def translateSettingName(setting):
+ def translateSettingName(setting: str) -> str:
if setting in _setting_name_translations:
return _setting_name_translations[setting]
return setting #Doesn't need to be translated.
@@ -426,7 +427,7 @@ class VersionUpgrade21to22(VersionUpgrade):
# 2.2's naming.
# \return The name of the corresponding variant in Cura 2.2.
@staticmethod
- def translateVariant(variant, machine):
+ def translateVariant(variant: str, machine: str) -> str:
if machine in _variant_translations and variant in _variant_translations[machine]:
return _variant_translations[machine][variant]
return variant
@@ -440,7 +441,7 @@ class VersionUpgrade21to22(VersionUpgrade):
# \return The name of the corresponding variant for in material profiles
# in Cura 2.2.
@staticmethod
- def translateVariantForMaterials(variant, machine):
+ def translateVariantForMaterials(variant: str, machine: str) -> str:
if machine in _variant_translations_materials and variant in _variant_translations_materials[machine]:
return _variant_translations_materials[machine][variant]
return variant
@@ -452,7 +453,7 @@ class VersionUpgrade21to22(VersionUpgrade):
# \return The name of the corresponding variant for in quality profiles in
# Cura 2.2.
@staticmethod
- def translateVariantForProfiles(variant):
+ def translateVariantForProfiles(variant: str) -> str:
if variant in _variant_translations_profiles:
return _variant_translations_profiles[variant]
return variant
\ No newline at end of file
diff --git a/plugins/VersionUpgrade/VersionUpgrade21to22/__init__.py b/plugins/VersionUpgrade/VersionUpgrade21to22/__init__.py
index 609781ebfe..67530b9d45 100644
--- a/plugins/VersionUpgrade/VersionUpgrade21to22/__init__.py
+++ b/plugins/VersionUpgrade/VersionUpgrade21to22/__init__.py
@@ -1,11 +1,16 @@
-# Copyright (c) 2016 Ultimaker B.V.
+# Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
+from typing import Any, Dict, TYPE_CHECKING
+
from . import VersionUpgrade21to22
+if TYPE_CHECKING:
+ from UM.Application import Application
+
upgrade = VersionUpgrade21to22.VersionUpgrade21to22()
-def getMetaData():
+def getMetaData() -> Dict[str, Any]:
return {
"version_upgrade": {
# From To Upgrade function
@@ -33,5 +38,5 @@ def getMetaData():
}
}
-def register(app):
+def register(app: "Application") -> Dict[str, Any]:
return { "version_upgrade": upgrade }
diff --git a/plugins/VersionUpgrade/VersionUpgrade21to22/plugin.json b/plugins/VersionUpgrade/VersionUpgrade21to22/plugin.json
index 463fcdc941..cad94c2eb5 100644
--- a/plugins/VersionUpgrade/VersionUpgrade21to22/plugin.json
+++ b/plugins/VersionUpgrade/VersionUpgrade21to22/plugin.json
@@ -1,8 +1,8 @@
{
"name": "Version Upgrade 2.1 to 2.2",
"author": "Ultimaker B.V.",
- "version": "1.0.0",
+ "version": "1.0.1",
"description": "Upgrades configurations from Cura 2.1 to Cura 2.2.",
- "api": 5,
+ "api": "6.0",
"i18n-catalog": "cura"
}
diff --git a/plugins/VersionUpgrade/VersionUpgrade22to24/VersionUpgrade.py b/plugins/VersionUpgrade/VersionUpgrade22to24/VersionUpgrade.py
index a56f1f807b..ded892d137 100644
--- a/plugins/VersionUpgrade/VersionUpgrade22to24/VersionUpgrade.py
+++ b/plugins/VersionUpgrade/VersionUpgrade22to24/VersionUpgrade.py
@@ -1,18 +1,18 @@
-# Copyright (c) 2017 Ultimaker B.V.
+# Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
import configparser #To get version numbers from config files.
+import io
import os
import os.path
-import io
+from typing import Dict, List, Optional, Tuple
from UM.Resources import Resources
from UM.VersionUpgrade import VersionUpgrade # Superclass of the plugin.
import UM.VersionUpgrade
class VersionUpgrade22to24(VersionUpgrade):
-
- def upgradeMachineInstance(self, serialised, filename):
+ def upgradeMachineInstance(self, serialised: str, filename: str) -> Optional[Tuple[List[str], List[str]]]:
# All of this is needed to upgrade custom variant machines from old Cura to 2.4 where
# `definition_changes` instance container has been introduced. Variant files which
# look like the the handy work of the old machine settings plugin are converted directly
@@ -22,11 +22,11 @@ class VersionUpgrade22to24(VersionUpgrade):
config.read_string(serialised) # Read the input string as config file.
if config.get("metadata", "type") == "definition_changes":
# This is not a container stack, don't upgrade it here
- return
+ return None
config.set("general", "version", "3")
- container_list = []
+ container_list = [] # type: List[str]
if config.has_section("containers"):
for index, container_id in config.items("containers"):
container_list.append(container_id)
@@ -37,14 +37,14 @@ class VersionUpgrade22to24(VersionUpgrade):
user_variants = self.__getUserVariants()
name_path_dict = {}
for variant in user_variants:
- name_path_dict[variant.get("name")] = variant.get("path")
+ name_path_dict[variant["name"]] = variant["path"]
user_variant_names = set(container_list).intersection(name_path_dict.keys())
if len(user_variant_names):
# One of the user defined variants appears in the list of containers in the stack.
for variant_name in user_variant_names: # really there should just be one variant to convert.
- config_name = self.__convertVariant(name_path_dict.get(variant_name))
+ config_name = self.__convertVariant(name_path_dict[variant_name])
# Change the name of variant and insert empty_variant into the stack.
new_container_list = []
@@ -64,14 +64,14 @@ class VersionUpgrade22to24(VersionUpgrade):
config.remove_option("general", "containers")
- for index in range(len(container_list)):
- config.set("containers", str(index), container_list[index])
+ for idx in range(len(container_list)):
+ config.set("containers", str(idx), container_list[idx])
output = io.StringIO()
config.write(output)
return [filename], [output.getvalue()]
- def __convertVariant(self, variant_path):
+ def __convertVariant(self, variant_path: str) -> str:
# Copy the variant to the machine_instances/*_settings.inst.cfg
variant_config = configparser.ConfigParser(interpolation = None)
with open(variant_path, "r", encoding = "utf-8") as fhandle:
@@ -99,7 +99,7 @@ class VersionUpgrade22to24(VersionUpgrade):
return config_name
- def __getUserVariants(self):
+ def __getUserVariants(self) -> List[Dict[str, str]]:
resource_path = Resources.getDataStoragePath()
variants_dir = os.path.join(resource_path, "variants")
@@ -113,7 +113,7 @@ class VersionUpgrade22to24(VersionUpgrade):
result.append( { "path": entry.path, "name": config.get("general", "name") } )
return result
- def upgradeExtruderTrain(self, serialised, filename):
+ def upgradeExtruderTrain(self, serialised: str, filename: str) -> Tuple[List[str], List[str]]:
config = configparser.ConfigParser(interpolation = None)
config.read_string(serialised) # Read the input string as config file.
config.set("general", "version", "3") # Just bump the version number. That is all we need for now.
@@ -122,7 +122,7 @@ class VersionUpgrade22to24(VersionUpgrade):
config.write(output)
return [filename], [output.getvalue()]
- def upgradePreferences(self, serialised, filename):
+ def upgradePreferences(self, serialised: str, filename: str) -> Tuple[List[str], List[str]]:
config = configparser.ConfigParser(interpolation = None)
config.read_string(serialised)
@@ -142,7 +142,7 @@ class VersionUpgrade22to24(VersionUpgrade):
config.write(output)
return [filename], [output.getvalue()]
- def upgradeQuality(self, serialised, filename):
+ def upgradeQuality(self, serialised: str, filename: str) -> Tuple[List[str], List[str]]:
config = configparser.ConfigParser(interpolation = None)
config.read_string(serialised) # Read the input string as config file.
config.set("metadata", "type", "quality_changes") # Update metadata/type to quality_changes
@@ -152,9 +152,9 @@ class VersionUpgrade22to24(VersionUpgrade):
config.write(output)
return [filename], [output.getvalue()]
- def getCfgVersion(self, serialised):
+ 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))
+ setting_version = int(parser.get("metadata", "setting_version", fallback = "0"))
return format_version * 1000000 + setting_version
diff --git a/plugins/VersionUpgrade/VersionUpgrade22to24/__init__.py b/plugins/VersionUpgrade/VersionUpgrade22to24/__init__.py
index 278b660ec1..fe79333544 100644
--- a/plugins/VersionUpgrade/VersionUpgrade22to24/__init__.py
+++ b/plugins/VersionUpgrade/VersionUpgrade22to24/__init__.py
@@ -1,11 +1,16 @@
-# Copyright (c) 2016 Ultimaker B.V.
+# Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
+from typing import Any, Dict, TYPE_CHECKING
+
from . import VersionUpgrade
+if TYPE_CHECKING:
+ from UM.Application import Application
+
upgrade = VersionUpgrade.VersionUpgrade22to24()
-def getMetaData():
+def getMetaData() -> Dict[str, Any]:
return {
"version_upgrade": {
# From To Upgrade function
@@ -26,5 +31,5 @@ def getMetaData():
}
}
-def register(app):
+def register(app: "Application"):
return { "version_upgrade": upgrade }
diff --git a/plugins/VersionUpgrade/VersionUpgrade22to24/plugin.json b/plugins/VersionUpgrade/VersionUpgrade22to24/plugin.json
index e7a0b1c559..7da1e7a56d 100644
--- a/plugins/VersionUpgrade/VersionUpgrade22to24/plugin.json
+++ b/plugins/VersionUpgrade/VersionUpgrade22to24/plugin.json
@@ -1,8 +1,8 @@
{
"name": "Version Upgrade 2.2 to 2.4",
"author": "Ultimaker B.V.",
- "version": "1.0.0",
+ "version": "1.0.1",
"description": "Upgrades configurations from Cura 2.2 to Cura 2.4.",
- "api": 5,
+ "api": "6.0",
"i18n-catalog": "cura"
}
diff --git a/plugins/VersionUpgrade/VersionUpgrade25to26/VersionUpgrade25to26.py b/plugins/VersionUpgrade/VersionUpgrade25to26/VersionUpgrade25to26.py
index 6643edb765..6dbcfebc46 100644
--- a/plugins/VersionUpgrade/VersionUpgrade25to26/VersionUpgrade25to26.py
+++ b/plugins/VersionUpgrade/VersionUpgrade25to26/VersionUpgrade25to26.py
@@ -4,6 +4,7 @@
import configparser #To parse the files we need to upgrade and write the new files.
import io #To serialise configparser output to a string.
import os
+from typing import Dict, List, Set, Tuple
from urllib.parse import quote_plus
from UM.Resources import Resources
@@ -12,19 +13,18 @@ from UM.VersionUpgrade import VersionUpgrade
_removed_settings = { #Settings that were removed in 2.5.
"start_layers_at_same_position",
"sub_div_rad_mult"
-}
+} # type: Set[str]
_split_settings = { #These settings should be copied to all settings it was split into.
"support_interface_line_distance": {"support_roof_line_distance", "support_bottom_line_distance"}
-}
+} # type: Dict[str, Set[str]]
## A collection of functions that convert the configuration of the user in Cura
# 2.5 to a configuration for Cura 2.6.
#
# All of these methods are essentially stateless.
class VersionUpgrade25to26(VersionUpgrade):
-
- def __init__(self):
+ def __init__(self) -> None:
super().__init__()
self._current_fdm_printer_count = 2
@@ -39,18 +39,18 @@ class VersionUpgrade25to26(VersionUpgrade):
# \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):
+ 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))
+ setting_version = int(parser.get("metadata", "setting_version", fallback = "0"))
return format_version * 1000000 + setting_version
## Upgrades the preferences file from version 2.5 to 2.6.
#
# \param serialised The serialised form of a preferences file.
# \param filename The name of the file to upgrade.
- def upgradePreferences(self, serialised, filename):
+ def upgradePreferences(self, serialised: str, filename: str) -> Tuple[List[str], List[str]]:
parser = configparser.ConfigParser(interpolation = None)
parser.read_string(serialised)
@@ -86,7 +86,7 @@ class VersionUpgrade25to26(VersionUpgrade):
#
# \param serialised The serialised form of a quality profile.
# \param filename The name of the file to upgrade.
- def upgradeInstanceContainer(self, serialised, filename):
+ def upgradeInstanceContainer(self, serialised: str, filename: str) -> Tuple[List[str], List[str]]:
parser = configparser.ConfigParser(interpolation = None)
parser.read_string(serialised)
@@ -116,7 +116,7 @@ class VersionUpgrade25to26(VersionUpgrade):
#
# \param serialised The serialised form of a quality profile.
# \param filename The name of the file to upgrade.
- def upgradeMachineStack(self, serialised, filename):
+ def upgradeMachineStack(self, serialised: str, filename: str) -> Tuple[List[str], List[str]]:
parser = configparser.ConfigParser(interpolation = None)
parser.read_string(serialised)
@@ -149,7 +149,7 @@ class VersionUpgrade25to26(VersionUpgrade):
return [filename], [output.getvalue()]
## Acquires the next unique extruder stack index number for the Custom FDM Printer.
- def _acquireNextUniqueCustomFdmPrinterExtruderStackIdIndex(self):
+ def _acquireNextUniqueCustomFdmPrinterExtruderStackIdIndex(self) -> int:
extruder_stack_dir = os.path.join(Resources.getDataStoragePath(), "extruders")
file_name_list = os.listdir(extruder_stack_dir)
file_name_list = [os.path.basename(file_name) for file_name in file_name_list]
@@ -169,7 +169,7 @@ class VersionUpgrade25to26(VersionUpgrade):
return self._current_fdm_printer_count
- def _checkCustomFdmPrinterHasExtruderStack(self, machine_id):
+ def _checkCustomFdmPrinterHasExtruderStack(self, machine_id: str) -> bool:
# go through all extruders and make sure that this custom FDM printer has extruder stacks.
extruder_stack_dir = os.path.join(Resources.getDataStoragePath(), "extruders")
has_extruders = False
@@ -197,7 +197,7 @@ class VersionUpgrade25to26(VersionUpgrade):
return has_extruders
- def _createCustomFdmPrinterExtruderStack(self, machine_id: str, position: int, quality_id: str, material_id: str):
+ def _createCustomFdmPrinterExtruderStack(self, machine_id: str, position: int, quality_id: str, material_id: str) -> None:
stack_id = "custom_extruder_%s" % (position + 1)
if self._current_fdm_printer_count > 1:
stack_id += " #%s" % self._current_fdm_printer_count
@@ -256,7 +256,7 @@ class VersionUpgrade25to26(VersionUpgrade):
## Creates a definition changes container which doesn't contain anything for the Custom FDM Printers.
# The container ID will be automatically generated according to the given stack name.
- def _getCustomFdmPrinterDefinitionChanges(self, stack_id: str):
+ def _getCustomFdmPrinterDefinitionChanges(self, stack_id: str) -> configparser.ConfigParser:
# In 2.5, there is no definition_changes container for the Custom FDM printer, so it should be safe to use the
# default name unless some one names the printer as something like "Custom FDM Printer_settings".
definition_changes_id = stack_id + "_settings"
@@ -277,7 +277,7 @@ class VersionUpgrade25to26(VersionUpgrade):
## Creates a user settings container which doesn't contain anything for the Custom FDM Printers.
# The container ID will be automatically generated according to the given stack name.
- def _getCustomFdmPrinterUserSettings(self, stack_id: str):
+ def _getCustomFdmPrinterUserSettings(self, stack_id: str) -> configparser.ConfigParser:
# For the extruder stacks created in the upgrade, also create user_settings containers so the user changes
# will be saved.
user_settings_id = stack_id + "_user"
diff --git a/plugins/VersionUpgrade/VersionUpgrade25to26/__init__.py b/plugins/VersionUpgrade/VersionUpgrade25to26/__init__.py
index 67aa73233f..c74b3218b6 100644
--- a/plugins/VersionUpgrade/VersionUpgrade25to26/__init__.py
+++ b/plugins/VersionUpgrade/VersionUpgrade25to26/__init__.py
@@ -1,11 +1,16 @@
-# Copyright (c) 2017 Ultimaker B.V.
+# Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
+from typing import Any, Dict, TYPE_CHECKING
+
from . import VersionUpgrade25to26
+if TYPE_CHECKING:
+ from UM.Application import Application
+
upgrade = VersionUpgrade25to26.VersionUpgrade25to26()
-def getMetaData():
+def getMetaData() -> Dict[str, Any]:
return {
"version_upgrade": {
# From To Upgrade function
@@ -41,5 +46,5 @@ def getMetaData():
}
}
-def register(app):
+def register(app: "Application") -> Dict[str, Any]:
return { "version_upgrade": upgrade }
diff --git a/plugins/VersionUpgrade/VersionUpgrade25to26/plugin.json b/plugins/VersionUpgrade/VersionUpgrade25to26/plugin.json
index 3029539887..e1f0a47685 100644
--- a/plugins/VersionUpgrade/VersionUpgrade25to26/plugin.json
+++ b/plugins/VersionUpgrade/VersionUpgrade25to26/plugin.json
@@ -1,8 +1,8 @@
{
"name": "Version Upgrade 2.5 to 2.6",
"author": "Ultimaker B.V.",
- "version": "1.0.0",
+ "version": "1.0.1",
"description": "Upgrades configurations from Cura 2.5 to Cura 2.6.",
- "api": 5,
+ "api": "6.0",
"i18n-catalog": "cura"
}
diff --git a/plugins/VersionUpgrade/VersionUpgrade26to27/VersionUpgrade26to27.py b/plugins/VersionUpgrade/VersionUpgrade26to27/VersionUpgrade26to27.py
index dfa436e5bd..39e3dea4ed 100644
--- a/plugins/VersionUpgrade/VersionUpgrade26to27/VersionUpgrade26to27.py
+++ b/plugins/VersionUpgrade/VersionUpgrade26to27/VersionUpgrade26to27.py
@@ -3,6 +3,7 @@
import configparser #To parse the files we need to upgrade and write the new files.
import io #To serialise configparser output to a string.
+from typing import Dict, List, Tuple
from UM.VersionUpgrade import VersionUpgrade
@@ -61,7 +62,7 @@ _renamed_quality_profiles = {
"um3_bb0.8_TPU_Not_Supported_Quality": "um3_bb0.8_TPU_Fast_print",
"um3_bb0.8_TPU_Not_Supported_Superdraft_Quality": "um3_bb0.8_TPU_Superdraft_Print",
-}
+} # type: Dict[str, str]
## A collection of functions that convert the configuration of the user in Cura
# 2.6 to a configuration for Cura 2.7.
@@ -79,19 +80,19 @@ class VersionUpgrade26to27(VersionUpgrade):
# \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):
+ 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))
+ setting_version = int(parser.get("metadata", "setting_version", fallback = "0"))
return format_version * 1000000 + setting_version
## Upgrades a preferences file from version 2.6 to 2.7.
#
# \param serialised The serialised form of a preferences file.
# \param filename The name of the file to upgrade.
- def upgradePreferences(self, serialised, filename):
- parser = configparser.ConfigParser(interpolation=None)
+ def upgradePreferences(self, serialised: str, filename: str) -> Tuple[List[str], List[str]]:
+ parser = configparser.ConfigParser(interpolation = None)
parser.read_string(serialised)
# Update version numbers
@@ -117,8 +118,8 @@ class VersionUpgrade26to27(VersionUpgrade):
#
# \param serialised The serialised form of a container file.
# \param filename The name of the file to upgrade.
- def upgradeOtherContainer(self, serialised, filename):
- parser = configparser.ConfigParser(interpolation=None)
+ def upgradeOtherContainer(self, serialised: str, filename: str) -> Tuple[List[str], List[str]]:
+ parser = configparser.ConfigParser(interpolation = None)
parser.read_string(serialised)
# Update version numbers
@@ -139,7 +140,7 @@ class VersionUpgrade26to27(VersionUpgrade):
#
# \param serialised The serialised form of a container stack.
# \param filename The name of the file to upgrade.
- def upgradeStack(self, serialised, filename):
+ def upgradeStack(self, serialised: str, filename: str) -> Tuple[List[str], List[str]]:
parser = configparser.ConfigParser(interpolation = None)
parser.read_string(serialised)
diff --git a/plugins/VersionUpgrade/VersionUpgrade26to27/__init__.py b/plugins/VersionUpgrade/VersionUpgrade26to27/__init__.py
index 0e26ca8bbf..1952c9ceff 100644
--- a/plugins/VersionUpgrade/VersionUpgrade26to27/__init__.py
+++ b/plugins/VersionUpgrade/VersionUpgrade26to27/__init__.py
@@ -1,11 +1,16 @@
-# Copyright (c) 2017 Ultimaker B.V.
+# Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
+from typing import Any, Dict, TYPE_CHECKING
+
from . import VersionUpgrade26to27
+if TYPE_CHECKING:
+ from UM.Application import Application
+
upgrade = VersionUpgrade26to27.VersionUpgrade26to27()
-def getMetaData():
+def getMetaData() -> Dict[str, Any]:
return {
"version_upgrade": {
# From To Upgrade function
@@ -59,5 +64,5 @@ def getMetaData():
}
}
-def register(app):
+def register(app: "Application") -> Dict[str, Any]:
return { "version_upgrade": upgrade }
diff --git a/plugins/VersionUpgrade/VersionUpgrade26to27/plugin.json b/plugins/VersionUpgrade/VersionUpgrade26to27/plugin.json
index 225da67235..6cdbd64cbb 100644
--- a/plugins/VersionUpgrade/VersionUpgrade26to27/plugin.json
+++ b/plugins/VersionUpgrade/VersionUpgrade26to27/plugin.json
@@ -1,8 +1,8 @@
{
"name": "Version Upgrade 2.6 to 2.7",
"author": "Ultimaker B.V.",
- "version": "1.0.0",
+ "version": "1.0.1",
"description": "Upgrades configurations from Cura 2.6 to Cura 2.7.",
- "api": 5,
+ "api": "6.0",
"i18n-catalog": "cura"
}
diff --git a/plugins/VersionUpgrade/VersionUpgrade27to30/VersionUpgrade27to30.py b/plugins/VersionUpgrade/VersionUpgrade27to30/VersionUpgrade27to30.py
index 5a141f1558..b594c3c6c4 100644
--- a/plugins/VersionUpgrade/VersionUpgrade27to30/VersionUpgrade27to30.py
+++ b/plugins/VersionUpgrade/VersionUpgrade27to30/VersionUpgrade27to30.py
@@ -1,9 +1,10 @@
-# Copyright (c) 2017 Ultimaker B.V.
+# Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
import configparser #To parse preference files.
import io #To serialise the preference files afterwards.
import os
+from typing import Dict, List, Tuple
import urllib.parse
import re
@@ -11,7 +12,7 @@ from UM.VersionUpgrade import VersionUpgrade #We're inheriting from this.
_renamed_themes = {
"cura": "cura-light"
-}
+} # type: Dict[str, str]
_renamed_i18n = {
"7s": "en_7S",
"de": "de_DE",
@@ -28,7 +29,7 @@ _renamed_i18n = {
"ptbr": "pt_BR",
"ru": "ru_RU",
"tr": "tr_TR"
-}
+} # type: Dict[str, str]
class VersionUpgrade27to30(VersionUpgrade):
@@ -43,19 +44,19 @@ class VersionUpgrade27to30(VersionUpgrade):
# \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):
+ 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))
+ setting_version = int(parser.get("metadata", "setting_version", fallback = "0"))
return format_version * 1000000 + setting_version
## Upgrades a preferences file from version 2.7 to 3.0.
#
# \param serialised The serialised form of a preferences file.
# \param filename The name of the file to upgrade.
- def upgradePreferences(self, serialised, filename):
- parser = configparser.ConfigParser(interpolation=None)
+ def upgradePreferences(self, serialised: str, filename: str) -> Tuple[List[str], List[str]]:
+ parser = configparser.ConfigParser(interpolation = None)
parser.read_string(serialised)
# Update version numbers
@@ -100,8 +101,8 @@ class VersionUpgrade27to30(VersionUpgrade):
#
# \param serialised The serialised form of the container file.
# \param filename The name of the file to upgrade.
- def upgradeQualityChangesContainer(self, serialised, filename):
- parser = configparser.ConfigParser(interpolation=None)
+ def upgradeQualityChangesContainer(self, serialised: str, filename: str) -> Tuple[List[str], List[str]]:
+ parser = configparser.ConfigParser(interpolation = None)
parser.read_string(serialised)
# Update the skin pre-shrink settings:
@@ -156,8 +157,8 @@ class VersionUpgrade27to30(VersionUpgrade):
#
# \param serialised The serialised form of the container file.
# \param filename The name of the file to upgrade.
- def upgradeOtherContainer(self, serialised, filename):
- parser = configparser.ConfigParser(interpolation=None)
+ def upgradeOtherContainer(self, serialised: str, filename: str) -> Tuple[List[str], List[str]]:
+ parser = configparser.ConfigParser(interpolation = None)
parser.read_string(serialised)
# Update the skin pre-shrink settings:
@@ -185,7 +186,7 @@ class VersionUpgrade27to30(VersionUpgrade):
#
# \param serialised The serialised form of a container stack.
# \param filename The name of the file to upgrade.
- def upgradeStack(self, serialised, filename):
+ def upgradeStack(self, serialised: str, filename: str) -> Tuple[List[str], List[str]]:
parser = configparser.ConfigParser(interpolation=None)
parser.read_string(serialised)
diff --git a/plugins/VersionUpgrade/VersionUpgrade27to30/__init__.py b/plugins/VersionUpgrade/VersionUpgrade27to30/__init__.py
index 4da7257b1c..bddc71a1e0 100644
--- a/plugins/VersionUpgrade/VersionUpgrade27to30/__init__.py
+++ b/plugins/VersionUpgrade/VersionUpgrade27to30/__init__.py
@@ -1,11 +1,16 @@
-# Copyright (c) 2017 Ultimaker B.V.
+# Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
+from typing import Any, Dict, TYPE_CHECKING
+
from . import VersionUpgrade27to30
+if TYPE_CHECKING:
+ from UM.Application import Application
+
upgrade = VersionUpgrade27to30.VersionUpgrade27to30()
-def getMetaData():
+def getMetaData() -> Dict[str, Any]:
return {
"version_upgrade": {
# From To Upgrade function
@@ -51,5 +56,5 @@ def getMetaData():
}
}
-def register(app):
+def register(app: "Application") -> Dict[str, Any]:
return { "version_upgrade": upgrade }
diff --git a/plugins/VersionUpgrade/VersionUpgrade27to30/plugin.json b/plugins/VersionUpgrade/VersionUpgrade27to30/plugin.json
index 9a139851ec..885d741a8c 100644
--- a/plugins/VersionUpgrade/VersionUpgrade27to30/plugin.json
+++ b/plugins/VersionUpgrade/VersionUpgrade27to30/plugin.json
@@ -1,8 +1,8 @@
{
"name": "Version Upgrade 2.7 to 3.0",
"author": "Ultimaker B.V.",
- "version": "1.0.0",
+ "version": "1.0.1",
"description": "Upgrades configurations from Cura 2.7 to Cura 3.0.",
- "api": 5,
+ "api": "6.0",
"i18n-catalog": "cura"
}
diff --git a/plugins/VersionUpgrade/VersionUpgrade30to31/VersionUpgrade30to31.py b/plugins/VersionUpgrade/VersionUpgrade30to31/VersionUpgrade30to31.py
index 399eb18b5d..f0b2e939b9 100644
--- a/plugins/VersionUpgrade/VersionUpgrade30to31/VersionUpgrade30to31.py
+++ b/plugins/VersionUpgrade/VersionUpgrade30to31/VersionUpgrade30to31.py
@@ -1,14 +1,15 @@
-# Copyright (c) 2017 Ultimaker B.V.
+# Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
import configparser #To parse preference files.
import io #To serialise the preference files afterwards.
+from typing import Dict, List, Set, Tuple
from UM.VersionUpgrade import VersionUpgrade #We're inheriting from this.
# a list of all legacy "Not Supported" quality profiles
-_OLD_NOT_SUPPORTED_PROFILES = [
+_OLD_NOT_SUPPORTED_PROFILES = {
"um2p_pp_0.25_normal",
"um2p_tpu_0.8_normal",
"um3_bb0.4_ABS_Fast_Print",
@@ -42,7 +43,7 @@ _OLD_NOT_SUPPORTED_PROFILES = [
"um3_bb0.8_PP_Superdraft_Print",
"um3_bb0.8_TPU_Fast_print",
"um3_bb0.8_TPU_Superdraft_Print",
-]
+} # type: Set[str]
# Some containers have their specific empty containers, those need to be set correctly.
@@ -51,13 +52,13 @@ _EMPTY_CONTAINER_DICT = {
"2": "empty_quality",
"3": "empty_material",
"4": "empty_variant",
-}
+} # type: Dict[str, str]
# Renamed definition files
_RENAMED_DEFINITION_DICT = {
"jellybox": "imade3d_jellybox",
-}
+} # type: Dict[str, str]
class VersionUpgrade30to31(VersionUpgrade):
@@ -72,18 +73,18 @@ class VersionUpgrade30to31(VersionUpgrade):
# \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):
+ 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))
+ setting_version = int(parser.get("metadata", "setting_version", fallback = "0"))
return format_version * 1000000 + setting_version
## Upgrades a preferences file from version 3.0 to 3.1.
#
# \param serialised The serialised form of a preferences file.
# \param filename The name of the file to upgrade.
- def upgradePreferences(self, serialised, filename):
+ def upgradePreferences(self, serialised: str, filename: str) -> Tuple[List[str], List[str]]:
parser = configparser.ConfigParser(interpolation = None)
parser.read_string(serialised)
@@ -104,7 +105,7 @@ class VersionUpgrade30to31(VersionUpgrade):
#
# \param serialised The serialised form of the container file.
# \param filename The name of the file to upgrade.
- def upgradeInstanceContainer(self, serialised, filename):
+ def upgradeInstanceContainer(self, serialised: str, filename: str) -> Tuple[List[str], List[str]]:
parser = configparser.ConfigParser(interpolation = None)
parser.read_string(serialised)
@@ -129,7 +130,7 @@ class VersionUpgrade30to31(VersionUpgrade):
#
# \param serialised The serialised form of a container stack.
# \param filename The name of the file to upgrade.
- def upgradeStack(self, serialised, filename):
+ def upgradeStack(self, serialised: str, filename: str) -> Tuple[List[str], List[str]]:
parser = configparser.ConfigParser(interpolation = None)
parser.read_string(serialised)
diff --git a/plugins/VersionUpgrade/VersionUpgrade30to31/__init__.py b/plugins/VersionUpgrade/VersionUpgrade30to31/__init__.py
index 7b2c213a31..c5cc851d6a 100644
--- a/plugins/VersionUpgrade/VersionUpgrade30to31/__init__.py
+++ b/plugins/VersionUpgrade/VersionUpgrade30to31/__init__.py
@@ -1,11 +1,16 @@
-# Copyright (c) 2017 Ultimaker B.V.
+# Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
+from typing import Any, Dict, TYPE_CHECKING
+
from . import VersionUpgrade30to31
+if TYPE_CHECKING:
+ from UM.Application import Application
+
upgrade = VersionUpgrade30to31.VersionUpgrade30to31()
-def getMetaData():
+def getMetaData() -> Dict[str, Any]:
return {
"version_upgrade": {
# From To Upgrade function
@@ -55,5 +60,5 @@ def getMetaData():
}
}
-def register(app):
+def register(app: "Application") -> Dict[str, Any]:
return { "version_upgrade": upgrade }
diff --git a/plugins/VersionUpgrade/VersionUpgrade30to31/plugin.json b/plugins/VersionUpgrade/VersionUpgrade30to31/plugin.json
index cf42b3f6cd..d5f22649c1 100644
--- a/plugins/VersionUpgrade/VersionUpgrade30to31/plugin.json
+++ b/plugins/VersionUpgrade/VersionUpgrade30to31/plugin.json
@@ -1,8 +1,8 @@
{
"name": "Version Upgrade 3.0 to 3.1",
"author": "Ultimaker B.V.",
- "version": "1.0.0",
+ "version": "1.0.1",
"description": "Upgrades configurations from Cura 3.0 to Cura 3.1.",
- "api": 5,
+ "api": "6.0",
"i18n-catalog": "cura"
}
diff --git a/plugins/VersionUpgrade/VersionUpgrade32to33/VersionUpgrade32to33.py b/plugins/VersionUpgrade/VersionUpgrade32to33/VersionUpgrade32to33.py
index 18851b82c7..83cb15c864 100644
--- a/plugins/VersionUpgrade/VersionUpgrade32to33/VersionUpgrade32to33.py
+++ b/plugins/VersionUpgrade/VersionUpgrade32to33/VersionUpgrade32to33.py
@@ -3,6 +3,7 @@
import configparser #To parse preference files.
import io #To serialise the preference files afterwards.
+from typing import Dict, List, Tuple
from UM.VersionUpgrade import VersionUpgrade #We're inheriting from this.
@@ -51,22 +52,22 @@ _EXTRUDER_TO_POSITION = {
"ultimaker_original_dual_2nd": 1,
"vertex_k8400_dual_1st": 0,
"vertex_k8400_dual_2nd": 1
-}
+} # type: Dict[str, int]
_RENAMED_QUALITY_PROFILES = {
"low": "fast",
"um2_low": "um2_fast"
-}
+} # type: Dict[str, str]
_RENAMED_QUALITY_TYPES = {
"low": "fast"
-}
+} # type: Dict[str, str]
## Upgrades configurations from the state they were in at version 3.2 to the
# state they should be in at version 3.3.
class VersionUpgrade32to33(VersionUpgrade):
-
temporary_group_name_counter = 1
+
## Gets the version number from a CFG file in Uranium's 3.2 format.
#
# Since the format may change, this is implemented for the 3.2 format only
@@ -78,18 +79,18 @@ class VersionUpgrade32to33(VersionUpgrade):
# \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):
+ 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))
+ setting_version = int(parser.get("metadata", "setting_version", fallback = "0"))
return format_version * 1000000 + setting_version
## Upgrades a preferences file from version 3.2 to 3.3.
#
# \param serialised The serialised form of a preferences file.
# \param filename The name of the file to upgrade.
- def upgradePreferences(self, serialised, filename):
+ def upgradePreferences(self, serialised: str, filename: str) -> Tuple[List[str], List[str]]:
parser = configparser.ConfigParser(interpolation = None)
parser.read_string(serialised)
@@ -117,7 +118,7 @@ class VersionUpgrade32to33(VersionUpgrade):
#
# \param serialised The serialised form of a container stack.
# \param filename The name of the file to upgrade.
- def upgradeStack(self, serialized, filename):
+ def upgradeStack(self, serialized: str, filename: str) -> Tuple[List[str], List[str]]:
parser = configparser.ConfigParser(interpolation = None)
parser.read_string(serialized)
@@ -141,7 +142,7 @@ class VersionUpgrade32to33(VersionUpgrade):
## Upgrades non-quality-changes instance containers to have the new version
# number.
- def upgradeInstanceContainer(self, serialized, filename):
+ def upgradeInstanceContainer(self, serialized: str, filename: str) -> Tuple[List[str], List[str]]:
parser = configparser.ConfigParser(interpolation = None)
parser.read_string(serialized)
@@ -153,7 +154,7 @@ class VersionUpgrade32to33(VersionUpgrade):
return [filename], [result.getvalue()]
## Upgrades a quality changes container to the new format.
- def upgradeQualityChanges(self, serialized, filename):
+ def upgradeQualityChanges(self, serialized: str, filename: str) -> Tuple[List[str], List[str]]:
parser = configparser.ConfigParser(interpolation = None)
parser.read_string(serialized)
@@ -182,7 +183,7 @@ class VersionUpgrade32to33(VersionUpgrade):
return [filename], [result.getvalue()]
## Upgrades a variant container to the new format.
- def upgradeVariants(self, serialized, filename):
+ def upgradeVariants(self, serialized: str, filename: str) -> Tuple[List[str], List[str]]:
parser = configparser.ConfigParser(interpolation = None)
parser.read_string(serialized)
diff --git a/plugins/VersionUpgrade/VersionUpgrade32to33/__init__.py b/plugins/VersionUpgrade/VersionUpgrade32to33/__init__.py
index 5073be772d..b55ea5ebaf 100644
--- a/plugins/VersionUpgrade/VersionUpgrade32to33/__init__.py
+++ b/plugins/VersionUpgrade/VersionUpgrade32to33/__init__.py
@@ -1,11 +1,16 @@
# Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
+from typing import Any, Dict, TYPE_CHECKING
+
from . import VersionUpgrade32to33
+if TYPE_CHECKING:
+ from UM.Application import Application
+
upgrade = VersionUpgrade32to33.VersionUpgrade32to33()
-def getMetaData():
+def getMetaData() -> Dict[str, Any]:
return {
"version_upgrade": {
# From To Upgrade function
@@ -42,7 +47,7 @@ def getMetaData():
},
"user": {
"get_version": upgrade.getCfgVersion,
- "location": {"./user"}
+ "location": {"./user", "./materials/*"}
},
"variant": {
"get_version": upgrade.getCfgVersion,
@@ -51,5 +56,5 @@ def getMetaData():
}
}
-def register(app):
+def register(app: "Application") -> Dict[str, Any]:
return { "version_upgrade": upgrade }
\ No newline at end of file
diff --git a/plugins/VersionUpgrade/VersionUpgrade32to33/plugin.json b/plugins/VersionUpgrade/VersionUpgrade32to33/plugin.json
index f9cc968dae..eb489169e0 100644
--- a/plugins/VersionUpgrade/VersionUpgrade32to33/plugin.json
+++ b/plugins/VersionUpgrade/VersionUpgrade32to33/plugin.json
@@ -1,8 +1,8 @@
{
"name": "Version Upgrade 3.2 to 3.3",
"author": "Ultimaker B.V.",
- "version": "1.0.0",
+ "version": "1.0.1",
"description": "Upgrades configurations from Cura 3.2 to Cura 3.3.",
- "api": 5,
+ "api": "6.0",
"i18n-catalog": "cura"
}
diff --git a/plugins/VersionUpgrade/VersionUpgrade33to34/VersionUpgrade33to34.py b/plugins/VersionUpgrade/VersionUpgrade33to34/VersionUpgrade33to34.py
index e2241fd195..704ede02d6 100644
--- a/plugins/VersionUpgrade/VersionUpgrade33to34/VersionUpgrade33to34.py
+++ b/plugins/VersionUpgrade/VersionUpgrade33to34/VersionUpgrade33to34.py
@@ -3,17 +3,17 @@
import configparser #To parse preference files.
import io #To serialise the preference files afterwards.
+from typing import Dict, List, Tuple
from UM.VersionUpgrade import VersionUpgrade #We're inheriting from this.
_renamed_settings = {
"infill_hollow": "infill_support_enabled"
-}
+} # type: Dict[str, str]
## Upgrades configurations from the state they were in at version 3.3 to the
# state they should be in at version 3.4.
class VersionUpgrade33to34(VersionUpgrade):
-
## Gets the version number from a CFG file in Uranium's 3.3 format.
#
# Since the format may change, this is implemented for the 3.3 format only
@@ -25,16 +25,16 @@ class VersionUpgrade33to34(VersionUpgrade):
# \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):
+ 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))
+ 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.
- def upgradeInstanceContainer(self, serialized, filename):
+ def upgradeInstanceContainer(self, serialized: str, filename: str) -> Tuple[List[str], List[str]]:
parser = configparser.ConfigParser(interpolation = None)
parser.read_string(serialized)
diff --git a/plugins/VersionUpgrade/VersionUpgrade33to34/__init__.py b/plugins/VersionUpgrade/VersionUpgrade33to34/__init__.py
index 8213f195d5..5fd757f843 100644
--- a/plugins/VersionUpgrade/VersionUpgrade33to34/__init__.py
+++ b/plugins/VersionUpgrade/VersionUpgrade33to34/__init__.py
@@ -1,16 +1,22 @@
# Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
+from typing import Any, Dict, TYPE_CHECKING
+
from . import VersionUpgrade33to34
+if TYPE_CHECKING:
+ from UM.Application import Application
+
upgrade = VersionUpgrade33to34.VersionUpgrade33to34()
-def getMetaData():
+def getMetaData() -> Dict[str, Any]:
return {
"version_upgrade": {
# From To Upgrade function
("definition_changes", 3000004): ("definition_changes", 4000004, upgrade.upgradeInstanceContainer),
("quality_changes", 3000004): ("quality_changes", 4000004, upgrade.upgradeInstanceContainer),
+ ("quality", 3000004): ("quality", 4000004, upgrade.upgradeInstanceContainer),
("user", 3000004): ("user", 4000004, upgrade.upgradeInstanceContainer),
},
"sources": {
@@ -22,6 +28,10 @@ def getMetaData():
"get_version": upgrade.getCfgVersion,
"location": {"./quality_changes"}
},
+ "quality": {
+ "get_version": upgrade.getCfgVersion,
+ "location": {"./quality"}
+ },
"user": {
"get_version": upgrade.getCfgVersion,
"location": {"./user"}
@@ -30,5 +40,5 @@ def getMetaData():
}
-def register(app):
+def register(app: "Application") -> Dict[str, Any]:
return { "version_upgrade": upgrade }
diff --git a/plugins/VersionUpgrade/VersionUpgrade33to34/plugin.json b/plugins/VersionUpgrade/VersionUpgrade33to34/plugin.json
index f5ba7235d1..9649010643 100644
--- a/plugins/VersionUpgrade/VersionUpgrade33to34/plugin.json
+++ b/plugins/VersionUpgrade/VersionUpgrade33to34/plugin.json
@@ -1,8 +1,8 @@
{
"name": "Version Upgrade 3.3 to 3.4",
"author": "Ultimaker B.V.",
- "version": "1.0.0",
+ "version": "1.0.1",
"description": "Upgrades configurations from Cura 3.3 to Cura 3.4.",
- "api": 5,
+ "api": "6.0",
"i18n-catalog": "cura"
}
diff --git a/plugins/VersionUpgrade/VersionUpgrade34to35/VersionUpgrade34to35.py b/plugins/VersionUpgrade/VersionUpgrade34to35/VersionUpgrade34to35.py
index 9d59133036..8e45d7cf73 100644
--- a/plugins/VersionUpgrade/VersionUpgrade34to35/VersionUpgrade34to35.py
+++ b/plugins/VersionUpgrade/VersionUpgrade34to35/VersionUpgrade34to35.py
@@ -3,13 +3,14 @@
import configparser
import io
+from typing import Dict, List, Set, Tuple
from UM.VersionUpgrade import VersionUpgrade
-deleted_settings = {"prime_tower_wall_thickness", "dual_pre_wipe", "prime_tower_purge_volume"}
+deleted_settings = {"prime_tower_wall_thickness", "dual_pre_wipe", "prime_tower_purge_volume"} # type: Set[str]
-changed_settings = {'retraction_combing': 'noskin'}
-updated_settings = {'retraction_combing': 'infill'}
+changed_settings = {"retraction_combing": "noskin"} # type: Dict[str, str]
+updated_settings = {"retraction_combing": "infill"} # type: Dict[str, str]
_RENAMED_MATERIAL_PROFILES = {
"dsm_arnitel2045_175_cartesio_0.25_mm": "dsm_arnitel2045_175_cartesio_0.25mm_thermoplastic_extruder",
@@ -57,15 +58,14 @@ _RENAMED_MATERIAL_PROFILES = {
"ultimaker_pva_cartesio_0.25_mm": "ultimaker_pva_cartesio_0.25mm_thermoplastic_extruder",
"ultimaker_pva_cartesio_0.4_mm": "ultimaker_pva_cartesio_0.4mm_thermoplastic_extruder",
"ultimaker_pva_cartesio_0.8_mm": "ultimaker_pva_cartesio_0.8mm_thermoplastic_extruder"
-}
+} # type: Dict[str, str]
## Upgrades configurations from the state they were in at version 3.4 to the
# state they should be in at version 3.5.
class VersionUpgrade34to35(VersionUpgrade):
-
- ## Gets the version number from a CFG file in Uranium's 3.3 format.
+ ## Gets the version number from a CFG file in Uranium's 3.4 format.
#
- # Since the format may change, this is implemented for the 3.3 format only
+ # Since the format may change, this is implemented for the 3.4 format only
# and needs to be included in the version upgrade system rather than
# globally in Uranium.
#
@@ -74,15 +74,15 @@ class VersionUpgrade34to35(VersionUpgrade):
# \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):
+ 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))
+ setting_version = int(parser.get("metadata", "setting_version", fallback = "0"))
return format_version * 1000000 + setting_version
## Upgrades Preferences to have the new version number.
- def upgradePreferences(self, serialized, filename):
+ def upgradePreferences(self, serialized: str, filename: str) -> Tuple[List[str], List[str]]:
parser = configparser.ConfigParser(interpolation = None)
parser.read_string(serialized)
@@ -103,7 +103,7 @@ class VersionUpgrade34to35(VersionUpgrade):
return [filename], [result.getvalue()]
## Upgrades stacks to have the new version number.
- def upgradeStack(self, serialized, filename):
+ def upgradeStack(self, serialized: str, filename: str) -> Tuple[List[str], List[str]]:
parser = configparser.ConfigParser(interpolation = None)
parser.read_string(serialized)
@@ -121,7 +121,7 @@ class VersionUpgrade34to35(VersionUpgrade):
## Upgrades instance containers to have the new version
# number.
- def upgradeInstanceContainer(self, serialized, filename):
+ def upgradeInstanceContainer(self, serialized: str, filename: str) -> Tuple[List[str], List[str]]:
parser = configparser.ConfigParser(interpolation = None)
parser.read_string(serialized)
@@ -147,7 +147,7 @@ class VersionUpgrade34to35(VersionUpgrade):
parser.write(result)
return [filename], [result.getvalue()]
- def _resetConcentric3DInfillPattern(self, parser):
+ def _resetConcentric3DInfillPattern(self, parser: configparser.ConfigParser) -> None:
if "values" not in parser:
return
@@ -161,5 +161,4 @@ class VersionUpgrade34to35(VersionUpgrade):
if key not in parser["values"]:
continue
if parser["values"][key] == "concentric_3d":
- del parser["values"][key]
-
+ del parser["values"][key]
\ No newline at end of file
diff --git a/plugins/VersionUpgrade/VersionUpgrade34to35/__init__.py b/plugins/VersionUpgrade/VersionUpgrade34to35/__init__.py
index de0fdccb7d..332bc827b9 100644
--- a/plugins/VersionUpgrade/VersionUpgrade34to35/__init__.py
+++ b/plugins/VersionUpgrade/VersionUpgrade34to35/__init__.py
@@ -1,11 +1,16 @@
# Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
+from typing import Any, Dict, TYPE_CHECKING
+
from . import VersionUpgrade34to35
+if TYPE_CHECKING:
+ from UM.Application import Application
+
upgrade = VersionUpgrade34to35.VersionUpgrade34to35()
-def getMetaData():
+def getMetaData() -> Dict[str, Any]:
return {
"version_upgrade": {
# From To Upgrade function
@@ -13,6 +18,7 @@ def getMetaData():
("definition_changes", 4000004): ("definition_changes", 4000005, upgrade.upgradeInstanceContainer),
("quality_changes", 4000004): ("quality_changes", 4000005, upgrade.upgradeInstanceContainer),
+ ("quality", 4000004): ("quality", 4000005, upgrade.upgradeInstanceContainer),
("user", 4000004): ("user", 4000005, upgrade.upgradeInstanceContainer),
("machine_stack", 4000004): ("machine_stack", 4000005, upgrade.upgradeStack),
@@ -39,6 +45,10 @@ def getMetaData():
"get_version": upgrade.getCfgVersion,
"location": {"./quality_changes"}
},
+ "quality": {
+ "get_version": upgrade.getCfgVersion,
+ "location": {"./quality"}
+ },
"user": {
"get_version": upgrade.getCfgVersion,
"location": {"./user"}
@@ -47,5 +57,5 @@ def getMetaData():
}
-def register(app):
+def register(app: "Application") -> Dict[str, Any]:
return { "version_upgrade": upgrade }
diff --git a/plugins/VersionUpgrade/VersionUpgrade34to35/plugin.json b/plugins/VersionUpgrade/VersionUpgrade34to35/plugin.json
index b73001b683..71b13ee5a9 100644
--- a/plugins/VersionUpgrade/VersionUpgrade34to35/plugin.json
+++ b/plugins/VersionUpgrade/VersionUpgrade34to35/plugin.json
@@ -1,8 +1,8 @@
- {
+{
"name": "Version Upgrade 3.4 to 3.5",
"author": "Ultimaker B.V.",
- "version": "1.0.0",
+ "version": "1.0.1",
"description": "Upgrades configurations from Cura 3.4 to Cura 3.5.",
- "api": 5,
+ "api": "6.0",
"i18n-catalog": "cura"
}
diff --git a/plugins/VersionUpgrade/VersionUpgrade35to40/VersionUpgrade35to40.py b/plugins/VersionUpgrade/VersionUpgrade35to40/VersionUpgrade35to40.py
new file mode 100644
index 0000000000..71ce2e4fd0
--- /dev/null
+++ b/plugins/VersionUpgrade/VersionUpgrade35to40/VersionUpgrade35to40.py
@@ -0,0 +1,77 @@
+import configparser
+from typing import Tuple, List, Set, Dict
+import io
+
+from UM.VersionUpgrade import VersionUpgrade
+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]
+
+
+class VersionUpgrade35to40(VersionUpgrade):
+ # 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["general"]["version"] = "4"
+ parser["metadata"]["setting_version"] = "6"
+
+ if parser["metadata"].get("um_network_key") is not None or parser["metadata"].get("octoprint_api_key") is not None:
+ # Set the connection type if um_network_key or the octoprint key is set.
+ parser["metadata"]["connection_type"] = str(ConnectionType.NetworkConnection.value)
+
+ if "metadata" in parser:
+ for old_name, new_name in renamed_configurations.items():
+ if old_name not in parser["metadata"]:
+ continue
+ parser["metadata"][new_name] = parser["metadata"][old_name]
+ del parser["metadata"][old_name]
+
+ result = io.StringIO()
+ parser.write(result)
+ return [filename], [result.getvalue()]
+
+ 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.
+ def upgradePreferences(self, serialized: str, filename: str) -> Tuple[List[str], List[str]]:
+ parser = configparser.ConfigParser(interpolation=None)
+ parser.read_string(serialized)
+
+ if "metadata" not in parser:
+ parser["metadata"] = {}
+ parser["general"]["version"] = "6"
+ parser["metadata"]["setting_version"] = "6"
+
+ result = io.StringIO()
+ parser.write(result)
+ return [filename], [result.getvalue()]
+
+ ## Upgrades instance containers to have the new version
+ # number.
+ def upgradeInstanceContainer(self, serialized: str, filename: str) -> Tuple[List[str], List[str]]:
+ parser = configparser.ConfigParser(interpolation=None)
+ parser.read_string(serialized)
+
+ # Update version number.
+ parser["general"]["version"] = "4"
+ parser["metadata"]["setting_version"] = "6"
+
+ #self._resetConcentric3DInfillPattern(parser)
+ if "values" in parser:
+ for deleted_setting in deleted_settings:
+ if deleted_setting not in parser["values"]:
+ continue
+ del parser["values"][deleted_setting]
+
+ result = io.StringIO()
+ parser.write(result)
+ return [filename], [result.getvalue()]
diff --git a/plugins/VersionUpgrade/VersionUpgrade35to40/__init__.py b/plugins/VersionUpgrade/VersionUpgrade35to40/__init__.py
new file mode 100644
index 0000000000..2ad1dddbf2
--- /dev/null
+++ b/plugins/VersionUpgrade/VersionUpgrade35to40/__init__.py
@@ -0,0 +1,56 @@
+from typing import Dict, Any
+
+from . import VersionUpgrade35to40
+
+upgrade = VersionUpgrade35to40.VersionUpgrade35to40()
+
+
+def getMetaData() -> Dict[str, Any]:
+ return {
+ "version_upgrade": {
+ # From To Upgrade function
+ ("preferences", 6000005): ("preferences", 6000006, upgrade.upgradePreferences),
+
+ ("definition_changes", 4000005): ("definition_changes", 4000006, upgrade.upgradeInstanceContainer),
+ ("quality_changes", 4000005): ("quality_changes", 4000006, upgrade.upgradeInstanceContainer),
+ ("quality", 4000005): ("quality", 4000006, upgrade.upgradeInstanceContainer),
+ ("user", 4000005): ("user", 4000006, upgrade.upgradeInstanceContainer),
+
+ ("machine_stack", 4000005): ("machine_stack", 4000006, upgrade.upgradeStack),
+ ("extruder_train", 4000005): ("extruder_train", 4000006, upgrade.upgradeStack),
+ },
+ "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) -> Dict[str, Any]:
+ return {"version_upgrade": upgrade}
\ No newline at end of file
diff --git a/plugins/VersionUpgrade/VersionUpgrade35to40/plugin.json b/plugins/VersionUpgrade/VersionUpgrade35to40/plugin.json
new file mode 100644
index 0000000000..578594fb6d
--- /dev/null
+++ b/plugins/VersionUpgrade/VersionUpgrade35to40/plugin.json
@@ -0,0 +1,8 @@
+ {
+ "name": "Version Upgrade 3.5 to 4.0",
+ "author": "Ultimaker B.V.",
+ "version": "1.0.0",
+ "description": "Upgrades configurations from Cura 3.5 to Cura 4.0.",
+ "api": "6.0",
+ "i18n-catalog": "cura"
+}
diff --git a/plugins/VersionUpgrade/VersionUpgrade40to41/VersionUpgrade40to41.py b/plugins/VersionUpgrade/VersionUpgrade40to41/VersionUpgrade40to41.py
new file mode 100644
index 0000000000..b63d1842b7
--- /dev/null
+++ b/plugins/VersionUpgrade/VersionUpgrade40to41/VersionUpgrade40to41.py
@@ -0,0 +1,109 @@
+# 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
+
+_renamed_quality_profiles = {
+ "gmax15plus_pla_dual_normal": "gmax15plus_global_dual_normal",
+ "gmax15plus_pla_dual_thick": "gmax15plus_global_dual_thick",
+ "gmax15plus_pla_dual_thin": "gmax15plus_global_dual_thin",
+ "gmax15plus_pla_dual_very_thick": "gmax15plus_global_dual_very_thick",
+ "gmax15plus_pla_normal": "gmax15plus_global_normal",
+ "gmax15plus_pla_thick": "gmax15plus_global_thick",
+ "gmax15plus_pla_thin": "gmax15plus_global_thin",
+ "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):
+ ## Gets the version number from a CFG file in Uranium's 4.0 format.
+ #
+ # Since the format may change, this is implemented for the 4.0 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.
+ def upgradeInstanceContainer(self, serialized: str, filename: str) -> Tuple[List[str], List[str]]:
+ parser = configparser.ConfigParser(interpolation = None)
+ parser.read_string(serialized)
+
+ # Update version number.
+ 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()]
+
+ ## Upgrades Preferences to have the new version number.
+ 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["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()
+ 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["general"]["version"] = "4"
+ parser["metadata"]["setting_version"] = "7"
+
+ #Update the name of the quality profile.
+ 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
new file mode 100644
index 0000000000..09be805147
--- /dev/null
+++ b/plugins/VersionUpgrade/VersionUpgrade40to41/__init__.py
@@ -0,0 +1,59 @@
+# Copyright (c) 2018 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+
+from typing import Any, Dict, TYPE_CHECKING
+
+from . import VersionUpgrade40to41
+
+if TYPE_CHECKING:
+ from UM.Application import Application
+
+upgrade = VersionUpgrade40to41.VersionUpgrade40to41()
+
+def getMetaData() -> Dict[str, Any]:
+ return {
+ "version_upgrade": {
+ # From To Upgrade function
+ ("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),
+ ("quality_changes", 4000006): ("quality_changes", 4000007, upgrade.upgradeInstanceContainer),
+ ("quality", 4000006): ("quality", 4000007, upgrade.upgradeInstanceContainer),
+ ("user", 4000006): ("user", 4000007, 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/VersionUpgrade40to41/plugin.json b/plugins/VersionUpgrade/VersionUpgrade40to41/plugin.json
new file mode 100644
index 0000000000..b1c6d75669
--- /dev/null
+++ b/plugins/VersionUpgrade/VersionUpgrade40to41/plugin.json
@@ -0,0 +1,8 @@
+{
+ "name": "Version Upgrade 4.0 to 4.1",
+ "author": "Ultimaker B.V.",
+ "version": "1.0.1",
+ "description": "Upgrades configurations from Cura 4.0 to Cura 4.1.",
+ "api": "6.0",
+ "i18n-catalog": "cura"
+}
diff --git a/plugins/VersionUpgrade/VersionUpgrade41to42/VersionUpgrade41to42.py b/plugins/VersionUpgrade/VersionUpgrade41to42/VersionUpgrade41to42.py
new file mode 100644
index 0000000000..1ffb4030c5
--- /dev/null
+++ b/plugins/VersionUpgrade/VersionUpgrade41to42/VersionUpgrade41to42.py
@@ -0,0 +1,337 @@
+# 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_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)
+ 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]:
+ 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..6fd1309747
--- /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 }
\ No newline at end of file
diff --git a/plugins/VersionUpgrade/VersionUpgrade41to42/plugin.json b/plugins/VersionUpgrade/VersionUpgrade41to42/plugin.json
new file mode 100644
index 0000000000..9f8edea286
--- /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": "6.0",
+ "i18n-catalog": "cura"
+}
diff --git a/plugins/VersionUpgrade/VersionUpgrade42to43/VersionUpgrade42to43.py b/plugins/VersionUpgrade/VersionUpgrade42to43/VersionUpgrade42to43.py
new file mode 100644
index 0000000000..207e73fdbd
--- /dev/null
+++ b/plugins/VersionUpgrade/VersionUpgrade42to43/VersionUpgrade42to43.py
@@ -0,0 +1,102 @@
+import configparser
+import io
+from typing import 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",
+ }
+
+_removed_settings = {
+ "start_layers_at_same_position"
+}
+
+## 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"
+
+ 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)
+ parser.read_string(serialized)
+
+ # Update version number.
+ parser["metadata"]["setting_version"] = "9"
+
+ if "values" in parser:
+ for key in _removed_settings:
+ if key in parser["values"]:
+ del parser["values"][key]
+
+ 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.endswith("_2-fans"):
+ parser["containers"]["3"] = material_id.replace("_2-fans", "")
+ 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()]
\ No newline at end of file
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..339ec67ee7
--- /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": "6.0",
+ "i18n-catalog": "cura"
+}
diff --git a/plugins/X3DReader/plugin.json b/plugins/X3DReader/plugin.json
index 9ee09e43df..1fc14104ed 100644
--- a/plugins/X3DReader/plugin.json
+++ b/plugins/X3DReader/plugin.json
@@ -1,8 +1,8 @@
{
"name": "X3D Reader",
"author": "Seva Alekseyev",
- "version": "0.5.0",
+ "version": "1.0.1",
"description": "Provides support for reading X3D files.",
- "api": 5,
+ "api": "6.0",
"i18n-catalog": "cura"
}
diff --git a/plugins/XRayView/XRayView.py b/plugins/XRayView/XRayView.py
index 0c4035c62d..88a5a441b8 100644
--- a/plugins/XRayView/XRayView.py
+++ b/plugins/XRayView/XRayView.py
@@ -10,20 +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
@@ -41,6 +42,10 @@ class XRayView(View):
self._xray_shader.setUniformValue("u_color", Color(*Application.getInstance().getTheme().getColor("xray").getRgb()))
for node in BreadthFirstIterator(scene.getRoot()):
+ # We do not want to render ConvexHullNode as it conflicts with the bottom of the X-Ray (z-fighting).
+ if type(node) is ConvexHullNode:
+ continue
+
if not node.render(renderer):
if node.getMeshData() and node.isVisible():
renderer.queueNode(node,
diff --git a/plugins/XRayView/plugin.json b/plugins/XRayView/plugin.json
index 576dec4656..71cc165b6c 100644
--- a/plugins/XRayView/plugin.json
+++ b/plugins/XRayView/plugin.json
@@ -1,8 +1,8 @@
{
"name": "X-Ray View",
"author": "Ultimaker B.V.",
- "version": "1.0.0",
+ "version": "1.0.1",
"description": "Provides the X-Ray view.",
- "api": 5,
+ "api": "6.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 011941eec7..8d0177c165 100644
--- a/plugins/XmlMaterialProfile/XmlMaterialProfile.py
+++ b/plugins/XmlMaterialProfile/XmlMaterialProfile.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 copy
@@ -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
+from typing import Any, Dict, List, Optional, Tuple, cast, Set
import xml.etree.ElementTree as ET
from UM.Resources import Resources
@@ -60,28 +60,47 @@ class XmlMaterialProfile(InstanceContainer):
def setMetaDataEntry(self, key, value, apply_to_all = True):
registry = ContainerRegistry.getInstance()
if registry.isReadOnly(self.getId()):
+ 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
+ # 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
+
# Prevent recursion
if not apply_to_all:
super().setMetaDataEntry(key, value)
+ for k, v in new_setting_values_dict.items():
+ self.setProperty(k, "value", v)
return
# 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)
+ for k, v in new_setting_values_dict.items():
+ self.setProperty(k, "value", v)
+ 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)
+ for k, v in new_setting_values_dict.items():
+ root_material_container.setProperty(k, "value", v)
# 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 k, v in new_setting_values_dict.items():
+ container.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
@@ -117,7 +136,7 @@ class XmlMaterialProfile(InstanceContainer):
## Overridden from InstanceContainer
# base file: common settings + supported machines
# machine / variant combination: only changes for itself.
- def serialize(self, ignored_metadata_keys: Optional[set] = None):
+ def serialize(self, ignored_metadata_keys: Optional[Set[str]] = None):
registry = ContainerRegistry.getInstance()
base_file = self.getMetaDataEntry("base_file", "")
@@ -141,23 +160,13 @@ 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"}
+ 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:
del metadata[key]
properties = metadata.pop("properties", {})
- # Metadata properties that should not be serialized.
- metadata.pop("status", "")
- metadata.pop("variant", "")
- metadata.pop("type", "")
- metadata.pop("base_file", "")
- metadata.pop("approximate_diameter", "")
- metadata.pop("id", "")
- metadata.pop("container_type", "")
- metadata.pop("name", "")
-
## Begin Name Block
builder.start("name") # type: ignore
@@ -181,13 +190,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
@@ -952,14 +964,12 @@ class XmlMaterialProfile(InstanceContainer):
for machine in data.iterfind("./um:settings/um:machine", cls.__namespaces):
machine_compatibility = common_compatibility
- for entry in machine.iterfind("./um:setting", cls.__namespaces):
- key = entry.get("key")
- if key == "hardware compatible":
- if entry.text is not None:
- machine_compatibility = cls._parseCompatibleValue(entry.text)
+ for entry in machine.iterfind("./um:setting[@key='hardware compatible']", cls.__namespaces):
+ if entry.text is not None:
+ 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"))
@@ -991,7 +1001,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:
@@ -1027,11 +1037,9 @@ class XmlMaterialProfile(InstanceContainer):
continue
hotend_compatibility = machine_compatibility
- for entry in hotend.iterfind("./um:setting", cls.__namespaces):
- key = entry.get("key")
- if key == "hardware compatible":
- if entry.text is not None:
- hotend_compatibility = cls._parseCompatibleValue(entry.text)
+ for entry in hotend.iterfind("./um:setting[@key='hardware compatible']", cls.__namespaces):
+ if entry.text is not None:
+ hotend_compatibility = cls._parseCompatibleValue(entry.text)
new_hotend_specific_material_id = container_id + "_" + machine_id + "_" + hotend_name.replace(" ", "_")
@@ -1165,6 +1173,8 @@ class XmlMaterialProfile(InstanceContainer):
with open(product_to_id_file, encoding = "utf-8") as f:
product_to_id_map = json.load(f)
product_to_id_map = {key: [value] for key, value in product_to_id_map.items()}
+ #This also loads "Ultimaker S5" -> "ultimaker_s5" even though that is not strictly necessary with the default to change spaces into underscores.
+ #However it is not always loaded with that default; this mapping is also used in serialize() without that default.
return product_to_id_map
## Parse the value of the "material compatible" property.
@@ -1176,6 +1186,8 @@ class XmlMaterialProfile(InstanceContainer):
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",
@@ -1188,6 +1200,14 @@ 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 position": "material_break_retracted_position",
+ "break speed": "material_break_speed",
+ "break temperature": "material_break_temperature"
}
__unmapped_settings = [
"hardware compatible",
diff --git a/plugins/XmlMaterialProfile/XmlMaterialUpgrader.py b/plugins/XmlMaterialProfile/XmlMaterialUpgrader.py
index 167a9f2849..832a443637 100644
--- a/plugins/XmlMaterialProfile/XmlMaterialUpgrader.py
+++ b/plugins/XmlMaterialProfile/XmlMaterialUpgrader.py
@@ -1,11 +1,10 @@
-# Copyright (c) 2017 Ultimaker B.V.
+# Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
import xml.etree.ElementTree as ET
from UM.VersionUpgrade import VersionUpgrade
-from cura.CuraApplication import CuraApplication
from .XmlMaterialProfile import XmlMaterialProfile
diff --git a/plugins/XmlMaterialProfile/__init__.py b/plugins/XmlMaterialProfile/__init__.py
index e8bde78424..b3810c97dc 100644
--- a/plugins/XmlMaterialProfile/__init__.py
+++ b/plugins/XmlMaterialProfile/__init__.py
@@ -16,7 +16,7 @@ def getMetaData():
"mimetype": "application/x-ultimaker-material-profile"
},
"version_upgrade": {
- ("materials", 1000000): ("materials", 1000004, upgrader.upgradeMaterial),
+ ("materials", 1000000): ("materials", 1000007, upgrader.upgradeMaterial),
},
"sources": {
"materials": {
diff --git a/plugins/XmlMaterialProfile/plugin.json b/plugins/XmlMaterialProfile/plugin.json
index 4b2901c375..bb1db82fa4 100644
--- a/plugins/XmlMaterialProfile/plugin.json
+++ b/plugins/XmlMaterialProfile/plugin.json
@@ -1,8 +1,8 @@
{
"name": "Material Profiles",
"author": "Ultimaker B.V.",
- "version": "1.0.0",
+ "version": "1.0.1",
"description": "Provides capabilities to read and write XML-based material profiles.",
- "api": 5,
+ "api": "6.0",
"i18n-catalog": "cura"
}
diff --git a/plugins/XmlMaterialProfile/product_to_id.json b/plugins/XmlMaterialProfile/product_to_id.json
index 3e7ce9311f..6b78d3fe64 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 S5": "ultimaker_s5",
"Ultimaker Original": "ultimaker_original",
"Ultimaker Original+": "ultimaker_original_plus",
"Ultimaker Original Dual Extrusion": "ultimaker_original_dual",
diff --git a/resources/bundled_packages/cura.json b/resources/bundled_packages/cura.json
index 7107bbe4f0..4d23d56e5c 100644
--- a/resources/bundled_packages/cura.json
+++ b/resources/bundled_packages/cura.json
@@ -5,11 +5,11 @@
"package_type": "plugin",
"display_name": "3MF Reader",
"description": "Provides support for reading 3MF files.",
- "package_version": "1.0.0",
- "sdk_version": 5,
+ "package_version": "1.0.1",
+ "sdk_version": "6.0.0",
"website": "https://ultimaker.com",
"author": {
- "author_id": "Ultimaker",
+ "author_id": "UltimakerPackages",
"display_name": "Ultimaker B.V.",
"email": "plugins@ultimaker.com",
"website": "https://ultimaker.com"
@@ -22,28 +22,45 @@
"package_type": "plugin",
"display_name": "3MF Writer",
"description": "Provides support for writing 3MF files.",
- "package_version": "1.0.0",
- "sdk_version": 5,
+ "package_version": "1.0.1",
+ "sdk_version": "6.0.0",
"website": "https://ultimaker.com",
"author": {
- "author_id": "Ultimaker",
+ "author_id": "UltimakerPackages",
"display_name": "Ultimaker B.V.",
"email": "plugins@ultimaker.com",
"website": "https://ultimaker.com"
}
}
},
- "ChangeLogPlugin": {
+ "AMFReader": {
"package_info": {
- "package_id": "ChangeLogPlugin",
+ "package_id": "AMFReader",
"package_type": "plugin",
- "display_name": "Change Log",
- "description": "Shows changes since latest checked version.",
+ "display_name": "AMF Reader",
+ "description": "Provides support for reading AMF files.",
"package_version": "1.0.0",
- "sdk_version": 5,
+ "sdk_version": "6.0.0",
"website": "https://ultimaker.com",
"author": {
- "author_id": "Ultimaker",
+ "author_id": "fieldOfView",
+ "display_name": "fieldOfView",
+ "email": "plugins@ultimaker.com",
+ "website": "https://ultimaker.com"
+ }
+ }
+ },
+ "CuraDrive": {
+ "package_info": {
+ "package_id": "CuraDrive",
+ "package_type": "plugin",
+ "display_name": "Cura Backups",
+ "description": "Backup and restore your configuration.",
+ "package_version": "1.2.0",
+ "sdk_version": "6.0.0",
+ "website": "https://ultimaker.com",
+ "author": {
+ "author_id": "UltimakerPackages",
"display_name": "Ultimaker B.V.",
"email": "plugins@ultimaker.com",
"website": "https://ultimaker.com"
@@ -56,11 +73,11 @@
"package_type": "plugin",
"display_name": "CuraEngine Backend",
"description": "Provides the link to the CuraEngine slicing backend.",
- "package_version": "1.0.0",
- "sdk_version": 5,
+ "package_version": "1.0.1",
+ "sdk_version": "6.0.0",
"website": "https://ultimaker.com",
"author": {
- "author_id": "Ultimaker",
+ "author_id": "UltimakerPackages",
"display_name": "Ultimaker B.V.",
"email": "plugins@ultimaker.com",
"website": "https://ultimaker.com"
@@ -73,11 +90,11 @@
"package_type": "plugin",
"display_name": "Cura Profile Reader",
"description": "Provides support for importing Cura profiles.",
- "package_version": "1.0.0",
- "sdk_version": 5,
+ "package_version": "1.0.1",
+ "sdk_version": "6.0.0",
"website": "https://ultimaker.com",
"author": {
- "author_id": "Ultimaker",
+ "author_id": "UltimakerPackages",
"display_name": "Ultimaker B.V.",
"email": "plugins@ultimaker.com",
"website": "https://ultimaker.com"
@@ -90,11 +107,11 @@
"package_type": "plugin",
"display_name": "Cura Profile Writer",
"description": "Provides support for exporting Cura profiles.",
- "package_version": "1.0.0",
- "sdk_version": 5,
+ "package_version": "1.0.1",
+ "sdk_version": "6.0.0",
"website": "https://ultimaker.com",
"author": {
- "author_id": "Ultimaker",
+ "author_id": "UltimakerPackages",
"display_name": "Ultimaker B.V.",
"email": "plugins@ultimaker.com",
"website": "https://ultimaker.com"
@@ -107,11 +124,28 @@
"package_type": "plugin",
"display_name": "Firmware Update Checker",
"description": "Checks for firmware updates.",
- "package_version": "1.0.0",
- "sdk_version": 5,
+ "package_version": "1.0.1",
+ "sdk_version": "6.0.0",
"website": "https://ultimaker.com",
"author": {
- "author_id": "Ultimaker",
+ "author_id": "UltimakerPackages",
+ "display_name": "Ultimaker B.V.",
+ "email": "plugins@ultimaker.com",
+ "website": "https://ultimaker.com"
+ }
+ }
+ },
+ "FirmwareUpdater": {
+ "package_info": {
+ "package_id": "FirmwareUpdater",
+ "package_type": "plugin",
+ "display_name": "Firmware Updater",
+ "description": "Provides a machine actions for updating firmware.",
+ "package_version": "1.0.1",
+ "sdk_version": "6.0.0",
+ "website": "https://ultimaker.com",
+ "author": {
+ "author_id": "UltimakerPackages",
"display_name": "Ultimaker B.V.",
"email": "plugins@ultimaker.com",
"website": "https://ultimaker.com"
@@ -124,11 +158,11 @@
"package_type": "plugin",
"display_name": "Compressed G-code Reader",
"description": "Reads g-code from a compressed archive.",
- "package_version": "1.0.0",
- "sdk_version": 5,
+ "package_version": "1.0.1",
+ "sdk_version": "6.0.0",
"website": "https://ultimaker.com",
"author": {
- "author_id": "Ultimaker",
+ "author_id": "UltimakerPackages",
"display_name": "Ultimaker B.V.",
"email": "plugins@ultimaker.com",
"website": "https://ultimaker.com"
@@ -141,11 +175,11 @@
"package_type": "plugin",
"display_name": "Compressed G-code Writer",
"description": "Writes g-code to a compressed archive.",
- "package_version": "1.0.0",
- "sdk_version": 5,
+ "package_version": "1.0.1",
+ "sdk_version": "6.0.0",
"website": "https://ultimaker.com",
"author": {
- "author_id": "Ultimaker",
+ "author_id": "UltimakerPackages",
"display_name": "Ultimaker B.V.",
"email": "plugins@ultimaker.com",
"website": "https://ultimaker.com"
@@ -158,11 +192,11 @@
"package_type": "plugin",
"display_name": "G-Code Profile Reader",
"description": "Provides support for importing profiles from g-code files.",
- "package_version": "1.0.0",
- "sdk_version": 5,
+ "package_version": "1.0.1",
+ "sdk_version": "6.0.0",
"website": "https://ultimaker.com",
"author": {
- "author_id": "Ultimaker",
+ "author_id": "UltimakerPackages",
"display_name": "Ultimaker B.V.",
"email": "plugins@ultimaker.com",
"website": "https://ultimaker.com"
@@ -175,8 +209,8 @@
"package_type": "plugin",
"display_name": "G-Code Reader",
"description": "Allows loading and displaying G-code files.",
- "package_version": "1.0.0",
- "sdk_version": 5,
+ "package_version": "1.0.1",
+ "sdk_version": "6.0.0",
"website": "https://ultimaker.com",
"author": {
"author_id": "VictorLarchenko",
@@ -192,11 +226,11 @@
"package_type": "plugin",
"display_name": "G-Code Writer",
"description": "Writes g-code to a file.",
- "package_version": "1.0.0",
- "sdk_version": 5,
+ "package_version": "1.0.1",
+ "sdk_version": "6.0.0",
"website": "https://ultimaker.com",
"author": {
- "author_id": "Ultimaker",
+ "author_id": "UltimakerPackages",
"display_name": "Ultimaker B.V.",
"email": "plugins@ultimaker.com",
"website": "https://ultimaker.com"
@@ -209,11 +243,11 @@
"package_type": "plugin",
"display_name": "Image Reader",
"description": "Enables ability to generate printable geometry from 2D image files.",
- "package_version": "1.0.0",
- "sdk_version": 5,
+ "package_version": "1.0.1",
+ "sdk_version": "6.0.0",
"website": "https://ultimaker.com",
"author": {
- "author_id": "Ultimaker",
+ "author_id": "UltimakerPackages",
"display_name": "Ultimaker B.V.",
"email": "plugins@ultimaker.com",
"website": "https://ultimaker.com"
@@ -226,11 +260,11 @@
"package_type": "plugin",
"display_name": "Legacy Cura Profile Reader",
"description": "Provides support for importing profiles from legacy Cura versions.",
- "package_version": "1.0.0",
- "sdk_version": 5,
+ "package_version": "1.0.1",
+ "sdk_version": "6.0.0",
"website": "https://ultimaker.com",
"author": {
- "author_id": "Ultimaker",
+ "author_id": "UltimakerPackages",
"display_name": "Ultimaker B.V.",
"email": "plugins@ultimaker.com",
"website": "https://ultimaker.com"
@@ -243,8 +277,8 @@
"package_type": "plugin",
"display_name": "Machine Settings Action",
"description": "Provides a way to change machine settings (such as build volume, nozzle size, etc.).",
- "package_version": "1.0.0",
- "sdk_version": 5,
+ "package_version": "1.0.1",
+ "sdk_version": "6.0.0",
"website": "https://ultimaker.com",
"author": {
"author_id": "fieldOfView",
@@ -260,11 +294,11 @@
"package_type": "plugin",
"display_name": "Model Checker",
"description": "Checks models and print configuration for possible printing issues and give suggestions.",
- "package_version": "0.1.0",
- "sdk_version": 5,
+ "package_version": "1.0.1",
+ "sdk_version": "6.0.0",
"website": "https://ultimaker.com",
"author": {
- "author_id": "Ultimaker",
+ "author_id": "UltimakerPackages",
"display_name": "Ultimaker B.V.",
"email": "plugins@ultimaker.com",
"website": "https://ultimaker.com"
@@ -277,11 +311,11 @@
"package_type": "plugin",
"display_name": "Monitor Stage",
"description": "Provides a monitor stage in Cura.",
- "package_version": "1.0.0",
- "sdk_version": 5,
+ "package_version": "1.0.1",
+ "sdk_version": "6.0.0",
"website": "https://ultimaker.com",
"author": {
- "author_id": "Ultimaker",
+ "author_id": "UltimakerPackages",
"display_name": "Ultimaker B.V.",
"email": "plugins@ultimaker.com",
"website": "https://ultimaker.com"
@@ -294,11 +328,11 @@
"package_type": "plugin",
"display_name": "Per-Object Settings Tool",
"description": "Provides the per-model settings.",
- "package_version": "1.0.0",
- "sdk_version": 5,
+ "package_version": "1.0.1",
+ "sdk_version": "6.0.0",
"website": "https://ultimaker.com",
"author": {
- "author_id": "Ultimaker",
+ "author_id": "UltimakerPackages",
"display_name": "Ultimaker B.V.",
"email": "plugins@ultimaker.com",
"website": "https://ultimaker.com"
@@ -311,11 +345,11 @@
"package_type": "plugin",
"display_name": "Post Processing",
"description": "Extension that allows for user created scripts for post processing.",
- "package_version": "2.2.0",
- "sdk_version": 5,
+ "package_version": "2.2.1",
+ "sdk_version": "6.0.0",
"website": "https://ultimaker.com",
"author": {
- "author_id": "Ultimaker",
+ "author_id": "UltimakerPackages",
"display_name": "Ultimaker B.V.",
"email": "plugins@ultimaker.com",
"website": "https://ultimaker.com"
@@ -328,11 +362,28 @@
"package_type": "plugin",
"display_name": "Prepare Stage",
"description": "Provides a prepare stage in Cura.",
- "package_version": "1.0.0",
- "sdk_version": 5,
+ "package_version": "1.0.1",
+ "sdk_version": "6.0.0",
"website": "https://ultimaker.com",
"author": {
- "author_id": "Ultimaker",
+ "author_id": "UltimakerPackages",
+ "display_name": "Ultimaker B.V.",
+ "email": "plugins@ultimaker.com",
+ "website": "https://ultimaker.com"
+ }
+ }
+ },
+ "PreviewStage": {
+ "package_info": {
+ "package_id": "PreviewStage",
+ "package_type": "plugin",
+ "display_name": "Preview Stage",
+ "description": "Provides a preview stage in Cura.",
+ "package_version": "1.0.1",
+ "sdk_version": "6.0.0",
+ "website": "https://ultimaker.com",
+ "author": {
+ "author_id": "UltimakerPackages",
"display_name": "Ultimaker B.V.",
"email": "plugins@ultimaker.com",
"website": "https://ultimaker.com"
@@ -345,11 +396,11 @@
"package_type": "plugin",
"display_name": "Removable Drive Output Device",
"description": "Provides removable drive hotplugging and writing support.",
- "package_version": "1.0.0",
- "sdk_version": 5,
+ "package_version": "1.0.1",
+ "sdk_version": "6.0.0",
"website": "https://ultimaker.com",
"author": {
- "author_id": "Ultimaker",
+ "author_id": "UltimakerPackages",
"display_name": "Ultimaker B.V.",
"email": "plugins@ultimaker.com",
"website": "https://ultimaker.com"
@@ -362,11 +413,11 @@
"package_type": "plugin",
"display_name": "Simulation View",
"description": "Provides the Simulation view.",
- "package_version": "1.0.0",
- "sdk_version": 5,
+ "package_version": "1.0.1",
+ "sdk_version": "6.0.0",
"website": "https://ultimaker.com",
"author": {
- "author_id": "Ultimaker",
+ "author_id": "UltimakerPackages",
"display_name": "Ultimaker B.V.",
"email": "plugins@ultimaker.com",
"website": "https://ultimaker.com"
@@ -379,11 +430,11 @@
"package_type": "plugin",
"display_name": "Slice Info",
"description": "Submits anonymous slice info. Can be disabled through preferences.",
- "package_version": "1.0.0",
- "sdk_version": 5,
+ "package_version": "1.0.1",
+ "sdk_version": "6.0.0",
"website": "https://ultimaker.com",
"author": {
- "author_id": "Ultimaker",
+ "author_id": "UltimakerPackages",
"display_name": "Ultimaker B.V.",
"email": "plugins@ultimaker.com",
"website": "https://ultimaker.com"
@@ -396,11 +447,11 @@
"package_type": "plugin",
"display_name": "Solid View",
"description": "Provides a normal solid mesh view.",
- "package_version": "1.0.0",
- "sdk_version": 5,
+ "package_version": "1.0.1",
+ "sdk_version": "6.0.0",
"website": "https://ultimaker.com",
"author": {
- "author_id": "Ultimaker",
+ "author_id": "UltimakerPackages",
"display_name": "Ultimaker B.V.",
"email": "plugins@ultimaker.com",
"website": "https://ultimaker.com"
@@ -413,11 +464,11 @@
"package_type": "plugin",
"display_name": "Support Eraser Tool",
"description": "Creates an eraser mesh to block the printing of support in certain places.",
- "package_version": "1.0.0",
- "sdk_version": 5,
+ "package_version": "1.0.1",
+ "sdk_version": "6.0.0",
"website": "https://ultimaker.com",
"author": {
- "author_id": "Ultimaker",
+ "author_id": "UltimakerPackages",
"display_name": "Ultimaker B.V.",
"email": "plugins@ultimaker.com",
"website": "https://ultimaker.com"
@@ -430,11 +481,28 @@
"package_type": "plugin",
"display_name": "Toolbox",
"description": "Find, manage and install new Cura packages.",
- "package_version": "1.0.0",
- "sdk_version": 5,
+ "package_version": "1.0.1",
+ "sdk_version": "6.0.0",
"website": "https://ultimaker.com",
"author": {
- "author_id": "Ultimaker",
+ "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": "6.0.0",
+ "website": "https://ultimaker.com",
+ "author": {
+ "author_id": "UltimakerPackages",
"display_name": "Ultimaker B.V.",
"email": "plugins@ultimaker.com",
"website": "https://ultimaker.com"
@@ -447,11 +515,11 @@
"package_type": "plugin",
"display_name": "UFP Writer",
"description": "Provides support for writing Ultimaker Format Packages.",
- "package_version": "1.0.0",
- "sdk_version": 5,
+ "package_version": "1.0.1",
+ "sdk_version": "6.0.0",
"website": "https://ultimaker.com",
"author": {
- "author_id": "Ultimaker",
+ "author_id": "UltimakerPackages",
"display_name": "Ultimaker B.V.",
"email": "plugins@ultimaker.com",
"website": "https://ultimaker.com"
@@ -464,11 +532,11 @@
"package_type": "plugin",
"display_name": "Ultimaker Machine Actions",
"description": "Provides machine actions for Ultimaker machines (such as bed leveling wizard, selecting upgrades, etc.).",
- "package_version": "1.0.0",
- "sdk_version": 5,
+ "package_version": "1.0.1",
+ "sdk_version": "6.0.0",
"website": "https://ultimaker.com",
"author": {
- "author_id": "Ultimaker",
+ "author_id": "UltimakerPackages",
"display_name": "Ultimaker B.V.",
"email": "plugins@ultimaker.com",
"website": "https://ultimaker.com"
@@ -481,11 +549,11 @@
"package_type": "plugin",
"display_name": "UM3 Network Printing",
"description": "Manages network connections to Ultimaker 3 printers.",
- "package_version": "1.0.0",
- "sdk_version": 5,
+ "package_version": "1.0.1",
+ "sdk_version": "6.0.0",
"website": "https://ultimaker.com",
"author": {
- "author_id": "Ultimaker",
+ "author_id": "UltimakerPackages",
"display_name": "Ultimaker B.V.",
"email": "plugins@ultimaker.com",
"website": "https://ultimaker.com"
@@ -498,28 +566,11 @@
"package_type": "plugin",
"display_name": "USB Printing",
"description": "Accepts G-Code and sends them to a printer. Plugin can also update firmware.",
- "package_version": "1.0.0",
- "sdk_version": 5,
+ "package_version": "1.0.2",
+ "sdk_version": "6.0.0",
"website": "https://ultimaker.com",
"author": {
- "author_id": "Ultimaker",
- "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.0",
- "sdk_version": 5,
- "website": "https://ultimaker.com",
- "author": {
- "author_id": "Ultimaker",
+ "author_id": "UltimakerPackages",
"display_name": "Ultimaker B.V.",
"email": "plugins@ultimaker.com",
"website": "https://ultimaker.com"
@@ -532,11 +583,11 @@
"package_type": "plugin",
"display_name": "Version Upgrade 2.1 to 2.2",
"description": "Upgrades configurations from Cura 2.1 to Cura 2.2.",
- "package_version": "1.0.0",
- "sdk_version": 5,
+ "package_version": "1.0.1",
+ "sdk_version": "6.0.0",
"website": "https://ultimaker.com",
"author": {
- "author_id": "Ultimaker",
+ "author_id": "UltimakerPackages",
"display_name": "Ultimaker B.V.",
"email": "plugins@ultimaker.com",
"website": "https://ultimaker.com"
@@ -549,11 +600,11 @@
"package_type": "plugin",
"display_name": "Version Upgrade 2.2 to 2.4",
"description": "Upgrades configurations from Cura 2.2 to Cura 2.4.",
- "package_version": "1.0.0",
- "sdk_version": 5,
+ "package_version": "1.0.1",
+ "sdk_version": "6.0.0",
"website": "https://ultimaker.com",
"author": {
- "author_id": "Ultimaker",
+ "author_id": "UltimakerPackages",
"display_name": "Ultimaker B.V.",
"email": "plugins@ultimaker.com",
"website": "https://ultimaker.com"
@@ -566,11 +617,11 @@
"package_type": "plugin",
"display_name": "Version Upgrade 2.5 to 2.6",
"description": "Upgrades configurations from Cura 2.5 to Cura 2.6.",
- "package_version": "1.0.0",
- "sdk_version": 5,
+ "package_version": "1.0.1",
+ "sdk_version": "6.0.0",
"website": "https://ultimaker.com",
"author": {
- "author_id": "Ultimaker",
+ "author_id": "UltimakerPackages",
"display_name": "Ultimaker B.V.",
"email": "plugins@ultimaker.com",
"website": "https://ultimaker.com"
@@ -583,11 +634,11 @@
"package_type": "plugin",
"display_name": "Version Upgrade 2.6 to 2.7",
"description": "Upgrades configurations from Cura 2.6 to Cura 2.7.",
- "package_version": "1.0.0",
- "sdk_version": 5,
+ "package_version": "1.0.1",
+ "sdk_version": "6.0.0",
"website": "https://ultimaker.com",
"author": {
- "author_id": "Ultimaker",
+ "author_id": "UltimakerPackages",
"display_name": "Ultimaker B.V.",
"email": "plugins@ultimaker.com",
"website": "https://ultimaker.com"
@@ -600,11 +651,11 @@
"package_type": "plugin",
"display_name": "Version Upgrade 2.7 to 3.0",
"description": "Upgrades configurations from Cura 2.7 to Cura 3.0.",
- "package_version": "1.0.0",
- "sdk_version": 5,
+ "package_version": "1.0.1",
+ "sdk_version": "6.0.0",
"website": "https://ultimaker.com",
"author": {
- "author_id": "Ultimaker",
+ "author_id": "UltimakerPackages",
"display_name": "Ultimaker B.V.",
"email": "plugins@ultimaker.com",
"website": "https://ultimaker.com"
@@ -617,11 +668,11 @@
"package_type": "plugin",
"display_name": "Version Upgrade 3.0 to 3.1",
"description": "Upgrades configurations from Cura 3.0 to Cura 3.1.",
- "package_version": "1.0.0",
- "sdk_version": 5,
+ "package_version": "1.0.1",
+ "sdk_version": "6.0.0",
"website": "https://ultimaker.com",
"author": {
- "author_id": "Ultimaker",
+ "author_id": "UltimakerPackages",
"display_name": "Ultimaker B.V.",
"email": "plugins@ultimaker.com",
"website": "https://ultimaker.com"
@@ -634,11 +685,11 @@
"package_type": "plugin",
"display_name": "Version Upgrade 3.2 to 3.3",
"description": "Upgrades configurations from Cura 3.2 to Cura 3.3.",
- "package_version": "1.0.0",
- "sdk_version": 5,
+ "package_version": "1.0.1",
+ "sdk_version": "6.0.0",
"website": "https://ultimaker.com",
"author": {
- "author_id": "Ultimaker",
+ "author_id": "UltimakerPackages",
"display_name": "Ultimaker B.V.",
"email": "plugins@ultimaker.com",
"website": "https://ultimaker.com"
@@ -651,11 +702,11 @@
"package_type": "plugin",
"display_name": "Version Upgrade 3.3 to 3.4",
"description": "Upgrades configurations from Cura 3.3 to Cura 3.4.",
- "package_version": "1.0.0",
- "sdk_version": 5,
+ "package_version": "1.0.1",
+ "sdk_version": "6.0.0",
"website": "https://ultimaker.com",
"author": {
- "author_id": "Ultimaker",
+ "author_id": "UltimakerPackages",
"display_name": "Ultimaker B.V.",
"email": "plugins@ultimaker.com",
"website": "https://ultimaker.com"
@@ -668,11 +719,79 @@
"package_type": "plugin",
"display_name": "Version Upgrade 3.4 to 3.5",
"description": "Upgrades configurations from Cura 3.4 to Cura 3.5.",
- "package_version": "1.0.0",
- "sdk_version": 5,
+ "package_version": "1.0.1",
+ "sdk_version": "6.0.0",
"website": "https://ultimaker.com",
"author": {
- "author_id": "Ultimaker",
+ "author_id": "UltimakerPackages",
+ "display_name": "Ultimaker B.V.",
+ "email": "plugins@ultimaker.com",
+ "website": "https://ultimaker.com"
+ }
+ }
+ },
+ "VersionUpgrade35to40": {
+ "package_info": {
+ "package_id": "VersionUpgrade35to40",
+ "package_type": "plugin",
+ "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.0",
+ "website": "https://ultimaker.com",
+ "author": {
+ "author_id": "UltimakerPackages",
+ "display_name": "Ultimaker B.V.",
+ "email": "plugins@ultimaker.com",
+ "website": "https://ultimaker.com"
+ }
+ }
+ },
+ "VersionUpgrade40to41": {
+ "package_info": {
+ "package_id": "VersionUpgrade40to41",
+ "package_type": "plugin",
+ "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.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": "6.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": "6.0.0",
+ "website": "https://ultimaker.com",
+ "author": {
+ "author_id": "UltimakerPackages",
"display_name": "Ultimaker B.V.",
"email": "plugins@ultimaker.com",
"website": "https://ultimaker.com"
@@ -685,8 +804,8 @@
"package_type": "plugin",
"display_name": "X3D Reader",
"description": "Provides support for reading X3D files.",
- "package_version": "0.5.0",
- "sdk_version": 5,
+ "package_version": "1.0.1",
+ "sdk_version": "6.0.0",
"website": "https://ultimaker.com",
"author": {
"author_id": "SevaAlekseyev",
@@ -702,11 +821,11 @@
"package_type": "plugin",
"display_name": "XML Material Profiles",
"description": "Provides capabilities to read and write XML-based material profiles.",
- "package_version": "1.0.0",
- "sdk_version": 5,
+ "package_version": "1.0.1",
+ "sdk_version": "6.0.0",
"website": "https://ultimaker.com",
"author": {
- "author_id": "Ultimaker",
+ "author_id": "UltimakerPackages",
"display_name": "Ultimaker B.V.",
"email": "plugins@ultimaker.com",
"website": "https://ultimaker.com"
@@ -719,11 +838,11 @@
"package_type": "plugin",
"display_name": "X-Ray View",
"description": "Provides the X-Ray view.",
- "package_version": "1.0.0",
- "sdk_version": 5,
+ "package_version": "1.0.1",
+ "sdk_version": "6.0.0",
"website": "https://ultimaker.com",
"author": {
- "author_id": "Ultimaker",
+ "author_id": "UltimakerPackages",
"display_name": "Ultimaker B.V.",
"email": "plugins@ultimaker.com",
"website": "https://ultimaker.com"
@@ -736,8 +855,8 @@
"package_type": "material",
"display_name": "Generic ABS",
"description": "The generic ABS profile which other profiles can be based upon.",
- "package_version": "1.0.0",
- "sdk_version": 6,
+ "package_version": "1.2.1",
+ "sdk_version": "6.0.0",
"website": "https://github.com/Ultimaker/fdm_materials",
"author": {
"author_id": "Generic",
@@ -754,8 +873,44 @@
"package_type": "material",
"display_name": "Generic BAM",
"description": "The generic BAM profile which other profiles can be based upon.",
- "package_version": "1.0.0",
- "sdk_version": 6,
+ "package_version": "1.2.1",
+ "sdk_version": "6.0.0",
+ "website": "https://github.com/Ultimaker/fdm_materials",
+ "author": {
+ "author_id": "Generic",
+ "display_name": "Generic",
+ "email": "materials@ultimaker.com",
+ "website": "https://github.com/Ultimaker/fdm_materials",
+ "description": "Professional 3D printing made accessible."
+ }
+ }
+ },
+ "GenericCFFCPE": {
+ "package_info": {
+ "package_id": "GenericCFFCPE",
+ "package_type": "material",
+ "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.0",
+ "website": "https://github.com/Ultimaker/fdm_materials",
+ "author": {
+ "author_id": "Generic",
+ "display_name": "Generic",
+ "email": "materials@ultimaker.com",
+ "website": "https://github.com/Ultimaker/fdm_materials",
+ "description": "Professional 3D printing made accessible."
+ }
+ }
+ },
+ "GenericCFFPA": {
+ "package_info": {
+ "package_id": "GenericCFFPA",
+ "package_type": "material",
+ "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.0",
"website": "https://github.com/Ultimaker/fdm_materials",
"author": {
"author_id": "Generic",
@@ -772,8 +927,8 @@
"package_type": "material",
"display_name": "Generic CPE",
"description": "The generic CPE profile which other profiles can be based upon.",
- "package_version": "1.0.0",
- "sdk_version": 6,
+ "package_version": "1.2.1",
+ "sdk_version": "6.0.0",
"website": "https://github.com/Ultimaker/fdm_materials",
"author": {
"author_id": "Generic",
@@ -790,8 +945,44 @@
"package_type": "material",
"display_name": "Generic CPE+",
"description": "The generic CPE+ profile which other profiles can be based upon.",
- "package_version": "1.0.0",
- "sdk_version": 6,
+ "package_version": "1.2.1",
+ "sdk_version": "6.0.0",
+ "website": "https://github.com/Ultimaker/fdm_materials",
+ "author": {
+ "author_id": "Generic",
+ "display_name": "Generic",
+ "email": "materials@ultimaker.com",
+ "website": "https://github.com/Ultimaker/fdm_materials",
+ "description": "Professional 3D printing made accessible."
+ }
+ }
+ },
+ "GenericGFFCPE": {
+ "package_info": {
+ "package_id": "GenericGFFCPE",
+ "package_type": "material",
+ "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.0",
+ "website": "https://github.com/Ultimaker/fdm_materials",
+ "author": {
+ "author_id": "Generic",
+ "display_name": "Generic",
+ "email": "materials@ultimaker.com",
+ "website": "https://github.com/Ultimaker/fdm_materials",
+ "description": "Professional 3D printing made accessible."
+ }
+ }
+ },
+ "GenericGFFPA": {
+ "package_info": {
+ "package_id": "GenericGFFPA",
+ "package_type": "material",
+ "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.0",
"website": "https://github.com/Ultimaker/fdm_materials",
"author": {
"author_id": "Generic",
@@ -808,8 +999,8 @@
"package_type": "material",
"display_name": "Generic HIPS",
"description": "The generic HIPS profile which other profiles can be based upon.",
- "package_version": "1.0.0",
- "sdk_version": 6,
+ "package_version": "1.0.1",
+ "sdk_version": "6.0.0",
"website": "https://github.com/Ultimaker/fdm_materials",
"author": {
"author_id": "Generic",
@@ -826,8 +1017,8 @@
"package_type": "material",
"display_name": "Generic Nylon",
"description": "The generic Nylon profile which other profiles can be based upon.",
- "package_version": "1.0.0",
- "sdk_version": 6,
+ "package_version": "1.2.1",
+ "sdk_version": "6.0.0",
"website": "https://github.com/Ultimaker/fdm_materials",
"author": {
"author_id": "Generic",
@@ -844,8 +1035,8 @@
"package_type": "material",
"display_name": "Generic PC",
"description": "The generic PC profile which other profiles can be based upon.",
- "package_version": "1.0.0",
- "sdk_version": 6,
+ "package_version": "1.2.1",
+ "sdk_version": "6.0.0",
"website": "https://github.com/Ultimaker/fdm_materials",
"author": {
"author_id": "Generic",
@@ -862,8 +1053,8 @@
"package_type": "material",
"display_name": "Generic PETG",
"description": "The generic PETG profile which other profiles can be based upon.",
- "package_version": "1.0.0",
- "sdk_version": 6,
+ "package_version": "1.0.1",
+ "sdk_version": "6.0.0",
"website": "https://github.com/Ultimaker/fdm_materials",
"author": {
"author_id": "Generic",
@@ -880,8 +1071,8 @@
"package_type": "material",
"display_name": "Generic PLA",
"description": "The generic PLA profile which other profiles can be based upon.",
- "package_version": "1.0.0",
- "sdk_version": 6,
+ "package_version": "1.2.1",
+ "sdk_version": "6.0.0",
"website": "https://github.com/Ultimaker/fdm_materials",
"author": {
"author_id": "Generic",
@@ -898,8 +1089,8 @@
"package_type": "material",
"display_name": "Generic PP",
"description": "The generic PP profile which other profiles can be based upon.",
- "package_version": "1.0.0",
- "sdk_version": 6,
+ "package_version": "1.2.1",
+ "sdk_version": "6.0.0",
"website": "https://github.com/Ultimaker/fdm_materials",
"author": {
"author_id": "Generic",
@@ -916,8 +1107,8 @@
"package_type": "material",
"display_name": "Generic PVA",
"description": "The generic PVA profile which other profiles can be based upon.",
- "package_version": "1.0.0",
- "sdk_version": 6,
+ "package_version": "1.2.1",
+ "sdk_version": "6.0.0",
"website": "https://github.com/Ultimaker/fdm_materials",
"author": {
"author_id": "Generic",
@@ -934,8 +1125,8 @@
"package_type": "material",
"display_name": "Generic Tough PLA",
"description": "The generic Tough PLA profile which other profiles can be based upon.",
- "package_version": "1.0.0",
- "sdk_version": 6,
+ "package_version": "1.0.2",
+ "sdk_version": "6.0.0",
"website": "https://github.com/Ultimaker/fdm_materials",
"author": {
"author_id": "Generic",
@@ -952,8 +1143,8 @@
"package_type": "material",
"display_name": "Generic TPU",
"description": "The generic TPU profile which other profiles can be based upon.",
- "package_version": "1.0.0",
- "sdk_version": 6,
+ "package_version": "1.2.1",
+ "sdk_version": "6.0.0",
"website": "https://github.com/Ultimaker/fdm_materials",
"author": {
"author_id": "Generic",
@@ -970,8 +1161,8 @@
"package_type": "material",
"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.0",
- "sdk_version": 5,
+ "package_version": "1.0.1",
+ "sdk_version": "6.0.0",
"website": "https://dagoma.fr/boutique/filaments.html",
"author": {
"author_id": "Dagoma",
@@ -987,8 +1178,8 @@
"package_type": "material",
"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.0",
- "sdk_version": 5,
+ "package_version": "1.0.1",
+ "sdk_version": "6.0.0",
"website": "https://store.fabtotum.com/eu/products/filaments.html?filament_type=40",
"author": {
"author_id": "FABtotum",
@@ -1004,8 +1195,8 @@
"package_type": "material",
"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.0",
- "sdk_version": 5,
+ "package_version": "1.0.1",
+ "sdk_version": "6.0.0",
"website": "https://store.fabtotum.com/eu/products/filaments.html?filament_type=53",
"author": {
"author_id": "FABtotum",
@@ -1021,8 +1212,8 @@
"package_type": "material",
"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.0",
- "sdk_version": 5,
+ "package_version": "1.0.1",
+ "sdk_version": "6.0.0",
"website": "https://store.fabtotum.com/eu/products/filaments.html?filament_type=39",
"author": {
"author_id": "FABtotum",
@@ -1038,8 +1229,8 @@
"package_type": "material",
"display_name": "FABtotum TPU Shore 98A",
"description": "",
- "package_version": "1.0.0",
- "sdk_version": 5,
+ "package_version": "1.0.1",
+ "sdk_version": "6.0.0",
"website": "https://store.fabtotum.com/eu/products/filaments.html?filament_type=66",
"author": {
"author_id": "FABtotum",
@@ -1055,12 +1246,12 @@
"package_type": "material",
"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.0",
- "sdk_version": 5,
+ "package_version": "1.0.1",
+ "sdk_version": "6.0.0",
"website": "http://fiberlogy.com/en/fiberlogy-filaments/filament-hd-pla/",
"author": {
"author_id": "Fiberlogy",
- "diplay_name": "Fiberlogy S.A.",
+ "display_name": "Fiberlogy S.A.",
"email": "grzegorz.h@fiberlogy.com",
"website": "http://fiberlogy.com"
}
@@ -1072,8 +1263,8 @@
"package_type": "material",
"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.0",
- "sdk_version": 5,
+ "package_version": "1.0.1",
+ "sdk_version": "6.0.0",
"website": "https://dagoma.fr",
"author": {
"author_id": "Dagoma",
@@ -1089,8 +1280,8 @@
"package_type": "material",
"display_name": "IMADE3D JellyBOX PETG",
"description": "",
- "package_version": "1.0.0",
- "sdk_version": 5,
+ "package_version": "1.0.1",
+ "sdk_version": "6.0.0",
"website": "http://shop.imade3d.com/filament.html",
"author": {
"author_id": "IMADE3D",
@@ -1106,8 +1297,8 @@
"package_type": "material",
"display_name": "IMADE3D JellyBOX PLA",
"description": "",
- "package_version": "1.0.0",
- "sdk_version": 5,
+ "package_version": "1.0.1",
+ "sdk_version": "6.0.0",
"website": "http://shop.imade3d.com/filament.html",
"author": {
"author_id": "IMADE3D",
@@ -1123,8 +1314,8 @@
"package_type": "material",
"display_name": "Octofiber PLA",
"description": "PLA material from Octofiber.",
- "package_version": "1.0.0",
- "sdk_version": 5,
+ "package_version": "1.0.1",
+ "sdk_version": "6.0.0",
"website": "https://nl.octofiber.com/3d-printing-filament/pla.html",
"author": {
"author_id": "Octofiber",
@@ -1140,8 +1331,8 @@
"package_type": "material",
"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.0",
- "sdk_version": 5,
+ "package_version": "1.0.1",
+ "sdk_version": "6.0.0",
"website": "http://www.polymaker.com/shop/polyflex/",
"author": {
"author_id": "Polymaker",
@@ -1157,8 +1348,8 @@
"package_type": "material",
"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.0",
- "sdk_version": 5,
+ "package_version": "1.0.1",
+ "sdk_version": "6.0.0",
"website": "http://www.polymaker.com/shop/polymax/",
"author": {
"author_id": "Polymaker",
@@ -1174,8 +1365,8 @@
"package_type": "material",
"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.0",
- "sdk_version": 5,
+ "package_version": "1.0.1",
+ "sdk_version": "6.0.0",
"website": "http://www.polymaker.com/shop/polyplus-true-colour/",
"author": {
"author_id": "Polymaker",
@@ -1191,8 +1382,8 @@
"package_type": "material",
"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.0",
- "sdk_version": 5,
+ "package_version": "1.0.1",
+ "sdk_version": "6.0.0",
"website": "http://www.polymaker.com/shop/polywood/",
"author": {
"author_id": "Polymaker",
@@ -1208,11 +1399,30 @@
"package_type": "material",
"display_name": "Ultimaker ABS",
"description": "Example package for material and quality profiles for Ultimaker materials.",
- "package_version": "1.0.0",
- "sdk_version": 5,
+ "package_version": "1.2.2",
+ "sdk_version": "6.0.0",
"website": "https://ultimaker.com/products/materials/abs",
"author": {
- "author_id": "Ultimaker",
+ "author_id": "UltimakerPackages",
+ "display_name": "Ultimaker B.V.",
+ "email": "materials@ultimaker.com",
+ "website": "https://ultimaker.com",
+ "description": "Professional 3D printing made accessible.",
+ "support_website": "https://ultimaker.com/en/resources/troubleshooting/materials"
+ }
+ }
+ },
+ "UltimakerBAM": {
+ "package_info": {
+ "package_id": "UltimakerBAM",
+ "package_type": "material",
+ "display_name": "Ultimaker Breakaway",
+ "description": "Example package for material and quality profiles for Ultimaker materials.",
+ "package_version": "1.2.1",
+ "sdk_version": "6.0.0",
+ "website": "https://ultimaker.com/products/materials/breakaway",
+ "author": {
+ "author_id": "UltimakerPackages",
"display_name": "Ultimaker B.V.",
"email": "materials@ultimaker.com",
"website": "https://ultimaker.com",
@@ -1227,11 +1437,30 @@
"package_type": "material",
"display_name": "Ultimaker CPE",
"description": "Example package for material and quality profiles for Ultimaker materials.",
- "package_version": "1.0.0",
- "sdk_version": 5,
+ "package_version": "1.2.2",
+ "sdk_version": "6.0.0",
"website": "https://ultimaker.com/products/materials/abs",
"author": {
- "author_id": "Ultimaker",
+ "author_id": "UltimakerPackages",
+ "display_name": "Ultimaker B.V.",
+ "email": "materials@ultimaker.com",
+ "website": "https://ultimaker.com",
+ "description": "Professional 3D printing made accessible.",
+ "support_website": "https://ultimaker.com/en/resources/troubleshooting/materials"
+ }
+ }
+ },
+ "UltimakerCPEP": {
+ "package_info": {
+ "package_id": "UltimakerCPEP",
+ "package_type": "material",
+ "display_name": "Ultimaker CPE+",
+ "description": "Example package for material and quality profiles for Ultimaker materials.",
+ "package_version": "1.2.2",
+ "sdk_version": "6.0.0",
+ "website": "https://ultimaker.com/products/materials/cpe",
+ "author": {
+ "author_id": "UltimakerPackages",
"display_name": "Ultimaker B.V.",
"email": "materials@ultimaker.com",
"website": "https://ultimaker.com",
@@ -1246,11 +1475,11 @@
"package_type": "material",
"display_name": "Ultimaker Nylon",
"description": "Example package for material and quality profiles for Ultimaker materials.",
- "package_version": "1.0.0",
- "sdk_version": 5,
+ "package_version": "1.2.2",
+ "sdk_version": "6.0.0",
"website": "https://ultimaker.com/products/materials/abs",
"author": {
- "author_id": "Ultimaker",
+ "author_id": "UltimakerPackages",
"display_name": "Ultimaker B.V.",
"email": "materials@ultimaker.com",
"website": "https://ultimaker.com",
@@ -1265,11 +1494,11 @@
"package_type": "material",
"display_name": "Ultimaker PC",
"description": "Example package for material and quality profiles for Ultimaker materials.",
- "package_version": "1.0.0",
- "sdk_version": 5,
+ "package_version": "1.2.2",
+ "sdk_version": "6.0.0",
"website": "https://ultimaker.com/products/materials/pc",
"author": {
- "author_id": "Ultimaker",
+ "author_id": "UltimakerPackages",
"display_name": "Ultimaker B.V.",
"email": "materials@ultimaker.com",
"website": "https://ultimaker.com",
@@ -1284,11 +1513,30 @@
"package_type": "material",
"display_name": "Ultimaker PLA",
"description": "Example package for material and quality profiles for Ultimaker materials.",
- "package_version": "1.0.0",
- "sdk_version": 5,
+ "package_version": "1.2.2",
+ "sdk_version": "6.0.0",
"website": "https://ultimaker.com/products/materials/abs",
"author": {
- "author_id": "Ultimaker",
+ "author_id": "UltimakerPackages",
+ "display_name": "Ultimaker B.V.",
+ "email": "materials@ultimaker.com",
+ "website": "https://ultimaker.com",
+ "description": "Professional 3D printing made accessible.",
+ "support_website": "https://ultimaker.com/en/resources/troubleshooting/materials"
+ }
+ }
+ },
+ "UltimakerPP": {
+ "package_info": {
+ "package_id": "UltimakerPP",
+ "package_type": "material",
+ "display_name": "Ultimaker PP",
+ "description": "Example package for material and quality profiles for Ultimaker materials.",
+ "package_version": "1.2.2",
+ "sdk_version": "6.0.0",
+ "website": "https://ultimaker.com/products/materials/pp",
+ "author": {
+ "author_id": "UltimakerPackages",
"display_name": "Ultimaker B.V.",
"email": "materials@ultimaker.com",
"website": "https://ultimaker.com",
@@ -1303,11 +1551,49 @@
"package_type": "material",
"display_name": "Ultimaker PVA",
"description": "Example package for material and quality profiles for Ultimaker materials.",
- "package_version": "1.0.0",
- "sdk_version": 5,
+ "package_version": "1.2.1",
+ "sdk_version": "6.0.0",
"website": "https://ultimaker.com/products/materials/abs",
"author": {
- "author_id": "Ultimaker",
+ "author_id": "UltimakerPackages",
+ "display_name": "Ultimaker B.V.",
+ "email": "materials@ultimaker.com",
+ "website": "https://ultimaker.com",
+ "description": "Professional 3D printing made accessible.",
+ "support_website": "https://ultimaker.com/en/resources/troubleshooting/materials"
+ }
+ }
+ },
+ "UltimakerTPU": {
+ "package_info": {
+ "package_id": "UltimakerTPU",
+ "package_type": "material",
+ "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.0",
+ "website": "https://ultimaker.com/products/materials/tpu-95a",
+ "author": {
+ "author_id": "UltimakerPackages",
+ "display_name": "Ultimaker B.V.",
+ "email": "materials@ultimaker.com",
+ "website": "https://ultimaker.com",
+ "description": "Professional 3D printing made accessible.",
+ "support_website": "https://ultimaker.com/en/resources/troubleshooting/materials"
+ }
+ }
+ },
+ "UltimakerTPLA": {
+ "package_info": {
+ "package_id": "UltimakerTPLA",
+ "package_type": "material",
+ "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.0",
+ "website": "https://ultimaker.com/products/materials/tough-pla",
+ "author": {
+ "author_id": "UltimakerPackages",
"display_name": "Ultimaker B.V.",
"email": "materials@ultimaker.com",
"website": "https://ultimaker.com",
@@ -1322,8 +1608,8 @@
"package_type": "material",
"display_name": "Vertex Delta ABS",
"description": "ABS material and quality files for the Delta Vertex K8800.",
- "package_version": "1.0.0",
- "sdk_version": 5,
+ "package_version": "1.0.1",
+ "sdk_version": "6.0.0",
"website": "https://vertex3dprinter.eu",
"author": {
"author_id": "Velleman",
@@ -1339,8 +1625,8 @@
"package_type": "material",
"display_name": "Vertex Delta PET",
"description": "ABS material and quality files for the Delta Vertex K8800.",
- "package_version": "1.0.0",
- "sdk_version": 5,
+ "package_version": "1.0.1",
+ "sdk_version": "6.0.0",
"website": "https://vertex3dprinter.eu",
"author": {
"author_id": "Velleman",
@@ -1356,8 +1642,8 @@
"package_type": "material",
"display_name": "Vertex Delta PLA",
"description": "ABS material and quality files for the Delta Vertex K8800.",
- "package_version": "1.0.0",
- "sdk_version": 5,
+ "package_version": "1.0.1",
+ "sdk_version": "6.0.0",
"website": "https://vertex3dprinter.eu",
"author": {
"author_id": "Velleman",
@@ -1373,8 +1659,8 @@
"package_type": "material",
"display_name": "Vertex Delta TPU",
"description": "ABS material and quality files for the Delta Vertex K8800.",
- "package_version": "1.0.0",
- "sdk_version": 5,
+ "package_version": "1.0.1",
+ "sdk_version": "6.0.0",
"website": "https://vertex3dprinter.eu",
"author": {
"author_id": "Velleman",
diff --git a/resources/definitions/101Hero.def.json b/resources/definitions/101Hero.def.json
index d77f01fd82..a77ea5ed97 100644
--- a/resources/definitions/101Hero.def.json
+++ b/resources/definitions/101Hero.def.json
@@ -38,7 +38,7 @@
"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 91f261906b..901ea87510 100644
--- a/resources/definitions/3dator.def.json
+++ b/resources/definitions/3dator.def.json
@@ -7,7 +7,6 @@
"author": "3Dator GmbH",
"manufacturer": "3Dator GmbH",
"file_formats": "text/x-gcode",
- "icon": "icon_ultimaker2",
"supports_usb_connection": true,
"platform": "3dator_platform.stl",
"machine_extruder_trains":
@@ -46,7 +45,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..b7e702036d
--- /dev/null
+++ b/resources/definitions/Mark2_for_Ultimaker2.def.json
@@ -0,0 +1,229 @@
+{
+ "id": "Mark2_for_Ultimaker2",
+ "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_materials": false,
+ "has_machine_quality": false,
+ "has_variant_materials": 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_layer_0": {
+ "default_value": 20
+ },
+ "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": {
+ "default_value": 0,
+ "value": "retraction_amount",
+ "enabled": false
+ },
+ "switch_extruder_retraction_speeds": {
+ "default_value": 25,
+ "value": "retraction_speed",
+ "enabled": false
+ },
+ "switch_extruder_retraction_speed": {
+ "default_value": 25,
+ "value": "retraction_retract_speed",
+ "enabled": false
+ },
+ "switch_extruder_prime_speed": {
+ "default_value": 25,
+ "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" : {
+ "default_value": "",
+ "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" : {
+ "default_value": "",
+ "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":
+ {
+ "default_value": 2000,
+ "value": "2000"
+ },
+ "acceleration_travel":
+ {
+ "default_value": 3000,
+ "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":
+ {
+ "default_value": 20,
+ "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": {
+ "default_value": 185
+ },
+ "prime_tower_position_y": {
+ "default_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/alfawise_u20.def.json b/resources/definitions/alfawise_u20.def.json
new file mode 100644
index 0000000000..748bf8797a
--- /dev/null
+++ b/resources/definitions/alfawise_u20.def.json
@@ -0,0 +1,93 @@
+{
+ "name": "Alfawise U20",
+ "version": 2,
+ "inherits": "fdmprinter",
+ "metadata": {
+ "visible": true,
+ "author": "Samuel Pinches",
+ "manufacturer": "Alfawise",
+ "file_formats": "text/x-gcode",
+ "preferred_quality_type": "fast",
+ "machine_extruder_trains":
+ {
+ "0": "alfawise_u20_extruder_0"
+ }
+ },
+ "overrides": {
+ "machine_name": {
+ "default_value": "Alfawise U20"
+ },
+ "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 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\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": 300
+ },
+ "machine_height": {
+ "default_value": 400
+ },
+ "machine_depth": {
+ "default_value": 300
+ },
+ "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
+ },
+ "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
+ }
+ }
+}
diff --git a/resources/definitions/alfawise_u30.def.json b/resources/definitions/alfawise_u30.def.json
new file mode 100644
index 0000000000..44caf61d1a
--- /dev/null
+++ b/resources/definitions/alfawise_u30.def.json
@@ -0,0 +1,65 @@
+{
+ "name": "Alfawise U30",
+ "version": 2,
+ "inherits": "fdmprinter",
+ "metadata": {
+ "visible": true,
+ "author": "Nicolas Nussbaum",
+ "manufacturer": "Alfawise",
+ "file_formats": "text/x-gcode",
+ "preferred_quality_type": "fast",
+ "machine_extruder_trains":
+ {
+ "0": "alfawise_u30_extruder_0"
+ }
+ },
+ "overrides": {
+ "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 --"
+ },
+ "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": 50 },
+ "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 },
+ "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
new file mode 100644
index 0000000000..05fffcb206
--- /dev/null
+++ b/resources/definitions/anycubic_4max.def.json
@@ -0,0 +1,88 @@
+{
+ "version": 2,
+ "name": "Anycubic 4Max",
+ "inherits": "fdmprinter",
+ "metadata":
+ {
+ "visible": true,
+ "author": "Jason Scurtu",
+ "manufacturer": "Anycubic",
+ "category": "Other",
+ "file_formats": "text/x-gcode",
+ "icon": "icon_ultimaker2",
+ "platform": "anycubic_4max_platform.stl",
+ "has_materials": true,
+ "quality_definition": "anycubic_4max",
+ "has_machine_quality": true,
+ "preferred_quality_type": "normal",
+ "machine_extruder_trains":
+ {
+ "0": "anycubic_4max_extruder_0"
+ }
+ },
+
+ "overrides":
+ {
+ "machine_name": { "default_value": "Anycubic 4Max" },
+ "machine_heated_bed": { "default_value": true },
+ "machine_width": { "default_value": 220 },
+ "machine_height": {"default_value": 300 },
+ "machine_depth": { "default_value": 220 },
+ "machine_center_is_zero": { "default_value": false },
+ "machine_max_feedrate_x": { "default_value": 300 },
+ "machine_max_feedrate_y": { "default_value": 300 },
+ "machine_max_feedrate_z": { "default_value": 10 },
+ "machine_acceleration": { "default_value": 1500 },
+ "machine_max_acceleration_x": { "default_value": 1500 },
+ "machine_max_acceleration_y": { "default_value": 1500 },
+ "machine_max_acceleration_z": { "default_value": 100 },
+ "machine_max_jerk_xy": { "default_value": 11.0 },
+ "machine_max_jerk_z": { "default_value": 0.4 },
+ "machine_max_jerk_e": { "default_value": 11.0 },
+
+ "jerk_enabled": { "value": "True" },
+ "jerk_layer_0": { "value": "jerk_topbottom" },
+ "jerk_prime_tower": { "value": "math.ceil(jerk_print * 15 / 25)" },
+ "jerk_print": { "value": "11" },
+ "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)" },
+
+ "gantry_height": { "value": "25.0" },
+ "skin_overlap": { "value": "10" },
+
+ "acceleration_enabled": { "value": "True" },
+ "acceleration_layer_0": { "value": "acceleration_topbottom" },
+ "acceleration_prime_tower": { "value": "math.ceil(acceleration_print * 2000 / 4000)" },
+ "acceleration_print": { "value": "900" },
+ "acceleration_support": { "value": "math.ceil(acceleration_print * 2000 / 4000)" },
+ "acceleration_support_interface": { "value": "acceleration_topbottom" },
+ "acceleration_topbottom": { "value": "math.ceil(acceleration_print * 1000 / 3000)" },
+ "acceleration_travel": { "value": "acceleration_print" },
+ "acceleration_wall": { "value": "math.ceil(acceleration_print * 1000 / 3000)" },
+ "acceleration_wall_0": { "value": "math.ceil(acceleration_wall * 1000 / 1000)" },
+
+ "speed_layer_0": { "value": "20" },
+ "speed_print": { "value": "40" },
+ "speed_support": { "value": "speed_wall_0" },
+ "speed_support_interface": { "value": "speed_topbottom" },
+ "speed_topbottom": { "value": "math.ceil(speed_print * 20 / 35)" },
+ "speed_travel": { "value": "60" },
+ "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" },
+
+ "infill_pattern": {"value": "'zigzag'" },
+ "infill_before_walls": {"value": false },
+
+ "adhesion_type": { "default_value": "skirt" },
+ "material_bed_temperature": { "maximum_value": "150" },
+ "material_bed_temperature_layer_0": { "maximum_value": "150" },
+
+ "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, 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
new file mode 100644
index 0000000000..1b18a936a7
--- /dev/null
+++ b/resources/definitions/anycubic_chiron.def.json
@@ -0,0 +1,80 @@
+{
+ "version": 2,
+ "name": "Anycubic Chiron",
+ "inherits": "fdmprinter",
+ "metadata":
+ {
+ "visible": true,
+ "author": "Patrick Glatt",
+ "manufacturer": "Anycubic",
+ "category": "Other",
+ "file_formats": "text/x-gcode",
+ "icon": "icon_ultimaker2",
+ "platform": "anycubic_chiron_platform.obj",
+ "platform_texture": "anycubic-chiron.png",
+ "has_materials": true,
+ "preferred_material": "generic_pla",
+ "has_machine_quality": true,
+ "quality_definition": "anycubic_chiron",
+ "preferred_quality_type": "normal",
+ "machine_extruder_trains":
+ {
+ "0": "anycubic_chiron_extruder_0"
+ },
+ "firmware_file": "MarlinChiron.hex"
+ },
+
+ "overrides":
+ {
+ "machine_name":
+ {
+ "default_value": "Anycubic Chiron"
+ },
+ "machine_heated_bed":
+ {
+ "default_value": true
+ },
+ "machine_width":
+ {
+ "default_value": 400
+ },
+ "machine_height":
+ {
+ "default_value": 450
+ },
+ "machine_depth":
+ {
+ "default_value": 400
+ },
+ "machine_center_is_zero":
+ {
+ "default_value": false
+ },
+ "gantry_height":
+ {
+ "value": "35"
+ },
+ "machine_head_with_fans_polygon":
+ {
+ "default_value":
+ [
+ [-45, 50],
+ [-45, -45],
+ [45, 50],
+ [45, -45]
+ ]
+ },
+ "machine_gcode_flavor":
+ {
+ "default_value": "RepRap (Marlin/Sprinter)"
+ },
+ "machine_start_gcode":
+ {
+ "default_value": "M107 ;Start with the fan off\nG21 ;Set units to millimeters\nG91 ;Change to relative positioning mode for retract filament and nozzle lifting\nG1 F200 E-3 ;Retract 3mm filament for a clean start\nG92 E0 ;Zero the extruded length\nG1 F1000 Z5 ;Lift the nozzle 5mm before homing axes\nG90 ;Absolute positioning\nM82 ;Set extruder to absolute mode too\nG28 X0 Y0 ;First move X/Y to min endstops\nG28 Z0 ;Then move Z to min endstops\nG1 F1000 Z15 ;After homing lift the nozzle 15mm before start printing\n"
+ },
+ "machine_end_gcode":
+ {
+ "default_value": "G91 ;Change to relative positioning mode for filament retraction and nozzle lifting\nG1 F200 E-4;Retract the filament a bit before lifting the nozzle\nG1 F1000 Z5;Lift nozzle 5mm\nG90 ;Change to absolute positioning mode to prepare for part rermoval\nG1 X0 Y400 ;Move the print to max y pos for part rermoval\nM104 S0 ; Turn off hotend\nM106 S0 ; Turn off cooling fan\nM140 S0 ; Turn off bed\nM84 ; Disable motors\n"
+ }
+ }
+}
diff --git a/resources/definitions/anycubic_i3_mega.def.json b/resources/definitions/anycubic_i3_mega.def.json
index a6c1567dc4..cc9832cf09 100644
--- a/resources/definitions/anycubic_i3_mega.def.json
+++ b/resources/definitions/anycubic_i3_mega.def.json
@@ -8,9 +8,8 @@
"author": "TheTobby",
"manufacturer": "Anycubic",
"file_formats": "text/x-gcode",
- "icon": "icon_ultimaker2",
"platform": "anycubic_i3_mega_platform.stl",
- "has_materials": false,
+ "has_materials": true,
"has_machine_quality": true,
"preferred_quality_type": "normal",
"machine_extruder_trains":
@@ -47,7 +46,7 @@
},
"gantry_height":
{
- "default_value": 0
+ "value": "0"
},
"machine_gcode_flavor":
{
@@ -59,7 +58,7 @@
},
"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/bibo2_dual.def.json b/resources/definitions/bibo2_dual.def.json
new file mode 100644
index 0000000000..e86c979260
--- /dev/null
+++ b/resources/definitions/bibo2_dual.def.json
@@ -0,0 +1,92 @@
+{
+ "id": "BIBO2 dual",
+ "version": 2,
+ "name": "BIBO2 dual",
+ "inherits": "fdmprinter",
+ "metadata": {
+ "visible": true,
+ "author": "unknown",
+ "manufacturer": "BIBO",
+ "category": "Other",
+ "file_formats": "text/x-gcode",
+ "has_materials": true,
+ "machine_extruder_trains": {
+ "0": "bibo2_dual_extruder_0",
+ "1": "bibo2_dual_extruder_1"
+ },
+ "first_start_actions": [
+ "MachineSettingsAction"
+ ]
+ },
+ "overrides": {
+ "machine_name": {
+ "default_value": "BIBO2 dual"
+ },
+ "machine_width": {
+ "default_value": 214
+ },
+ "machine_height": {
+ "default_value": 160
+ },
+ "machine_depth": {
+ "default_value": 186
+ },
+ "machine_center_is_zero": {
+ "default_value": true
+ },
+ "machine_heated_bed": {
+ "default_value": true
+ },
+ "machine_nozzle_heat_up_speed": {
+ "default_value": 2
+ },
+ "machine_nozzle_cool_down_speed": {
+ "default_value": 2
+ },
+ "machine_head_with_fans_polygon": {
+ "default_value": [
+ [
+ -68.18,
+ 64.63
+ ],
+ [
+ -68.18,
+ -47.38
+ ],
+ [
+ 35.18,
+ 64.63
+ ],
+ [
+ 35.18,
+ -47.38
+ ]
+ ]
+ },
+ "gantry_height": {
+ "value": "12"
+ },
+ "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\nM107 ;start with the fan off\nG28 X0 Y0 ;move X/Y to min endstops\nG28 Z0 ;move Z to min endstops\nG1 Z2.0 F400 ;move the platform down 15mm\nT0\nG92 E0\nG28\nG1 Y0 F1200 E0\nG92 E0\nM117 BIBO Printing..."
+ },
+ "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"
+ },
+ "machine_extruder_count": {
+ "default_value": 2
+ },
+ "prime_tower_position_x": {
+ "default_value": 50
+ },
+ "prime_tower_position_y": {
+ "default_value": 50
+ }
+ }
+}
+
diff --git a/resources/definitions/bq_hephestos.def.json b/resources/definitions/bq_hephestos.def.json
index 8dc67a8cad..be024cd6fa 100644
--- a/resources/definitions/bq_hephestos.def.json
+++ b/resources/definitions/bq_hephestos.def.json
@@ -12,7 +12,8 @@
"machine_extruder_trains":
{
"0": "bq_hephestos_extruder_0"
- }
+ },
+ "firmware_file": "MarlinHephestos2.hex"
},
"overrides": {
diff --git a/resources/definitions/bq_witbox.def.json b/resources/definitions/bq_witbox.def.json
index 0ae1c5e339..b96da6179c 100644
--- a/resources/definitions/bq_witbox.def.json
+++ b/resources/definitions/bq_witbox.def.json
@@ -12,7 +12,8 @@
"machine_extruder_trains":
{
"0": "bq_witbox_extruder_0"
- }
+ },
+ "firmware_file": "MarlinWitbox.hex"
},
"overrides": {
diff --git a/resources/definitions/builder_premium_large.def.json b/resources/definitions/builder_premium_large.def.json
index 2e0cd4f839..3ceae8d63f 100644
--- a/resources/definitions/builder_premium_large.def.json
+++ b/resources/definitions/builder_premium_large.def.json
@@ -93,7 +93,7 @@
"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 },
+ "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..5f608ba2a8 100644
--- a/resources/definitions/builder_premium_medium.def.json
+++ b/resources/definitions/builder_premium_medium.def.json
@@ -93,7 +93,7 @@
"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 },
+ "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..a19773ec05 100644
--- a/resources/definitions/builder_premium_small.def.json
+++ b/resources/definitions/builder_premium_small.def.json
@@ -92,7 +92,7 @@
"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 },
+ "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..1d83363684 100644
--- a/resources/definitions/cartesio.def.json
+++ b/resources/definitions/cartesio.def.json
@@ -35,7 +35,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 },
diff --git a/resources/definitions/cocoon_create_modelmaker.def.json b/resources/definitions/cocoon_create_modelmaker.def.json
new file mode 100644
index 0000000000..83d1f41a99
--- /dev/null
+++ b/resources/definitions/cocoon_create_modelmaker.def.json
@@ -0,0 +1,96 @@
+{
+ "name": "Cocoon Create ModelMaker",
+ "version": 2,
+ "inherits": "fdmprinter",
+ "metadata": {
+ "visible": true,
+ "author": "Samuel Pinches",
+ "manufacturer": "Cocoon Create",
+ "file_formats": "text/x-gcode",
+ "preferred_quality_type": "fine",
+ "machine_extruder_trains":
+ {
+ "0": "cocoon_create_modelmaker_extruder_0"
+ }
+ },
+ "overrides": {
+ "machine_name": {
+ "default_value": "Cocoon Create ModelMaker"
+ },
+ "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\nG91 ;set to relative positioning\nG1 E-10 F300 ;retract the filament slightly\nG90 ;set to absolute positioning\nG28 X0 Y0 ;move to the XY-axis origin (Home)\nM84 ;turn off stepper motors\n; -- end of END GCODE --"
+ },
+ "machine_width": {
+ "default_value": 120
+ },
+ "machine_height": {
+ "default_value": 100
+ },
+ "machine_depth": {
+ "default_value": 135
+ },
+ "machine_heated_bed": {
+ "default_value": false
+ },
+ "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
+ },
+ "material_print_temperature": {
+ "default_value": 220
+ },
+ "layer_height": {
+ "default_value": 0.10
+ },
+ "layer_height_0": {
+ "default_value": 0.2
+ },
+ "wall_thickness": {
+ "default_value": 1.2
+ },
+ "top_bottom_thickness": {
+ "default_value": 0.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
+ },
+ "retraction_enable": {
+ "default_value": true
+ },
+ "retraction_amount": {
+ "default_value": 7
+ },
+ "retraction_speed": {
+ "default_value": 40
+ }
+ }
+}
diff --git a/resources/definitions/creality_base.def.json b/resources/definitions/creality_base.def.json
new file mode 100644
index 0000000000..47f941e998
--- /dev/null
+++ b/resources/definitions/creality_base.def.json
@@ -0,0 +1,263 @@
+{
+ "name": "Creawsome Base Printer",
+ "version": 2,
+ "inherits": "fdmprinter",
+ "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 positionning\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" },
+
+ "skirt_brim_speed": { "value": "speed_layer_0" },
+
+ "line_width": { "value": "machine_nozzle_size * 1.1"},
+
+ "material_initial_print_temperature": { "value": "material_print_temperature"},
+ "material_final_print_temperature": { "value": "material_print_temperature"},
+ "material_flow": { "value": 100},
+
+ "z_seam_type": { "value": "'back'"},
+ "z_seam_corner": { "value": "'z_seam_corner_none'"},
+
+ "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": "support_enable" },
+ "retraction_hop": { "value": 0.2 },
+ "retraction_combing": { "value": "'off' if retraction_hop_enabled else 'infill'"},
+ "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": "'none' if support_enable else 'skirt'" },
+ "brim_replaces_support": { "value": false},
+ "skirt_gap": { "value": 10.0 },
+ "skirt_line_count": { "value": 4 },
+
+ "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_type": { "value": "'buildplate'"},
+ "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": 10},
+ "minimum_interface_area": { "value": 10}
+
+ },
+ "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,
+ "has_machine_materials": 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"
+ ]
+ }
+}
\ No newline at end of file
diff --git a/resources/definitions/creality_cr-x.def.json b/resources/definitions/creality_cr-x.def.json
new file mode 100644
index 0000000000..0117c4fffe
--- /dev/null
+++ b/resources/definitions/creality_cr-x.def.json
@@ -0,0 +1,51 @@
+{
+ "id": "CR-X",
+ "version": 2,
+ "name": "Creality CR-X",
+ "inherits": "fdmprinter",
+ "metadata": {
+ "visible": true,
+ "author": "SRC",
+ "manufacturer": "Creality3D",
+ "category": "Other",
+ "file_formats": "text/x-gcode",
+ "platform": "cr-x.stl",
+ "has_variants": false,
+ "has_machine_quality": false,
+ "preferred_quality_type": "draft",
+ "machine_extruder_trains": {
+ "0": "cr-x_extruder_0",
+ "1": "cr-x_extruder_1"
+ }
+ },
+
+ "overrides": {
+ "machine_name": { "default_value": "Creality CR-X" },
+ "machine_extruder_count": { "default_value": 2 },
+ "machine_heated_bed": { "default_value": true },
+ "machine_width": { "default_value": 300 },
+ "machine_depth": { "default_value": 300 },
+ "machine_height": { "default_value": 400 },
+ "machine_center_is_zero": { "default_value": false },
+ "retraction_amount": { "default_value": 3 },
+ "retraction_speed": { "default_value": 70},
+ "adhesion_type": { "default_value": "skirt" },
+ "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 },
+ "machine_max_acceleration_e": { "default_value": 5000 },
+ "machine_max_jerk_xy": { "default_value": 5.0 },
+ "machine_max_jerk_z": { "default_value": 0.4 },
+ "machine_max_jerk_e": { "default_value": 5.0 },
+ "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 }
+ }
+}
diff --git a/resources/definitions/creality_cr10.def.json b/resources/definitions/creality_cr10.def.json
index fb63867163..0a08c56cc6 100644
--- a/resources/definitions/creality_cr10.def.json
+++ b/resources/definitions/creality_cr10.def.json
@@ -1,95 +1,32 @@
{
"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_polygon": { "default_value": [
+ [-26, 34],
+ [-26, -32],
+ [22, -32],
+ [22, 34]
]
},
- "layer_height_0": {
- "default_value": 0.2
+ "machine_head_with_fans_polygon": { "default_value": [
+ [-26, 34],
+ [-26, -32],
+ [32, -32],
+ [32, 34]
+ ]
},
- "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_cr10mini.def.json b/resources/definitions/creality_cr10mini.def.json
new file mode 100644
index 0000000000..bdc0d4406e
--- /dev/null
+++ b/resources/definitions/creality_cr10mini.def.json
@@ -0,0 +1,32 @@
+{
+ "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_polygon": { "default_value": [
+ [-26, 34],
+ [-26, -32],
+ [22, -32],
+ [22, 34]
+ ]
+ },
+ "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..593a526fc3 100644
--- a/resources/definitions/creality_cr10s4.def.json
+++ b/resources/definitions/creality_cr10s4.def.json
@@ -1,26 +1,32 @@
{
- "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_polygon": { "default_value": [
+ [-26, 34],
+ [-26, -32],
+ [22, -32],
+ [22, 34]
+ ]
},
- "machine_height": {
- "default_value": 400
+ "machine_head_with_fans_polygon": { "default_value": [
+ [-26, 34],
+ [-26, -32],
+ [32, -32],
+ [32, 34]
+ ]
},
- "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..91469deb7f 100644
--- a/resources/definitions/creality_cr10s5.def.json
+++ b/resources/definitions/creality_cr10s5.def.json
@@ -1,26 +1,32 @@
{
- "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_polygon": { "default_value": [
+ [-26, 34],
+ [-26, -32],
+ [22, -32],
+ [22, 34]
+ ]
},
- "machine_height": {
- "default_value": 500
+ "machine_head_with_fans_polygon": { "default_value": [
+ [-26, 34],
+ [-26, -32],
+ [32, -32],
+ [32, 34]
+ ]
},
- "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..86897e711a
--- /dev/null
+++ b/resources/definitions/creality_cr10spro.def.json
@@ -0,0 +1,31 @@
+{
+ "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_polygon": { "default_value": [
+ [-44, 34],
+ [-44, -34],
+ [18, -34],
+ [18, 34]
+ ]
+ },
+ "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..af027f2452
--- /dev/null
+++ b/resources/definitions/creality_cr20.def.json
@@ -0,0 +1,32 @@
+{
+ "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_polygon": { "default_value": [
+ [-26, 34],
+ [-26, -32],
+ [22, -32],
+ [22, 34]
+ ]
+ },
+ "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..55b2e88478
--- /dev/null
+++ b/resources/definitions/creality_ender2.def.json
@@ -0,0 +1,33 @@
+{
+ "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_polygon": { "default_value": [
+ [-26, 34],
+ [-26, -32],
+ [22, -32],
+ [22, 34]
+ ]
+ },
+ "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 64e01504dd..e00e6eab63
--- a/resources/definitions/creality_ender3.def.json
+++ b/resources/definitions/creality_ender3.def.json
@@ -1,90 +1,32 @@
{
"name": "Creality Ender-3",
"version": 2,
- "inherits": "fdmprinter",
- "metadata": {
- "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"
- }
- },
+ "inherits": "creality_base",
"overrides": {
- "machine_name": {
- "default_value": "Creality Ender-3"
- },
- "machine_width": {
- "default_value": 220
- },
- "machine_height": {
- "default_value": 250
- },
- "machine_depth": {
- "default_value": 220
- },
- "machine_heated_bed": {
- "default_value": true
- },
- "gantry_height": {
- "default_value": 30
- },
- "machine_head_polygon": {
- "default_value": [
- [-30, 34],
- [-30, -32],
- [30, -32],
- [30, 34]
+ "machine_name": { "default_value": "Creality Ender-3" },
+ "machine_width": { "default_value": 220 },
+ "machine_depth": { "default_value": 220 },
+ "machine_height": { "default_value": 250 },
+ "machine_head_polygon": { "default_value": [
+ [-26, 34],
+ [-26, -32],
+ [22, -32],
+ [22, 34]
]
},
- "acceleration_enabled": {
- "default_value": true
+ "machine_head_with_fans_polygon": { "default_value": [
+ [-26, 34],
+ [-26, -32],
+ [32, -32],
+ [32, 34]
+ ]
},
- "acceleration_print": {
- "default_value": 500
- },
- "acceleration_travel": {
- "default_value": 500
- },
- "jerk_enabled": {
- "default_value": true
- },
- "jerk_travel": {
- "default_value": 20
- },
- "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\nM104 S{material_print_temperature_layer_0} ; Set Extruder temperature\nM140 S{material_bed_temperature_layer_0} ; Set Heat Bed temperature\nM190 S{material_bed_temperature_layer_0} ; Wait for Heat Bed temperature\nM109 S{material_print_temperature_layer_0} ; Wait for Extruder temperature\nG28 ; Home all axes\nG92 E0 ; Reset Extruder\nG1 Z5.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 Z5.0 F3000 ; Move Z Axis up little to prevent scratching of Heat Bed"
- },
- "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 Z10 ; Move Z Axis up 10 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\nM104 S0 ; Turn off Extruder temperature\nM140 S0 ; Turn off Heat Bed\nM106 S0 ; Turn off Cooling Fan\nM107 ; Turn off Fan\nM84 ; Disable stepper motors"
- }
+
+ "gantry_height": { "value": 25 }
+
+ },
+ "metadata": {
+ "quality_definition": "creality_base",
+ "visible": true
}
-}
+}
\ No newline at end of file
diff --git a/resources/definitions/creality_ender4.def.json b/resources/definitions/creality_ender4.def.json
new file mode 100644
index 0000000000..6962be558e
--- /dev/null
+++ b/resources/definitions/creality_ender4.def.json
@@ -0,0 +1,34 @@
+{
+ "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_polygon": { "default_value": [
+ [-26, 34],
+ [-26, -32],
+ [22, -32],
+ [22, 34]
+ ]
+ },
+ "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..d95f4a1467
--- /dev/null
+++ b/resources/definitions/creality_ender5.def.json
@@ -0,0 +1,35 @@
+{
+ "name": "Creality Ender-5",
+ "version": 2,
+ "inherits": "creality_base",
+ "overrides": {
+ "machine_name": { "default_value": "Creality Ender-5" },
+ "machine_end_gcode": { "default_value": "G91 ;Relative positionning\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_polygon": { "default_value": [
+ [-26, 34],
+ [-26, -32],
+ [22, -32],
+ [22, 34]
+ ]
+ },
+ "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
new file mode 100644
index 0000000000..1491089e24
--- /dev/null
+++ b/resources/definitions/creatable_d3.def.json
@@ -0,0 +1,45 @@
+{
+ "version": 2,
+ "name": "Creatable D3",
+ "inherits": "fdmprinter",
+ "metadata": {
+ "visible": true,
+ "author": "Creatable Labs",
+ "manufacturer": "Ateam Ventures Co. Ltd.",
+ "file_formats": "text/x-gcode",
+ "icon": "icon_ultimaker.png",
+ "platform": "rostock_platform.stl",
+ "machine_extruder_trains":
+ {
+ "0": "creatable_d3_extruder_0"
+ }
+ },
+
+ "overrides": {
+ "machine_name": { "default_value": "Creatable D3" },
+ "machine_center_is_zero": { "default_value": true },
+ "machine_gcode_flavor": { "default_value": "RepRap (RepRap)" },
+ "machine_width": { "default_value": 250 },
+ "machine_height": { "default_value": 200 },
+ "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": {"value": "43"},
+ "layer_height": { "default_value": 0.1 },
+ "relative_extrusion": { "default_value": false },
+ "retraction_combing": { "default_value": "off" },
+ "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"
+ },
+ "machine_end_gcode": {
+ "default_value": "M400\nG28\nM104 S0\nM140 S0\nM107\nG92 E0\nG1 E-32 F300\nM84\nG90"
+ }
+ }
+}
diff --git a/resources/definitions/cubicon_3dp_110f.def.json b/resources/definitions/cubicon_3dp_110f.def.json
new file mode 100644
index 0000000000..168b57cd66
--- /dev/null
+++ b/resources/definitions/cubicon_3dp_110f.def.json
@@ -0,0 +1,41 @@
+{
+ "id": "3DP-110F",
+ "version": 2,
+ "name": "Cubicon Single",
+ "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_3dp_110f_extruder_0"
+ },
+ "platform_offset": [
+ 0,
+ -32.05,
+ -20
+ ]
+ },
+ "overrides": {
+ "machine_name": {
+ "default_value": "Cubicon Single"
+ },
+ "machine_start_gcode": {
+ "default_value": "M911 3DP-110F\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": 240
+ },
+ "machine_depth": {
+ "default_value": 190
+ },
+ "machine_height": {
+ "default_value": 200
+ },
+ "material_bed_temp_wait": {
+ "default_value": true
+ }
+ }
+}
\ No newline at end of file
diff --git a/resources/definitions/cubicon_3dp_210f.def.json b/resources/definitions/cubicon_3dp_210f.def.json
new file mode 100644
index 0000000000..cc99899f92
--- /dev/null
+++ b/resources/definitions/cubicon_3dp_210f.def.json
@@ -0,0 +1,41 @@
+{
+ "id": "3DP-210F",
+ "version": 2,
+ "name": "Cubicon Style",
+ "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_3dp_210f_extruder_0"
+ },
+ "platform_offset": [
+ 0,
+ -18.8,
+ 0
+ ]
+ },
+ "overrides": {
+ "machine_name": {
+ "default_value": "Cubicon Style"
+ },
+ "machine_start_gcode": {
+ "default_value": "M911 3DP-210F\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
+ }
+ }
+}
\ No newline at end of file
diff --git a/resources/definitions/cubicon_3dp_310f.def.json b/resources/definitions/cubicon_3dp_310f.def.json
new file mode 100644
index 0000000000..90d0e3f25c
--- /dev/null
+++ b/resources/definitions/cubicon_3dp_310f.def.json
@@ -0,0 +1,41 @@
+{
+ "id": "3DP-310F",
+ "version": 2,
+ "name": "Cubicon Single Plus",
+ "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_3dp_310f_extruder_0"
+ },
+ "platform_offset": [
+ 0,
+ -32.05,
+ -20
+ ]
+ },
+ "overrides": {
+ "machine_name": {
+ "default_value": "Cubicon Single Plus"
+ },
+ "machine_start_gcode": {
+ "default_value": "M911 3DP-310F\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": 240
+ },
+ "machine_depth": {
+ "default_value": 190
+ },
+ "machine_height": {
+ "default_value": 200
+ },
+ "material_bed_temp_wait": {
+ "default_value": true
+ }
+ }
+}
\ No newline at end of file
diff --git a/resources/definitions/cubicon_common.def.json b/resources/definitions/cubicon_common.def.json
new file mode 100644
index 0000000000..ae085c7552
--- /dev/null
+++ b/resources/definitions/cubicon_common.def.json
@@ -0,0 +1,99 @@
+{
+ "version": 2,
+ "name": "Cubicon Common",
+ "inherits": "fdmprinter",
+ "metadata": {
+ "author": "Cubicon R&D Center",
+ "manufacturer": "Cubicon",
+ "visible": false
+ },
+ "overrides": {
+ "machine_start_gcode": {
+ "default_value": "M201 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_end_gcode": {
+ "default_value": "M104 S0\nM140 S0\nM904\nM117 Print completed! \nM84"
+ },
+ "machine_gcode_flavor": {
+ "default_value": "Repetier"
+ },
+ "machine_heated_bed": {
+ "default_value": true
+ },
+ "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
+ }
+ }
+}
\ No newline at end of file
diff --git a/resources/definitions/dagoma_discoeasy200.def.json b/resources/definitions/dagoma_discoeasy200.def.json
index 89d94ff6b7..17e285a422 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"
diff --git a/resources/definitions/dagoma_magis.def.json b/resources/definitions/dagoma_magis.def.json
index 75e6e449cd..9d2f7170c6 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"
diff --git a/resources/definitions/dagoma_neva.def.json b/resources/definitions/dagoma_neva.def.json
index 67c8795678..ea6046b613 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"
diff --git a/resources/definitions/delta_go.def.json b/resources/definitions/delta_go.def.json
index 968bf281a5..cd1fb180c2 100644
--- a/resources/definitions/delta_go.def.json
+++ b/resources/definitions/delta_go.def.json
@@ -8,7 +8,6 @@
"manufacturer": "Deltaprintr",
"file_formats": "text/x-gcode",
"platform_offset": [0, 0, 0],
- "platform": "",
"machine_extruder_trains":
{
"0": "delta_go_extruder_0"
diff --git a/resources/definitions/deltabot.def.json b/resources/definitions/deltabot.def.json
index 95435f659d..613b61d32c 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":
diff --git a/resources/definitions/deltacomb.def.json b/resources/definitions/deltacomb.def.json
old mode 100644
new mode 100755
index a4b2d47a7b..026dfca9ed
--- a/resources/definitions/deltacomb.def.json
+++ b/resources/definitions/deltacomb.def.json
@@ -1,60 +1,68 @@
{
- "version": 2,
- "name": "Deltacomb 3D",
- "inherits": "fdmprinter",
+ "version": 2,
+ "name": "Deltacomb 3D",
+ "inherits": "fdmprinter",
+
"metadata": {
- "author": "Gabriele Rossetti",
- "visible": true,
- "manufacturer": "Deltacomb 3D",
- "category": "Other",
- "file_formats": "text/x-gcode",
- "icon": "icon_ultimaker2",
- "platform": "deltacomb.stl",
- "has_machine_quality": true,
- "machine_extruder_trains":
- {
- "0": "deltacomb_extruder_0"
- }
+ "author": "Gabriele Rossetti",
+ "visible": true,
+ "manufacturer": "Deltacomb 3D",
+ "category": "Other",
+ "file_formats": "text/x-gcode",
+ "icon": "icon_ultimaker2",
+ "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",
+ "preferred_material": "generic_pla",
+ "preferred_quality_type": "normal",
+ "machine_extruder_trains": { "0": "deltacomb_extruder_0", "1": "deltacomb_extruder_1" }
},
"overrides": {
- "machine_heated_bed": { "default_value": true },
- "machine_width": { "default_value": 190 },
- "machine_height": { "default_value": 250 },
- "machine_depth": { "default_value": 190 },
- "machine_center_is_zero": { "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 ;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": "elliptic" },
- "retraction_hop_enabled": { "default_value": true },
- "retraction_amount" : { "default_value": 3.5 },
- "retraction_speed" : { "default_value": 50 },
- "material_final_print_temperature": { "value": "material_print_temperature - 5" },
- "material_initial_print_temperature": { "value": "material_print_temperature" },
- "material_print_temperature_layer_0": { "value": "material_print_temperature + 5" },
- "travel_avoid_distance": { "default_value": 1, "value": "1" },
- "speed_print" : { "default_value": 70 },
- "speed_travel": { "value": "150.0" },
- "speed_infill": { "value": "round(speed_print * 1.05, 0)" },
- "speed_topbottom": { "value": "round(speed_print * 0.95, 0)" },
- "speed_wall": { "value": "speed_print" },
- "speed_wall_0": { "value": "20" },
- "speed_wall_x": { "value": "speed_wall" },
- "speed_layer_0": { "value": "min(round(speed_print * 0.75, 0), 45.0)" },
- "speed_travel_layer_0": { "value": "round(speed_travel * 0.7, 0)" },
- "skirt_brim_speed": { "value": "speed_layer_0" },
- "skirt_line_count": { "default_value": 3 },
- "skirt_brim_minimal_length": { "default_value": 150 },
- "infill_sparse_density": { "default_value": 90 },
- "gradual_infill_steps": { "default_value": 2 },
- "infill_before_walls" : { "default_value": false },
- "top_bottom_thickness": { "default_value": 0.6 },
- "support_z_distance": { "value": "layer_height * 2" },
- "support_bottom_distance": { "value": "layer_height" },
- "support_use_towers" : { "default_value": false },
- "jerk_wall_0" : { "value": "30" },
- "jerk_travel" : { "default_value": 20 },
- "acceleration_travel" : { "value": 10000 }
+ "machine_extruder_count": { "default_value": 1 },
+ "machine_heated_bed": { "default_value": true },
+ "machine_width": { "default_value": 190 },
+ "machine_height": { "default_value": 250 },
+ "machine_depth": { "default_value": 190 },
+ "machine_center_is_zero": { "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 ;Home all axes (max endstops)\nG1 Z15.0 F9000 ;move the platform down 15mm\nG92 E0 ;zero the extruded length\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": "elliptic" },
+ "retraction_hop_enabled": { "default_value": true },
+ "retraction_hop": { "default_value": 1 },
+ "retraction_amount" : { "default_value": 3.5 },
+ "retraction_speed" : { "default_value": 30 },
+ "retraction_combing" : { "default_value": "noskin" },
+ "travel_avoid_distance": { "default_value": 1, "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)" },
+ "speed_wall": { "value": "speed_print" },
+ "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_layer_0": { "value": "round(speed_travel * 0.7, 0)" },
+ "skirt_brim_speed": { "value": "speed_layer_0" },
+ "skirt_line_count": { "default_value": 3 },
+ "skirt_brim_minimal_length": { "default_value": 150 },
+ "infill_sparse_density": { "default_value": 30 },
+ "infill_pattern": { "value": "'cubic'" },
+ "infill_before_walls" : { "default_value": false },
+ "top_bottom_thickness": { "default_value": 0.8 },
+ "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" },
+ "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..0e2742f484 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":
{
diff --git a/resources/definitions/erzay3d.def.json b/resources/definitions/erzay3d.def.json
new file mode 100644
index 0000000000..0a6d676bea
--- /dev/null
+++ b/resources/definitions/erzay3d.def.json
@@ -0,0 +1,121 @@
+{
+ "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 },
+ "roofing_pattern": { "default_value": "concentric" },
+
+ "infill_sparse_density": { "default_value": 20 },
+ "infill_line_distance": { "default_value": 4 },
+
+ "default_material_print_temperature": { "default_value": 220 },
+ "material_print_temperature": { "default_value": 220 },
+ "material_print_temperature_layer_0": { "default_value": 220 },
+ "material_initial_print_temperature": { "default_value": 220 },
+ "material_final_print_temperature": { "default_value": 220 },
+ "retraction_amount": { "default_value": 6.5 },
+
+ "speed_print": { "default_value": 40 },
+ "speed_infill": { "default_value": 60 },
+ "speed_wall": { "default_value": 20 },
+ "speed_wall_0": { "default_value": 20 },
+ "speed_wall_x": { "default_value": 40 },
+ "speed_roofing": { "default_value": 20 },
+ "speed_topbottom": { "default_value": 20 },
+ "speed_support": { "default_value": 40 },
+ "speed_support_infill": { "default_value": 40 },
+ "speed_support_interface": { "default_value": 25 },
+ "speed_support_roof": { "default_value": 25 },
+ "speed_support_bottom": { "default_value": 25 },
+ "speed_prime_tower": { "default_value": 40 },
+ "speed_travel": { "default_value": 100 },
+ "speed_layer_0": { "default_value": 20 },
+ "speed_print_layer_0": { "default_value": 20 },
+ "speed_travel_layer_0": { "default_value": 80 },
+ "skirt_brim_speed": { "default_value": 20 },
+ "speed_equalize_flow_enabled": { "default_value": true },
+ "speed_equalize_flow_max": { "default_value": 100 },
+
+ "acceleration_print": { "default_value": 1000 },
+ "acceleration_infill": { "default_value": 3000 },
+ "acceleration_wall": { "default_value": 1000 },
+ "acceleration_wall_0": { "default_value": 1000 },
+ "acceleration_wall_x": { "default_value": 1000 },
+ "acceleration_roofing": { "default_value": 1000 },
+ "acceleration_topbottom": { "default_value": 1000 },
+ "acceleration_support": { "default_value": 1000 },
+ "acceleration_support_infill": { "default_value": 1000 },
+ "acceleration_support_interface": { "default_value": 1000 },
+ "acceleration_support_roof": { "default_value": 1000 },
+ "acceleration_support_bottom": { "default_value": 1000 },
+ "acceleration_prime_tower": { "default_value": 1000 },
+ "acceleration_travel": { "default_value": 1500 },
+ "acceleration_layer_0": { "default_value": 1000 },
+ "acceleration_print_layer_0": { "default_value": 1000 },
+ "acceleration_travel_layer_0": { "default_value": 1000 },
+ "acceleration_skirt_brim": { "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 1908e42913..959a5bdaec 100644
--- a/resources/definitions/fabtotum.def.json
+++ b/resources/definitions/fabtotum.def.json
@@ -9,7 +9,6 @@
"category": "Other",
"file_formats": "text/x-gcode",
"platform": "fabtotum_platform.stl",
- "icon": "fabtotum_platform.png",
"has_machine_quality": true,
"has_variants": true,
"variants_name": "Head",
@@ -29,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 },
diff --git a/resources/definitions/fdmextruder.def.json b/resources/definitions/fdmextruder.def.json
index 19c9e92d18..6554b2aa0f 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": 9,
"visible": false,
"position": "0"
},
@@ -78,7 +78,7 @@
"machine_extruder_start_code":
{
"label": "Extruder Start G-Code",
- "description": "Start g-code to execute whenever turning the extruder on.",
+ "description": "Start g-code to execute when switching to this extruder.",
"type": "str",
"default_value": "",
"settable_per_mesh": false,
@@ -124,7 +124,7 @@
"machine_extruder_end_code":
{
"label": "Extruder End G-Code",
- "description": "End g-code to execute whenever turning the extruder off.",
+ "description": "End g-code to execute when switching away from this extruder.",
"type": "str",
"default_value": "",
"settable_per_mesh": false,
@@ -189,7 +189,7 @@
"settable_per_mesh": false,
"settable_per_extruder": true,
"settable_per_meshgroup": false,
- "setttable_globally": false
+ "settable_globally": false
}
}
},
diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json
index 1d59feb4a6..5a06d36f78 100644
--- a/resources/definitions/fdmprinter.def.json
+++ b/resources/definitions/fdmprinter.def.json
@@ -7,7 +7,7 @@
"author": "Ultimaker",
"category": "Other",
"manufacturer": "Unknown",
- "setting_version": 1,
+ "setting_version": 9,
"file_formats": "text/x-gcode;application/x-stl-ascii;application/x-stl-binary;application/x-wavefront-obj;application/x3g",
"visible": false,
"has_materials": true,
@@ -17,7 +17,8 @@
{
"0": "fdmextruder"
},
- "supports_usb_connection": true
+ "supports_usb_connection": true,
+ "supports_network_connection": false
},
"settings":
{
@@ -227,7 +228,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 +241,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 +253,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 +264,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 +277,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 +311,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 +322,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 +344,7 @@
},
"machine_gcode_flavor":
{
- "label": "G-code flavour",
+ "label": "G-code Flavor",
"description": "The type of g-code to be generated.",
"type": "enum",
"options":
@@ -376,7 +377,7 @@
},
"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":
@@ -400,7 +401,7 @@
},
"machine_head_polygon":
{
- "label": "Machine head polygon",
+ "label": "Machine Head Polygon",
"description": "A 2D silhouette of the print head (fan caps excluded).",
"type": "polygon",
"default_value":
@@ -428,7 +429,7 @@
},
"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 +457,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 +489,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 +524,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 +535,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 +546,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
@@ -876,7 +878,7 @@
"default_value": 0.4,
"type": "float",
"value": "line_width",
- "enabled": "resolveOrValue('adhesion_type') == 'skirt' or resolveOrValue('adhesion_type') == 'brim'",
+ "enabled": "resolveOrValue('adhesion_type') == 'skirt' or resolveOrValue('adhesion_type') == 'brim' or resolveOrValue('prime_tower_brim_enable')",
"settable_per_mesh": false,
"settable_per_extruder": true
},
@@ -890,7 +892,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 +908,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 +925,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 +941,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 +963,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
}
}
},
@@ -1217,11 +1219,11 @@
"connect_skin_polygons":
{
"label": "Connect Top/Bottom Polygons",
- "description": "Connect top/bottom skin paths where they run next to each other. For the concentric pattern enabling this setting greatly reduces the travel time, but because the connections can happend midway over infill this feature can reduce the top surface quality.",
+ "description": "Connect top/bottom skin paths where they run next to each other. For the concentric pattern enabling this setting greatly reduces the travel time, but because the connections can happen midway over infill this feature can reduce the top surface quality.",
"type": "bool",
"default_value": false,
"enabled": "(top_layers > 0 or bottom_layers > 0) and top_bottom_pattern == 'concentric'",
- "limit_to_extruder": "infill_extruder_nr",
+ "limit_to_extruder": "top_bottom_extruder_nr",
"settable_per_mesh": true
},
"skin_angles":
@@ -1315,8 +1317,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 +1326,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":
{
@@ -1426,14 +1426,15 @@
"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 +1454,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 +1477,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 +1591,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
+ }
+ }
}
}
},
@@ -1789,36 +1820,6 @@
}
}
},
- "skin_overlap":
- {
- "label": "Skin Overlap Percentage",
- "description": "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.",
- "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": "The amount of overlap between the skin and the walls. A slight overlap allows the walls to connect firmly to the skin.",
- "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",
@@ -1924,7 +1925,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 +1939,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 +1952,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 +1967,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 +1981,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 +1994,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",
@@ -2056,6 +2057,21 @@
"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": true,
+ "settable_per_mesh": false,
+ "settable_per_extruder": false
+ },
"material_print_temperature":
{
"label": "Printing Temperature",
@@ -2218,6 +2234,107 @@
"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_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",
@@ -2229,7 +2346,195 @@
"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",
+ "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":
{
@@ -2237,7 +2542,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",
@@ -2382,10 +2686,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
},
@@ -2406,7 +2710,7 @@
"switch_extruder_retraction_amount":
{
"label": "Nozzle Switch Retraction Distance",
- "description": "The amount of retraction: Set at 0 for no retraction at all. This should generally be the same as the length of the heat zone.",
+ "description": "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.",
"type": "float",
"unit": "mm",
"enabled": "retraction_enable",
@@ -2466,6 +2770,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
}
}
},
@@ -2590,7 +2907,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,
@@ -2607,7 +2924,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
@@ -2622,7 +2939,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,
@@ -2639,7 +2956,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,
@@ -2655,7 +2972,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,
@@ -2750,21 +3067,21 @@
"maximum_value": "math.sqrt(machine_max_feedrate_x ** 2 + machine_max_feedrate_y ** 2)",
"maximum_value_warning": "300",
"value": "speed_layer_0",
- "enabled": "resolveOrValue('adhesion_type') == 'skirt' or resolveOrValue('adhesion_type') == 'brim'",
+ "enabled": "resolveOrValue('adhesion_type') == 'skirt' or resolveOrValue('adhesion_type') == 'brim' or resolveOrValue('draft_shield_enabled') or resolveOrValue('ooze_shield_enabled')",
"settable_per_mesh": false,
"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
},
@@ -2901,7 +3218,6 @@
"default_value": 3000,
"value": "acceleration_topbottom",
"enabled": "resolveOrValue('acceleration_enabled') and roofing_layer_count > 0 and top_layers > 0",
- "enabled": "top_layers > 0 or bottom_layers > 0",
"limit_to_extruder": "roofing_extruder_nr",
"settable_per_mesh": true
},
@@ -2931,7 +3247,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,
@@ -2948,7 +3264,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
@@ -2964,7 +3280,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,
@@ -2981,7 +3297,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
@@ -2997,7 +3313,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
@@ -3093,7 +3409,7 @@
"minimum_value": "0.1",
"minimum_value_warning": "100",
"maximum_value_warning": "10000",
- "enabled": "resolveOrValue('acceleration_enabled')",
+ "enabled": "resolveOrValue('acceleration_enabled') and (resolveOrValue('adhesion_type') == 'skirt' or resolveOrValue('adhesion_type') == 'brim' or resolveOrValue('draft_shield_enabled') or resolveOrValue('ooze_shield_enabled'))",
"settable_per_mesh": false,
"limit_to_extruder": "adhesion_extruder_nr"
},
@@ -3216,7 +3532,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",
@@ -3232,7 +3548,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
@@ -3247,7 +3563,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,
@@ -3263,7 +3579,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
@@ -3278,7 +3594,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
@@ -3368,7 +3684,7 @@
"minimum_value": "0",
"maximum_value_warning": "50",
"value": "jerk_layer_0",
- "enabled": "resolveOrValue('jerk_enabled')",
+ "enabled": "resolveOrValue('jerk_enabled') and (resolveOrValue('adhesion_type') == 'skirt' or resolveOrValue('adhesion_type') == 'brim' or resolveOrValue('draft_shield_enabled') or resolveOrValue('ooze_shield_enabled'))",
"settable_per_mesh": false,
"limit_to_extruder": "adhesion_extruder_nr"
}
@@ -3385,7 +3701,7 @@
"retraction_combing":
{
"label": "Combing Mode",
- "description": "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 and also to only comb within the infill. Note that the 'Within Infill' option behaves exactly like the 'Not in Skin' option in earlier Cura releases.",
+ "description": "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.",
"type": "enum",
"options":
{
@@ -3395,7 +3711,7 @@
"infill": "Within Infill"
},
"default_value": "all",
- "resolve": "'noskin' if 'noskin' in extruderValues('retraction_combing') else ('all' if 'all' in extruderValues('retraction_combing') else 'off')",
+ "resolve": "'noskin' if 'noskin' in extruderValues('retraction_combing') else ('infill' if 'infill' in extruderValues('retraction_combing') else ('all' if 'all' in extruderValues('retraction_combing') else 'off'))",
"settable_per_mesh": false,
"settable_per_extruder": false
},
@@ -3456,17 +3772,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",
@@ -3529,6 +3834,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",
+ "settable_per_mesh": false,
+ "settable_per_extruder": true
}
}
},
@@ -3811,7 +4130,8 @@
"triangles": "Triangles",
"concentric": "Concentric",
"zigzag": "Zig Zag",
- "cross": "Cross"
+ "cross": "Cross",
+ "gyroid": "Gyroid"
},
"default_value": "zigzag",
"enabled": "support_enable or support_tree_enable",
@@ -3840,8 +4160,8 @@
"description": "Connect the ends of the support lines together. Enabling this setting can make your support more sturdy and reduce underextrusion, but it will cost more material.",
"type": "bool",
"default_value": false,
- "value": "support_pattern == 'cross'",
- "enabled": "support_pattern == 'grid' or support_pattern == 'triangles' or support_pattern == 'cross'",
+ "value": "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
@@ -3911,10 +4231,53 @@
"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 and support_pattern != 'concentric' and support_infill_rate > 0",
+ "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
},
+ "support_brim_enable":
+ {
+ "label": "Enable Support Brim",
+ "description": "Generate a brim within the support infill regions of the first layer. This brim is printed underneath the support, not around it. Enabling this setting increases the adhesion of support to the build plate.",
+ "type": "bool",
+ "default_value": false,
+ "enabled": "support_enable or support_tree_enable",
+ "limit_to_extruder": "support_infill_extruder_nr",
+ "settable_per_mesh": false,
+ "settable_per_extruder": true
+ },
+ "support_brim_width":
+ {
+ "label": "Support Brim Width",
+ "description": "The width of the brim to print underneath the support. A larger brim enhances adhesion to the build plate, at the cost of some extra material.",
+ "type": "float",
+ "unit": "mm",
+ "default_value": 8.0,
+ "minimum_value": "0.0",
+ "maximum_value_warning": "50.0",
+ "enabled": "support_enable or support_tree_enable",
+ "settable_per_mesh": false,
+ "settable_per_extruder": true,
+ "limit_to_extruder": "support_infill_extruder_nr",
+ "children":
+ {
+ "support_brim_line_count":
+ {
+ "label": "Support Brim Line Count",
+ "description": "The number of lines used for the support brim. More brim lines enhance adhesion to the build plate, at the cost of some extra material.",
+ "type": "int",
+ "default_value": 20,
+ "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 or support_tree_enable",
+ "settable_per_mesh": false,
+ "settable_per_extruder": true,
+ "limit_to_extruder": "support_infill_extruder_nr"
+ }
+ }
+ },
"support_z_distance":
{
"label": "Support Z Distance",
@@ -4030,7 +4393,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,
@@ -4046,7 +4409,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",
@@ -4094,6 +4457,18 @@
"limit_to_extruder": "support_infill_extruder_nr",
"settable_per_mesh": false
},
+ "minimum_support_area":
+ {
+ "label": "Minimum Support Area",
+ "description": "Minimum area size for support polygons. Polygons which have an area smaller than this value will not be generated.",
+ "unit": "mm²",
+ "type": "float",
+ "default_value": 0.0,
+ "minimum_value": "0",
+ "enabled": "support_enable",
+ "limit_to_extruder": "support_infill_extruder_nr",
+ "settable_per_mesh": true
+ },
"support_interface_enable":
{
"label": "Enable Support Interface",
@@ -4185,7 +4560,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":
@@ -4333,12 +4708,101 @@
}
}
},
- "support_interface_angles":
+ "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.",
+ "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 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.",
+ "unit": "mm²",
+ "type": "float",
+ "default_value": 1.0,
+ "value": "extruderValue(support_roof_extruder_nr, 'minimum_interface_area')",
+ "minimum_value": "0",
+ "minimum_value_warning": "minimum_support_area",
+ "limit_to_extruder": "support_roof_extruder_nr",
+ "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.",
+ "unit": "mm²",
+ "type": "float",
+ "default_value": 1.0,
+ "value": "extruderValue(support_bottom_extruder_nr, 'minimum_interface_area')",
+ "minimum_value": "0",
+ "minimum_value_warning": "minimum_support_area",
+ "limit_to_extruder": "support_bottom_extruder_nr",
+ "enabled": "support_bottom_enable and (support_enable or support_tree_enable)",
+ "settable_per_mesh": true
+ }
+ }
+ },
+ "support_interface_offset":
+ {
+ "label": "Support Interface Horizontal Expansion",
+ "description": "Amount of offset applied to the support interface polygons.",
+ "unit": "mm",
+ "type": "float",
+ "default_value": 0.0,
+ "maximum_value": "extruderValue(support_extruder_nr, 'support_offset')",
+ "limit_to_extruder": "support_interface_extruder_nr",
+ "enabled": "support_interface_enable and (support_enable or support_tree_enable)",
+ "settable_per_mesh": false,
+ "settable_per_extruder": true,
+ "children":
+ {
+ "support_roof_offset":
+ {
+ "label": "Support Roof Horizontal Expansion",
+ "description": "Amount of offset applied to the roofs of the support.",
+ "unit": "mm",
+ "type": "float",
+ "default_value": 0.0,
+ "value": "extruderValue(support_roof_extruder_nr, 'support_interface_offset')",
+ "maximum_value": "extruderValue(support_extruder_nr, 'support_offset')",
+ "limit_to_extruder": "support_roof_extruder_nr",
+ "enabled": "support_roof_enable and (support_enable or support_tree_enable)",
+ "settable_per_mesh": false,
+ "settable_per_extruder": true
+ },
+ "support_bottom_offset":
+ {
+ "label": "Support Floor Horizontal Expansion",
+ "description": "Amount of offset applied to the floors of the support.",
+ "unit": "mm",
+ "type": "float",
+ "default_value": 0.0,
+ "value": "extruderValue(support_bottom_extruder_nr, 'support_interface_offset')",
+ "maximum_value": "extruderValue(support_extruder_nr, 'support_offset')",
+ "limit_to_extruder": "support_bottom_extruder_nr",
+ "enabled": "support_bottom_enable and (support_enable or support_tree_enable)",
+ "settable_per_mesh": false,
+ "settable_per_extruder": true
+ }
+ }
+ },
+ "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).",
+ "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_interface_enable and support_interface_pattern != 'concentric'",
"settable_per_mesh": false,
"settable_per_extruder": true,
@@ -4347,9 +4811,10 @@
"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).",
+ "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_roof_extruder_nr",
"enabled": "support_roof_enable and support_roof_pattern != 'concentric'",
"settable_per_mesh": false,
"settable_per_extruder": true
@@ -4357,9 +4822,10 @@
"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).",
+ "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_bottom_extruder_nr",
"enabled": "support_bottom_enable and support_bottom_pattern != 'concentric'",
"settable_per_mesh": false,
"settable_per_extruder": true
@@ -4372,7 +4838,7 @@
"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":
@@ -4384,7 +4850,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":
@@ -4411,10 +4877,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,
@@ -4466,11 +4932,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": true,
+ "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":
{
@@ -4522,7 +4988,7 @@
"type": "extruder",
"default_value": "0",
"value": "defaultExtruderPosition()",
- "enabled": "extruders_enabled_count > 1 and resolveOrValue('adhesion_type') != 'none'",
+ "enabled": "extruders_enabled_count > 1 and (resolveOrValue('adhesion_type') != 'none' or resolveOrValue('prime_tower_brim_enable'))",
"settable_per_mesh": false,
"settable_per_extruder": false
},
@@ -4563,7 +5029,7 @@
"minimum_value": "0",
"minimum_value_warning": "25",
"maximum_value_warning": "2500",
- "enabled": "resolveOrValue('adhesion_type') == 'skirt' or resolveOrValue('adhesion_type') == 'brim'",
+ "enabled": "resolveOrValue('adhesion_type') == 'skirt' or resolveOrValue('adhesion_type') == 'brim' or resolveOrValue('prime_tower_brim_enable')",
"settable_per_mesh": false,
"settable_per_extruder": true
},
@@ -4576,7 +5042,8 @@
"default_value": 8.0,
"minimum_value": "0.0",
"maximum_value_warning": "50.0",
- "enabled": "resolveOrValue('adhesion_type') == 'brim'",
+ "maximum_value": "0.5 * min(machine_width, machine_depth)",
+ "enabled": "resolveOrValue('adhesion_type') == 'brim' or resolveOrValue('prime_tower_brim_enable')",
"settable_per_mesh": false,
"settable_per_extruder": true,
"limit_to_extruder": "adhesion_extruder_nr",
@@ -4590,14 +5057,26 @@
"default_value": 20,
"minimum_value": "0",
"maximum_value_warning": "50 / skirt_brim_line_width",
+ "maximum_value": "0.5 * min(machine_width, machine_depth) / skirt_brim_line_width",
"value": "math.ceil(brim_width / (skirt_brim_line_width * initial_layer_line_width_factor / 100.0))",
- "enabled": "resolveOrValue('adhesion_type') == 'brim'",
+ "enabled": "resolveOrValue('adhesion_type') == 'brim' or resolveOrValue('prime_tower_brim_enable')",
"settable_per_mesh": false,
"settable_per_extruder": true,
"limit_to_extruder": "adhesion_extruder_nr"
}
}
},
+ "brim_replaces_support":
+ {
+ "label": "Brim Replaces Support",
+ "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 or support_tree_enable)",
+ "settable_per_mesh": false,
+ "settable_per_extruder": true,
+ "limit_to_extruder": "support_infill_extruder_nr"
+ },
"brim_outside_only":
{
"label": "Brim Only on Outside",
@@ -5095,18 +5574,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
},
@@ -5134,7 +5602,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
@@ -5147,7 +5615,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' 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",
+ "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,
@@ -5161,27 +5629,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' 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",
+ "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",
@@ -5192,6 +5645,17 @@
"settable_per_mesh": false,
"settable_per_extruder": true
},
+ "prime_tower_brim_enable":
+ {
+ "label": "Prime Tower Brim",
+ "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
+ },
"ooze_shield_enabled":
{
"label": "Enable Ooze Shield",
@@ -5314,7 +5778,7 @@
"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
}
@@ -5474,7 +5938,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",
@@ -5719,10 +6183,10 @@
"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,
+ "default_value": 0.5,
"minimum_value": "0.001",
- "minimum_value_warning": "0.005",
- "maximum_value_warning": "0.1",
+ "minimum_value_warning": "0.01",
+ "maximum_value_warning": "3",
"settable_per_mesh": true
},
"meshfix_maximum_travel_resolution":
@@ -5731,14 +6195,26 @@
"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",
+ "default_value": 1.0,
+ "value": "min(meshfix_maximum_resolution * speed_travel / speed_print, 2 * line_width)",
"minimum_value": "0.001",
- "minimum_value_warning": "0.005",
- "maximum_value_warning": "1",
+ "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.",
+ "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
+ },
"support_skip_some_zags":
{
"label": "Break Up Support In Chunks",
@@ -6035,7 +6511,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",
@@ -6205,7 +6681,7 @@
"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)",
+ "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,
@@ -6237,7 +6713,7 @@
"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)",
+ "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",
@@ -6253,7 +6729,7 @@
"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)",
+ "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",
@@ -6513,7 +6989,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,
@@ -6523,7 +6999,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",
@@ -6535,19 +7011,20 @@
},
"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.0001",
"settable_per_extruder": false,
"settable_per_meshgroup": false
},
"adaptive_layer_height_threshold":
{
- "label": "Adaptive layers 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.",
"type": "float",
"enabled": "adaptive_layer_height_enabled",
@@ -6575,9 +7052,8 @@
"unit": "%",
"type": "float",
"default_value": 100,
- "minimum_value": "10",
+ "minimum_value": "0.001",
"minimum_value_warning": "25",
- "maximum_value": "100",
"settable_per_mesh": true
},
"bridge_settings_enabled":
@@ -6819,44 +7295,247 @@
"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,
+ "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,
+ "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,
+ "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,
+ "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": "retraction_speed",
+ "settable_per_mesh": false,
+ "settable_per_extruder": true
+ },
+ "wipe_retraction_prime_speed":
+ {
+ "label": "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": "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 When Retracted",
+ "description": "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.",
+ "type": "bool",
+ "default_value": true,
+ "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,
+ "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": 100,
+ "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
}
}
},
- "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/felixtec4dual.def.json b/resources/definitions/felixtec4dual.def.json
index ba612d4e3c..ba5bcfa112 100644
--- a/resources/definitions/felixtec4dual.def.json
+++ b/resources/definitions/felixtec4dual.def.json
@@ -43,15 +43,15 @@
"retraction_amount": { "default_value": 1 },
"retraction_speed": { "default_value": 50},
- "material_flow": { "default_value": 87 },
+ "material_flow": { "default_value": 95 },
"adhesion_type": { "default_value": "skirt" },
"skirt_brim_minimal_length": { "default_value": 130},
- "machine_start_gcode": {
- "default_value": "; FELIXprinters | www.FELIXprinters.com | Zeemanlaan 15 3401 MV IJsselstein The Netherlands\n; FELIX Tec 4 | Start Code Dual Extruders v1.0\n; Modified by kerog777@gmail.com\n;================================ \n;Initializing\nM80 ; Turn on the power supply\nM107 ; Turn off fans\nM117 Heating up\nM104 T0 S120\nM104 T1 S120\nM140 S{print_bed_temperature} ; Heatup Bed and continue\nG28 ; Home all\nM109 T0 S{print_temperature} ; Heatup hot-end and continue\nM117 Purging\nT0 ; Select extruder 1\nG92 E0 ; Reset extruder\nG1 X10.0 Y1.1 Z5.0 F15240 ; Move to start-line position\nG1 Z0.3 F15240 ; Move z up\nG1 X127.0 Y1.1 Z0.3 F1500.0 E15 ; Purge 1st line\nG92 E0 ; Reset extruder\n\n;================================ ; Initializing done\nM117 FELIXprinting"
+ "machine_start_gcode": {
+ "default_value": "; FELIXprinters | www.FELIXprinters.com | Zeemanlaan 15 3401 MV IJsselstein The Netherlands\n; FELIX Tec 4 | Start Code Dual Extruders v1.0\n; Modified by kerog777@gmail.com\n;================================ \n;Initializing\nM80 ; Turn on the power supply\nM107 ; Turn off fans\nM117 Heating up\nM190 S{material_bed_temperature} ; Heatup Bed\nM104 T0 S120\nM104 T1 S120\nG28 ; Home all\nM109 T0 S{material_print_temperature_layer_0} ; Heatup hot-end\nM117 Purging\nT0 ; Select extruder 1\nG92 E0 ; Reset extruder\nG1 X10.0 Y1.1 Z5.0 F15240 ; Move to start-line position\nG1 Z0.3 F15240 ; Move z up\nG1 X127.0 Y1.1 Z0.3 F1500.0 E15 ; Purge 1st line\nG92 E0 ; Reset extruder\n\n;================================ ; Initializing done\nM117 FELIXprinting"
},
"machine_end_gcode": {
- "default_value": "; FELIXprinters End Code Tec Series v1.0\n; Modified by kerog777@gmail.com\n; ================================= \n; Move extruder to park position\nG91 ; Make coordinates relative\nG1 Z2 F1000 ; Move z 2mm up\nG90 ; Use absolute coordinates again\n G1 X0 Y0 F15240 ; Move bed and printhead to ergonomic position\n\n; ================================= ; Turn off heaters\nM140 S0 ; Turn off bed heater\nT0 ; Select left extruder\nM104 T0 S0 ; Turn off heater and continue\n G92 E0 ; Reset extruder position\nG1 E-6 ; Retract filament 8mm\nG92 E0 ; Reset extruder position\nT1 ; Select right extruder\nM104 T1 S0 ; Turn off heater and continue\nG92 E0 ; Reset extruder position\nG1 E-6 ; Retract filament 8mm\nG92 E0 ; Reset extruder position\nT0 ; Select left extruder\n\n; ================================= ; Turn the rest off\nM107 ; Turn off fan\nM84 ; Disable steppers\nM117 Finished Printing!"
+ "default_value": "; FELIXprinters End Code Tec Series v1.0\n; Modified by kerog777@gmail.com\n; ================================= \n; Move extruder to park position\nG91 ; Make coordinates relative\nG1 Z2 F1000 ; Move z 2mm up\nG90 ; Use absolute coordinates again\nG1 X0 Y0 F15240 ; Move bed and printhead to ergonomic position\n\n; ================================= ; Turn off heaters\nM140 S0 ; Turn off bed heater\nT0 ; Select left extruder\nM104 T0 S0 ; Turn off heater and continue\nG92 E0 ; Reset extruder position\nG1 E-6 ; Retract filament 8mm\nG92 E0 ; Reset extruder position\nT1 ; Select right extruder\nM104 T1 S0 ; Turn off heater and continue\nG92 E0 ; Reset extruder position\nG1 E-6 ; Retract filament 8mm\nG92 E0 ; Reset extruder position\nT0 ; Select left extruder\n\n; ================================= ; Turn the rest off\nM107 ; Turn off fan\nM84 ; Disable steppers\nM117 Finished Printing!"
}
}
}
diff --git a/resources/definitions/flsun_qq.def.json b/resources/definitions/flsun_qq.def.json
new file mode 100644
index 0000000000..ce69317b33
--- /dev/null
+++ b/resources/definitions/flsun_qq.def.json
@@ -0,0 +1,46 @@
+{
+ "version": 2,
+ "name": "FLSUN QQ",
+ "inherits": "fdmprinter",
+ "metadata": {
+ "visible": true,
+ "manufacturer": "FLSUN",
+ "author": "Daniel Green",
+ "file_formats": "text/x-gcode",
+ "machine_extruder_trains": {
+ "0": "flsun_qq_extruder"
+ }
+ },
+ "overrides": {
+ "machine_extruder_count": {
+ "default_value": 1
+ },
+ "machine_heated_bed": {
+ "default_value": true
+ },
+ "machine_width": {
+ "default_value": 240
+ },
+ "machine_height": {
+ "default_value": 285
+ },
+ "machine_depth": {
+ "default_value": 240
+ },
+ "machine_center_is_zero": {
+ "default_value": true
+ },
+ "machine_gcode_flavor": {
+ "default_value": "RepRap (Marlin/Sprinter)"
+ },
+ "machine_start_gcode": {
+ "default_value": "G28 ;Home\nG1 Z15.0 F6000 ;Move the platform down 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_shape": {
+ "default_value": "elliptic"
+ }
+ }
+}
diff --git a/resources/definitions/flsun_qq_s.def.json b/resources/definitions/flsun_qq_s.def.json
new file mode 100644
index 0000000000..5a739e9ae1
--- /dev/null
+++ b/resources/definitions/flsun_qq_s.def.json
@@ -0,0 +1,78 @@
+{
+ "id": "flsun_qq_s",
+ "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"
+ },
+ "top_thickness": {
+ "default_value": 5
+ },
+ "bottom_layers": {
+ "default_value": 4
+ },
+ "gantry_height": {
+ "default_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..3d8823f438
--- /dev/null
+++ b/resources/definitions/geeetech_a30.def.json
@@ -0,0 +1,131 @@
+{
+ "id": "geeetech_a30",
+ "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
+ },
+ "material_bed_temperature": {
+ "default_value": 60
+ },
+ "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
+ },
+ "retraction_retract_speed": {
+ "default_value": 25
+ },
+ "retraction_prime_speed": {
+ "default_value": 25
+ },
+ "adhesion_type": {
+ "default_value": "skirt"
+ },
+ "machine_head_polygon": {
+ "default_value": [
+ [-75, 35],
+ [18, 35],
+ [18, -18],
+ [-75, -18]
+ ]
+ },
+ "machine_head_with_fans_polygon": {
+ "default_value": [
+ [-75, 35],
+ [18, 35],
+ [18, -18],
+ [-75, -18]
+ ]
+ },
+ "gantry_height": {
+ "default_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 16695714f4..eb576f0e19 100644
--- a/resources/definitions/gmax15plus.def.json
+++ b/resources/definitions/gmax15plus.def.json
@@ -14,25 +14,30 @@
"has_variants": true,
"variants_name": "Hotend",
"preferred_variant_name": "0.5mm E3D (Default)",
+ "preferred_quality_type": "gmax15plus_global_normal",
"machine_extruder_trains": {
"0": "gmax15plus_extruder_0"
}
+
+
},
"overrides": {
- "machine_extruder_count": { "default_value": 1 },
+ "machine_extruder_count": { "default_value": 1 },
"machine_name": { "default_value": "gMax 1.5 Plus" },
"machine_heated_bed": { "default_value": false },
"machine_width": { "default_value": 406 },
"machine_depth": { "default_value": 406 },
"machine_height": { "default_value": 533 },
"machine_center_is_zero": { "default_value": false },
+ "material_diameter": { "default_value": 1.75 },
+ "machine_nozzle_size": { "default_value": 0.5 },
"layer_height": { "default_value": 0.2 },
"layer_height_0": { "default_value": 0.3 },
"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 },
@@ -43,10 +48,10 @@
"machine_max_jerk_z": { "default_value": 0.4 },
"machine_max_jerk_e": { "default_value": 5.0 },
"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 ;Home X/Y/Z\nG29 ; Bed level\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_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 },
+ "material_print_temperature": { "default_value": 202 },
+ "wall_thickness": { "default_value": 1 },
"top_bottom_thickness": { "default_value": 1 },
"bottom_thickness": { "default_value": 1 }
}
diff --git a/resources/definitions/gmax15plus_dual.def.json b/resources/definitions/gmax15plus_dual.def.json
index 5972061933..40a3dde303 100644
--- a/resources/definitions/gmax15plus_dual.def.json
+++ b/resources/definitions/gmax15plus_dual.def.json
@@ -10,30 +10,32 @@
"category": "Other",
"file_formats": "text/x-gcode",
"platform": "gmax_1-5_xt-plus_s3d_full model_150707.stl",
- "has_variants": true,
- "has_machine_quality": true,
- "variants_name": "Hotend",
- "preferred_variant_name": "0.5mm E3D (Default)",
- "machine_extruder_trains": {
- "0": "gmax15plus_dual_extruder_0",
- "1": "gmax15plus_dual_extruder_1"
- }
+ "has_variants": true,
+ "variants_name": "Hotend",
+ "preferred_variant_name": "0.5mm E3D (Default)",
+ "preferred_quality_type": "gmax15plus_global_dual_normal",
+ "machine_extruder_trains": {
+ "0": "gmax15plus_dual_extruder_0",
+ "1": "gmax15plus_dual_extruder_1"
+ }
},
"overrides": {
"machine_name": { "default_value": "gMax 1.5 Plus Dual Extruder" },
- "machine_extruder_count": { "default_value": 2 },
+ "machine_extruder_count": { "default_value": 2 },
"machine_heated_bed": { "default_value": false },
"machine_width": { "default_value": 406 },
"machine_depth": { "default_value": 406 },
"machine_height": { "default_value": 533 },
"machine_center_is_zero": { "default_value": false },
+ "material_diameter": { "default_value": 1.75 },
+ "machine_nozzle_size": { "default_value": 0.5 },
"layer_height": { "default_value": 0.2 },
"layer_height_0": { "default_value": 0.3 },
"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 },
@@ -44,10 +46,10 @@
"machine_max_jerk_z": { "default_value": 0.4 },
"machine_max_jerk_e": { "default_value": 5.0 },
"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 ;Home X/Y/Z\nG29 ; Bed level\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_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 },
+ "material_print_temperature": { "default_value": 202 },
+ "wall_thickness": { "default_value": 1 },
"top_bottom_thickness": { "default_value": 1 },
"bottom_thickness": { "default_value": 1 }
}
diff --git a/resources/definitions/grr_neo.def.json b/resources/definitions/grr_neo.def.json
index 0153fc4c01..b3a558825a 100644
--- a/resources/definitions/grr_neo.def.json
+++ b/resources/definitions/grr_neo.def.json
@@ -7,7 +7,6 @@
"author": "Simon Cor",
"manufacturer": "German RepRap",
"file_formats": "text/x-gcode",
- "icon": "icon_ultimaker.png",
"platform": "grr_neo_platform.stl",
"machine_extruder_trains":
{
@@ -38,7 +37,7 @@
]
},
"gantry_height": {
- "default_value": 55
+ "value": "55"
},
"machine_gcode_flavor": {
"default_value": "RepRap (Marlin/Sprinter)"
diff --git a/resources/definitions/hms434.def.json b/resources/definitions/hms434.def.json
new file mode 100644
index 0000000000..58fc65855c
--- /dev/null
+++ b/resources/definitions/hms434.def.json
@@ -0,0 +1,163 @@
+{
+ "name": "HMS434",
+ "version": 2,
+ "inherits": "fdmprinter",
+ "metadata": {
+ "visible": true,
+ "author": "Scheepers",
+ "manufacturer": "MaukCC",
+ "file_formats": "text/x-gcode",
+
+ "has_materials": true,
+ "has_machine_materials": false,
+ "preferred_material": "generic_pla",
+ "exclude_materials": [ "chromatik_pla", "fabtotum_abs", "fabtotum_nylon", "fabtotum_pla", "fabtotum_tpu", "fiberlogy_hd_pla", "filo3d_pla", "filo3d_pla_green", "filo3d_pla_red", "imade3d_petg_green", "imade3d_petg_pink", "imade3d_pla_green", "imade3d_pla_pink", "innofill_innoflex60_175", "octofiber_pla", "imade3d_pla", "polyflex_pla", "polymax_pla", "polyplus_pla", "polywood_pla", "tizyx_abs", "tizyx_pla", "tizyx_pla_bois", "verbatim_bvoh_175", "Vertex_Delta_ABS", "Vertex_Delta_PET", "Vertex_Delta_PLA", "Vertex_Delta_TPU", "zyyx_pro_flex", "zyyx_pro_pla", "generic_cpe_175", "generic_nylon_175", "dsm_arnitel2045_175", "dsm_novamid1070_175", "generic_tpu_175", "generic_pc_175" ],
+
+ "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_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": true},
+ "material_bed_temp_wait": {"default_value": true },
+ "machine_max_feedrate_z": {"default_value": 1200 },
+ "machine_start_gcode": {"default_value": "\n;Neither MaukCC nor any of MaukCC 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" },
+ "alternate_extra_perimeter": {"value": false },
+ "filter_out_tiny_gaps": {"value": false },
+ "fill_outline_gaps": {"value": true },
+ "skin_outline_count": {"value": "0"},
+
+ "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": "100"},
+ "speed_travel_layer_0": {"value": "speed_travel"},
+ "speed_support_interface": {"value": "speed_topbottom"},
+ "speed_slowdown_layers": {"value": 1},
+ "acceleration_print": {"value": 200},
+ "acceleration_travel": {"value": 200},
+ "jerk_print": {"value": 5},
+ "jerk_travel": {"value": 5},
+
+ "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": "'skirt'"},
+ "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..c58235fb67 100644
--- a/resources/definitions/imade3d_jellybox.def.json
+++ b/resources/definitions/imade3d_jellybox.def.json
@@ -1,14 +1,12 @@
{
"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,
@@ -22,18 +20,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..10b2043954
--- /dev/null
+++ b/resources/definitions/imade3d_jellybox_2.def.json
@@ -0,0 +1,37 @@
+{
+ "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_materials": 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..72a9ec3edb 100644
--- a/resources/definitions/innovo_inventor.def.json
+++ b/resources/definitions/innovo_inventor.def.json
@@ -41,7 +41,7 @@
]
},
"gantry_height": {
- "default_value": 82.3
+ "value": "82.3"
},
"machine_gcode_flavor": {
"default_value": "RepRap (Marlin/Sprinter)"
diff --git a/resources/definitions/jgaurora_a1.def.json b/resources/definitions/jgaurora_a1.def.json
new file mode 100644
index 0000000000..3c9f9c61e9
--- /dev/null
+++ b/resources/definitions/jgaurora_a1.def.json
@@ -0,0 +1,93 @@
+{
+ "name": "JGAurora A1",
+ "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_a1_extruder_0"
+ }
+ },
+ "overrides": {
+ "machine_name": {
+ "default_value": "JGAurora A1"
+ },
+ "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": 300
+ },
+ "machine_height": {
+ "default_value": 300
+ },
+ "machine_depth": {
+ "default_value": 300
+ },
+ "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
+ },
+ "material_print_temperature": {
+ "default_value": 215
+ },
+ "material_bed_temperature": {
+ "default_value": 67
+ },
+ "layer_height_0": {
+ "default_value": 0.12
+ },
+ "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": 12
+ },
+ "support_enable": {
+ "default_value": true
+ },
+ "retraction_enable": {
+ "default_value": true
+ },
+ "retraction_amount": {
+ "default_value": 6
+ },
+ "retraction_speed": {
+ "default_value": 40
+ }
+ }
+}
diff --git a/resources/definitions/jgaurora_a5.def.json b/resources/definitions/jgaurora_a5.def.json
new file mode 100644
index 0000000000..e02fca881b
--- /dev/null
+++ b/resources/definitions/jgaurora_a5.def.json
@@ -0,0 +1,95 @@
+{
+ "name": "JGAurora A5 & A5S",
+ "version": 2,
+ "inherits": "fdmprinter",
+ "metadata": {
+ "visible": true,
+ "author": "Samuel Pinches",
+ "manufacturer": "JGAurora",
+ "file_formats": "text/x-gcode",
+ "platform": "jgaurora_a5.stl",
+ "platform_offset": [-242, -101, 273],
+ "preferred_quality_type": "fast",
+ "machine_extruder_trains":
+ {
+ "0": "jgaurora_a5_extruder_0"
+ }
+ },
+ "overrides": {
+ "machine_name": {
+ "default_value": "JGAurora A5 & A5S"
+ },
+ "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": 300
+ },
+ "machine_height": {
+ "default_value": 320
+ },
+ "machine_depth": {
+ "default_value": 300
+ },
+ "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
+ },
+ "material_print_temperature": {
+ "default_value": 215
+ },
+ "material_bed_temperature": {
+ "default_value": 67
+ },
+ "layer_height_0": {
+ "default_value": 0.12
+ },
+ "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": 12
+ },
+ "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_jgmaker_magic.def.json b/resources/definitions/jgaurora_jgmaker_magic.def.json
new file mode 100644
index 0000000000..703305151a
--- /dev/null
+++ b/resources/definitions/jgaurora_jgmaker_magic.def.json
@@ -0,0 +1,93 @@
+{
+ "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
+ },
+ "material_print_temperature": {
+ "default_value": 200
+ },
+ "material_bed_temperature": {
+ "default_value": 60
+ },
+ "layer_height_0": {
+ "default_value": 0.2
+ },
+ "wall_thickness": {
+ "default_value": 1.2
+ },
+ "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": 30
+ },
+ "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
new file mode 100644
index 0000000000..cf92f2fc71
--- /dev/null
+++ b/resources/definitions/jgaurora_z_603s.def.json
@@ -0,0 +1,93 @@
+{
+ "name": "JGAurora Z-603S",
+ "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_z_603s_extruder_0"
+ }
+ },
+ "overrides": {
+ "machine_name": {
+ "default_value": "JGAurora Z-603S"
+ },
+ "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": 280
+ },
+ "machine_height": {
+ "default_value": 175
+ },
+ "machine_depth": {
+ "default_value": 180
+ },
+ "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
+ },
+ "material_print_temperature": {
+ "default_value": 210
+ },
+ "material_bed_temperature": {
+ "default_value": 55
+ },
+ "layer_height_0": {
+ "default_value": 0.2
+ },
+ "wall_thickness": {
+ "default_value": 1.2
+ },
+ "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
+ },
+ "retraction_enable": {
+ "default_value": true
+ },
+ "retraction_amount": {
+ "default_value": 5
+ },
+ "retraction_speed": {
+ "default_value": 50
+ }
+ }
+}
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/kossel_mini.def.json b/resources/definitions/kossel_mini.def.json
index 76fe72dac1..d9c3b3d37f 100644
--- a/resources/definitions/kossel_mini.def.json
+++ b/resources/definitions/kossel_mini.def.json
@@ -5,9 +5,8 @@
"metadata": {
"visible": true,
"author": "Claudio Sampaio (Patola)",
- "manufacturer": "Other",
+ "manufacturer": "Johann",
"file_formats": "text/x-gcode",
- "icon": "icon_ultimaker2",
"platform": "kossel_platform.stl",
"platform_offset": [0, -0.25, 0],
"machine_extruder_trains":
diff --git a/resources/definitions/kossel_pro.def.json b/resources/definitions/kossel_pro.def.json
index 9fadd0db91..f26c6ed068 100644
--- a/resources/definitions/kossel_pro.def.json
+++ b/resources/definitions/kossel_pro.def.json
@@ -5,9 +5,8 @@
"metadata": {
"visible": true,
"author": "Chris Petersen",
- "manufacturer": "OpenBeam",
+ "manufacturer": "Johann",
"file_formats": "text/x-gcode",
- "icon": "icon_ultimaker2",
"platform": "kossel_pro_build_platform.stl",
"platform_offset": [0, -0.25, 0],
"machine_extruder_trains":
diff --git a/resources/definitions/kupido.def.json b/resources/definitions/kupido.def.json
index 412fe979b8..a81a40542b 100644
--- a/resources/definitions/kupido.def.json
+++ b/resources/definitions/kupido.def.json
@@ -1,40 +1,49 @@
{
- "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"
+ "0": "alya3dp_extruder_0"
}
},
"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": "ALYA 3DP" },
+ "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/makeR_pegasus.def.json b/resources/definitions/makeR_pegasus.def.json
index 9bd4547c9b..6b19544612 100644
--- a/resources/definitions/makeR_pegasus.def.json
+++ b/resources/definitions/makeR_pegasus.def.json
@@ -7,7 +7,6 @@
"author": "makeR",
"manufacturer": "makeR",
"file_formats": "text/x-gcode",
- "icon": "icon_ultimaker2",
"platform": "makeR_pegasus_platform.stl",
"platform_offset": [-200, -10, 200],
"machine_extruder_trains":
@@ -42,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 d22af5c516..c7e7f4079d 100644
--- a/resources/definitions/makeR_prusa_tairona_i3.def.json
+++ b/resources/definitions/makeR_prusa_tairona_i3.def.json
@@ -7,7 +7,6 @@
"author": "makeR",
"manufacturer": "makeR",
"file_formats": "text/x-gcode",
- "icon": "icon_ultimaker2",
"platform": "makeR_prusa_tairona_i3_platform.stl",
"platform_offset": [-2, 0, 0],
"machine_extruder_trains":
@@ -42,7 +41,7 @@
]
},
"gantry_height": {
- "default_value": 55
+ "value": "55"
},
"machine_gcode_flavor": {
"default_value": "RepRap (Marlin/Sprinter)"
diff --git a/resources/definitions/makeit_pro_l.def.json b/resources/definitions/makeit_pro_l.def.json
index 2f9173c90e..5d09189de8 100644
--- a/resources/definitions/makeit_pro_l.def.json
+++ b/resources/definitions/makeit_pro_l.def.json
@@ -4,11 +4,10 @@
"inherits": "fdmprinter",
"metadata": {
"visible": true,
- "author": "NA",
- "manufacturer": "NA",
+ "author": "unknown",
+ "manufacturer": "MAKEiT 3D",
"file_formats": "text/x-gcode",
"has_materials": false,
- "supported_actions": [ "MachineSettingsAction", "UpgradeFirmware" ],
"machine_extruder_trains":
{
"0": "makeit_l_dual_1st",
@@ -40,7 +39,7 @@
]
},
"gantry_height": {
- "default_value": 330
+ "value": "330"
},
"machine_use_extruder_offset_to_offset_coords": {
"default_value": true
diff --git a/resources/definitions/makeit_pro_m.def.json b/resources/definitions/makeit_pro_m.def.json
index 0cd7b42df3..57e2a7dbd4 100644
--- a/resources/definitions/makeit_pro_m.def.json
+++ b/resources/definitions/makeit_pro_m.def.json
@@ -4,11 +4,10 @@
"inherits": "fdmprinter",
"metadata": {
"visible": true,
- "author": "NA",
- "manufacturer": "NA",
+ "author": "unknown",
+ "manufacturer": "MAKEiT 3D",
"file_formats": "text/x-gcode",
"has_materials": false,
- "supported_actions": [ "MachineSettingsAction", "UpgradeFirmware" ],
"machine_extruder_trains":
{
"0": "makeit_dual_1st",
@@ -40,7 +39,7 @@
]
},
"gantry_height": {
- "default_value": 200
+ "value": "200"
},
"machine_use_extruder_offset_to_offset_coords": {
"default_value": true
diff --git a/resources/definitions/maker_starter.def.json b/resources/definitions/maker_starter.def.json
index 8fb67623ed..560e53ccb9 100644
--- a/resources/definitions/maker_starter.def.json
+++ b/resources/definitions/maker_starter.def.json
@@ -7,7 +7,6 @@
"author": "tvlgiao",
"manufacturer": "3DMaker",
"file_formats": "text/x-gcode;application/x-stl-ascii;application/x-stl-binary;application/x-wavefront-obj",
- "icon": "icon_ultimaker2.png",
"platform": "makerstarter_platform.stl",
"preferred_quality_type": "draft",
"machine_extruder_trains":
@@ -34,7 +33,7 @@
"default_value": false
},
"gantry_height": {
- "default_value": 55
+ "value": "55"
},
"machine_gcode_flavor": {
"default_value": "RepRap (Marlin/Sprinter)"
@@ -133,7 +132,7 @@
"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"
diff --git a/resources/definitions/makerbotreplicator.def.json b/resources/definitions/makerbotreplicator.def.json
index 1770b7a979..3b02215e74 100644
--- a/resources/definitions/makerbotreplicator.def.json
+++ b/resources/definitions/makerbotreplicator.def.json
@@ -6,6 +6,7 @@
"visible": true,
"author": "Ultimaker",
"manufacturer": "MakerBot",
+ "machine_x3g_variant": "r1",
"file_formats": "application/x3g",
"platform_offset": [ 0, 0, 0],
"machine_extruder_trains":
diff --git a/resources/definitions/malyan_m180.def.json b/resources/definitions/malyan_m180.def.json
index 53864dabae..cd3a068134 100644
--- a/resources/definitions/malyan_m180.def.json
+++ b/resources/definitions/malyan_m180.def.json
@@ -53,7 +53,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..71c94184b2 100644
--- a/resources/definitions/malyan_m200.def.json
+++ b/resources/definitions/malyan_m200.def.json
@@ -80,7 +80,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..104be7091b 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": {
diff --git a/resources/definitions/mendel90.def.json b/resources/definitions/mendel90.def.json
index 104ca7f42f..39cb4de8d3 100644
--- a/resources/definitions/mendel90.def.json
+++ b/resources/definitions/mendel90.def.json
@@ -5,7 +5,7 @@
"metadata":
{
"visible": true,
- "author": "Bo Herrmannsen",
+ "author": "Wilmer Gaona",
"manufacturer": "Nophead",
"file_formats": "text/x-gcode",
"platform": "mendel90_platform.stl",
@@ -23,10 +23,10 @@
"overrides": {
"machine_name": { "default_value": "Mendel90" },
"machine_start_gcode": {
- "default_value": "G21 ;metric values\nG90 ;absolute positioning\nG92 E0 ;zero the extruded length\nM107 ;start with the fan off\nG1 X90 Y200 F6000 ;go to the middle of the front\nG1 Z0.05 ;close to the bed\nG1 Z0.3 ;lift Z\n"
+ "default_value": "G21 ;metric values\nG90 ;absolute positioning\nM82 ;absolute extrusion\nM107 ;start with the fan off\nG28 ;home\nG92 E0 ;zero the extruded length\nM140 S{material_bed_temperature_layer_0} ; set the bed temperature and continue on\nG1 X-50 Y98 F9000 ;go to the left of the top\nG1 Z0.05 ; close to the bed\nM104 S{material_print_temperature_layer_0}; pre-heat the extruder continue on\nM190 S{material_bed_temperature_layer_0} ;set the bed temp & wait\nM109 S{material_print_temperature_layer_0};set the extruder temp for layer 0 & wait\nG92 E0 ;zero the extruded length\nG1 X50 E10 F300 ; make a thick line to prime extruder\nG92 E0 ; reset extruder\nG1 E-4 F1800\nG1 Z0.3 ;lift Z\n"
},
"machine_end_gcode": {
- "default_value": "M104 S0 ;extruder heater off\nM140 S0 ;heated bed heater off (if you have it)\nM107 ;carriage fan off\nG91 ;relative positioning\nG1 Z10 ;Move up Z 10mm\nG90 ;back to absolute mode\nG1 E-1 F1200 ;retract the filament a bit before lifting the nozzle, to release some of the pressure\nG92 E0 ;zero the extruded length\nG1 Y200 F5000 ;Move Y to middle of bed cooling fan\nM42 P42 S255 ;Turn on Bed cooling fan on\nG4 S420 ;Wait 7 mins\nM42 P42 S0 ;Turn off bed cooling fan\nG1 Y10 F5000 ;Move Y to front\nM84 ;steppers off\n"
+ "default_value": "M104 S0 ;extruder heater off\nM140 S0 ;heated bed heater off (if you have it)\nM107 ;carriage fan off\nG91 ;relative positioning\nG1 Z10 ;Move up Z 10mm\nG90 ;back to absolute mode\nG1 E-1 F1200 ;retract the filament a bit before lifting the nozzle, to release some of the pressure\nG92 E0 ;zero the extruded length\nG1 Z200 X-100 F9000 ; go to top\nG1 Y100 F5000 ;Move Y to back\nM42 P42 S255 ;Turn on Bed cooling fan on\nG4 S10 ;Wait 10 seconds\nM42 P42 S0 ;Turn off bed cooling fan\nM84 ;steppers off\n"
},
"material_bed_temp_wait": {
"default_value": true
@@ -47,7 +47,7 @@
"default_value": true
},
"machine_center_is_zero": {
- "default_value": false
+ "default_value": true
},
"machine_extruder_count": {
"default_value": 1
@@ -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_ultimate.def.json b/resources/definitions/monoprice_ultimate.def.json
new file mode 100644
index 0000000000..48290f0941
--- /dev/null
+++ b/resources/definitions/monoprice_ultimate.def.json
@@ -0,0 +1,52 @@
+{
+ "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
+ ]
+ },
+ "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..8ef46fb98c
--- /dev/null
+++ b/resources/definitions/nwa3d_a31.def.json
@@ -0,0 +1,66 @@
+{
+ "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",
+ "has_machine_materials": true,
+ "has_variant_materials": false,
+ "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_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
new file mode 100644
index 0000000000..2829b06927
--- /dev/null
+++ b/resources/definitions/nwa3d_a5.def.json
@@ -0,0 +1,64 @@
+{
+ "name": "NWA3D A5",
+ "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": false,
+ "has_machine_materials": true,
+ "has_variant_materials": false,
+ "preferred_quality_type": "normal",
+ "has_machine_quality": true,
+ "preferred_material": "generic_pla",
+ "machine_extruder_trains":
+ {
+ "0": "nwa3d_a5_extruder_0"
+ }
+ },
+
+ "overrides": {
+ "machine_name": {
+ "default_value": "NWA3D A5"
+ },
+ "machine_width": {
+ "default_value": 125
+ },
+ "machine_height": {
+ "default_value": 100
+ },
+ "machine_depth": {
+ "default_value": 150
+ },
+ "machine_head_polygon": {
+ "default_value": [
+ [-30, 34],
+ [-30, -32],
+ [30, -32],
+ [30, 34]
+ ]
+ },
+ "gantry_height": {
+ "value": "30"
+ },
+ "machine_heated_bed": {
+ "default_value": false
+ },
+ "material_diameter": {
+ "default_value": 1.75
+ },
+ "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_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/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..b8879e825c 100644
--- a/resources/definitions/printrbot_play.def.json
+++ b/resources/definitions/printrbot_play.def.json
@@ -27,7 +27,7 @@
"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},
diff --git a/resources/definitions/printrbot_play_heated.def.json b/resources/definitions/printrbot_play_heated.def.json
index 680496bf56..7987f55010 100644
--- a/resources/definitions/printrbot_play_heated.def.json
+++ b/resources/definitions/printrbot_play_heated.def.json
@@ -7,7 +7,6 @@
"author": "Chris Pearson",
"manufacturer": "Printrbot",
"file_formats": "text/x-gcode",
- "platform": "",
"machine_extruder_trains":
{
"0": "printrbot_play_heated_extruder_0"
diff --git a/resources/definitions/printrbot_simple.def.json b/resources/definitions/printrbot_simple.def.json
index fb65b77fa5..4d1f368b6d 100644
--- a/resources/definitions/printrbot_simple.def.json
+++ b/resources/definitions/printrbot_simple.def.json
@@ -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..c4cab54386 100644
--- a/resources/definitions/printrbot_simple_extended.def.json
+++ b/resources/definitions/printrbot_simple_extended.def.json
@@ -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 c676f7fe96..581de6fd98 100644
--- a/resources/definitions/prusa_i3.def.json
+++ b/resources/definitions/prusa_i3.def.json
@@ -5,9 +5,8 @@
"metadata": {
"visible": true,
"author": "Quillford",
- "manufacturer": "Prusajr",
+ "manufacturer": "Prusa3D",
"file_formats": "text/x-gcode",
- "icon": "icon_ultimaker2",
"platform": "prusai3_platform.stl",
"machine_extruder_trains":
{
@@ -49,7 +48,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 169eb6ffc2..ff6f4469e7 100644
--- a/resources/definitions/prusa_i3_mk2.def.json
+++ b/resources/definitions/prusa_i3_mk2.def.json
@@ -5,9 +5,8 @@
"metadata": {
"visible": true,
"author": "Apsu, Nounours2099",
- "manufacturer": "Prusa Research",
+ "manufacturer": "Prusa3D",
"file_formats": "text/x-gcode",
- "icon": "icon_ultimaker2",
"platform": "prusai3_platform.stl",
"has_materials": true,
"machine_extruder_trains":
@@ -32,7 +31,7 @@
"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_xl.def.json b/resources/definitions/prusa_i3_xl.def.json
index eafed22df1..b9628b9430 100644
--- a/resources/definitions/prusa_i3_xl.def.json
+++ b/resources/definitions/prusa_i3_xl.def.json
@@ -5,9 +5,8 @@
"metadata": {
"visible": true,
"author": "guigashm",
- "manufacturer": "Prusajr",
+ "manufacturer": "Prusa3D",
"file_formats": "text/x-gcode",
- "icon": "icon_ultimaker2.png",
"platform": "prusai3_xl_platform.stl",
"machine_extruder_trains":
{
@@ -41,7 +40,7 @@
]
},
"gantry_height": {
- "default_value": 55
+ "value": "55"
},
"machine_gcode_flavor": {
"default_value": "RepRap (Marlin/Sprinter)"
diff --git a/resources/definitions/raise3D_N2_dual.def.json b/resources/definitions/raise3D_N2_dual.def.json
index eff5884da8..1994cc2bcb 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"
diff --git a/resources/definitions/raise3D_N2_plus_dual.def.json b/resources/definitions/raise3D_N2_plus_dual.def.json
index 06de52321a..23ad1fbd09 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"
diff --git a/resources/definitions/raise3D_N2_plus_single.def.json b/resources/definitions/raise3D_N2_plus_single.def.json
index b829147160..f8a1a7e0fb 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,7 +66,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\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"
diff --git a/resources/definitions/raise3D_N2_single.def.json b/resources/definitions/raise3D_N2_single.def.json
index 899da5188f..c69823466b 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,7 +66,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\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"
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_zero2.def.json b/resources/definitions/rigid3d_zero2.def.json
index 09390ed8b5..f24c869636 100644
--- a/resources/definitions/rigid3d_zero2.def.json
+++ b/resources/definitions/rigid3d_zero2.def.json
@@ -81,7 +81,7 @@
"default_value": false
},
"gantry_height": {
- "default_value": 25
+ "value": "25"
},
"machine_gcode_flavor": {
"default_value": "RepRap"
diff --git a/resources/definitions/rigidbot.def.json b/resources/definitions/rigidbot.def.json
index 5eb346c7ca..c04cd7c5e6 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)"
diff --git a/resources/definitions/rigidbot_big.def.json b/resources/definitions/rigidbot_big.def.json
index 581b6144a0..c97c6df9f3 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)"
diff --git a/resources/definitions/seemecnc_artemis.def.json b/resources/definitions/seemecnc_artemis.def.json
index aa788865df..ec92f528d7 100644
--- a/resources/definitions/seemecnc_artemis.def.json
+++ b/resources/definitions/seemecnc_artemis.def.json
@@ -7,7 +7,6 @@
"author": "PouncingIguana, JJ",
"manufacturer": "SeeMeCNC",
"file_formats": "text/x-gcode",
- "icon": "icon_ultimaker2",
"platform": "artemis_platform.stl",
"has_materials": true,
"machine_extruder_trains":
diff --git a/resources/definitions/seemecnc_v32.def.json b/resources/definitions/seemecnc_v32.def.json
index 5a855f67fc..d4316c25d9 100644
--- a/resources/definitions/seemecnc_v32.def.json
+++ b/resources/definitions/seemecnc_v32.def.json
@@ -7,7 +7,6 @@
"author": "PouncingIguana, JJ",
"manufacturer": "SeeMeCNC",
"file_formats": "text/x-gcode",
- "icon": "icon_ultimaker2",
"platform": "rostock_platform.stl",
"has_materials": true,
"machine_extruder_trains":
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..38f7c4b0d3
--- /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_machine_materials": true,
+ "has_variants": true,
+ "preferred_variant_name": "Standard 0.6",
+ "preferred_material": "emotiontech_pla",
+ "preferred_quality_type": "e",
+ "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_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": { "default_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 E-1 F1500 \nG0 z1 \nG90 \nG28 \nM801.2 \nM801.0 \nM84" },
+ "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": 2000 },
+
+ "acceleration_enabled": { "value": false },
+ "acceleration_layer_0": { "value": "acceleration_topbottom" },
+ "acceleration_prime_tower": { "value": "math.ceil(acceleration_print * 1000 / 2000)" },
+ "acceleration_print": { "value": "2000" },
+ "acceleration_support": { "value": "acceleration_print" },
+ "acceleration_support_interface": { "value": "acceleration_topbottom" },
+ "acceleration_topbottom": { "value": "math.ceil(acceleration_print * 1000 / 2000)" },
+ "acceleration_wall": { "value": "math.ceil(acceleration_print * 1500 / 2000)" },
+ "acceleration_wall_0": { "value": "math.ceil(acceleration_wall * 1000 / 1500)" },
+ "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
new file mode 100644
index 0000000000..fd43ae7da9
--- /dev/null
+++ b/resources/definitions/structur3d_discov3ry1_complete_um2plus.def.json
@@ -0,0 +1,118 @@
+{
+ "version": 2,
+ "name": "Discov3ry Complete",
+ "inherits": "fdmprinter",
+ "metadata": {
+ "author": "Andrew Finkle, CTO",
+ "manufacturer": "Structur3d.io",
+ "visible": true,
+ "file_formats": "text/x-gcode",
+ "platform": "ultimaker2_platform.obj",
+ "platform_texture": "Ultimaker2Plusbackplate.png",
+ "platform_offset": [0, 0, 0],
+ "has_materials": true,
+ "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": [],
+ "supported_actions": [],
+ "machine_extruder_trains":
+ {
+ "0": "structur3d_discov3ry1_complete_um2plus_extruder_0"
+ },
+ "firmware_file": "MarlinUltimaker2plus.hex"
+ },
+
+ "overrides": {
+ "machine_name": { "default_value": "Discov3ry Complete (Ultimaker 2+)" },
+ "speed_infill": {
+ "value": "speed_print"
+ },
+ "infill_sparse_density": {
+ "value": 100
+ },
+ "retraction_hop_enabled": {
+ "value": true
+ },
+ "adhesion_type": {
+ "default_value": "skirt"
+ },
+ "skirt_brim_minimal_length": {
+ "value": 1500
+ },
+ "speed_print": {
+ "value": 15
+ },
+ "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_layer_0": {
+ "default_value": 10
+ },
+ "speed_support": {
+ "value": "speed_wall_0"
+ },
+ "machine_height": {
+ "default_value": 205
+ },
+ "machine_width": {
+ "default_value": 205
+ },
+ "machine_depth": {
+ "default_value": 205
+ },
+ "machine_show_variants": {
+ "default_value": true
+ },
+ "gantry_height": {
+ "value": "52"
+ },
+ "machine_nozzle_head_distance": {
+ "default_value": 5
+ },
+ "machine_nozzle_expansion_angle": {
+ "default_value": 45
+ },
+ "machine_heat_zone_length": {
+ "default_value": 20
+ },
+ "machine_head_with_fans_polygon":
+ {
+ "default_value": [
+ [ -44, 14 ],
+ [ -44, -34 ],
+ [ 64, 14 ],
+ [ 64, -34 ]
+ ]
+ },
+ "machine_disallowed_areas": {
+ "default_value": [
+ [[-115, 112.5], [ -78, 112.5], [ -80, 102.5], [-115, 102.5]],
+ [[ 115, 112.5], [ 115, 102.5], [ 105, 102.5], [ 103, 112.5]],
+ [[-115, -112.5], [-115, -104.5], [ -84, -104.5], [ -82, -112.5]],
+ [[ 115, -112.5], [ 108, -112.5], [ 110, -104.5], [ 115, -104.5]]
+ ]
+ },
+ "machine_gcode_flavor": {
+ "default_value": "RepRap (Marlin/Sprinter)"
+ },
+ "machine_start_gcode": {
+ "default_value": "\n;Updated Firmware (.hex and Marlin .ino) for \n;Ultimaker 2+ with Discov3ry Extruder available at: \n;https://github.com/Structur3d/UM2.1Discov3ry-Firmware-beta \n;**Learn more at https://www.structur3d.io** \n \nM104 S{material_print_temperature} ;Start heating extruder \nM140 S{material_bed_temperature} ;Start heating bed \nG21 ;metric values \nG90 ;absolute positioning \nM82 ;set extruder to absolute mode \nM107 ;start with the fan off \nM302 ;allow cold extrusion \nM92 E2589 ;set extruder EEPROM steps/mm for paste \nG28 Z0 ;move Z to bottom endstops \nG28 X0 Y0 ;move X/Y to endstops \nG1 X15 Y0 F4000 ;move X/Y to front of printer \nG1 Z15.0 F9000 ;move the platform to 15mm \nG92 E0 ;zero the extruded length \nG1 F200 E10 ;extrude 10 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 S0 ;extruder heater off \nM140 S0 ;heated bed heater off (if you have it) \nM92 E282 ;reset extruder EEPROM steps/mm for plastic filament \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"
+ }
+
+ }
+}
diff --git a/resources/definitions/tam.def.json b/resources/definitions/tam.def.json
index 9865abedda..67a4bb8eab 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,
@@ -10,7 +10,6 @@
"platform": "tam_series1.stl",
"platform_offset": [-580.0, -6.23, 253.5],
"has_materials": false,
- "supported_actions": ["UpgradeFirmware"],
"machine_extruder_trains":
{
"0": "tam_extruder_0"
@@ -33,8 +32,8 @@
"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 },
diff --git a/resources/definitions/tevo_blackwidow.def.json b/resources/definitions/tevo_blackwidow.def.json
index b193023867..9e450067fb 100644
--- a/resources/definitions/tevo_blackwidow.def.json
+++ b/resources/definitions/tevo_blackwidow.def.json
@@ -7,7 +7,6 @@
"author": "TheTobby",
"manufacturer": "Tevo",
"file_formats": "text/x-gcode",
- "icon": "icon_ultimaker2",
"has_materials": false,
"has_machine_quality": true,
"platform": "tevo_blackwidow.stl",
@@ -45,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 40d579552e..038cc3a318 100644
--- a/resources/definitions/tevo_tarantula.def.json
+++ b/resources/definitions/tevo_tarantula.def.json
@@ -8,7 +8,6 @@
"author": "TheAssassin",
"manufacturer": "Tevo",
"file_formats": "text/x-gcode",
- "icon": "icon_ultimaker2",
"platform": "prusai3_platform.stl",
"machine_extruder_trains":
{
@@ -34,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 },
@@ -43,7 +42,7 @@
"machine_max_feedrate_x": { "default_value": 255 },
"machine_max_feedrate_y": { "default_value": 225 },
"machine_max_feedrate_z": { "default_value": 3 },
- "machine_max_acceleration_x": { "default_value": 2620 },
+ "machine_max_acceleration_x": { "default_value": 2650 },
"machine_max_acceleration_y": { "default_value": 2650 },
"acceleration_print": { "default_value": 2650 },
"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/tevo_tornado.def.json b/resources/definitions/tevo_tornado.def.json
index e121c8e097..67f25ec9d8 100644
--- a/resources/definitions/tevo_tornado.def.json
+++ b/resources/definitions/tevo_tornado.def.json
@@ -7,14 +7,13 @@
"author": "nean",
"manufacturer": "Tevo",
"file_formats": "text/x-gcode",
- "icon": "icon_ultimaker2.png",
"has_materials": true,
"machine_extruder_trains": {
"0": "tevo_tornado_extruder_0"
}
},
"overrides": {
- "machine_name": {
+ "machine_name": {
"default_value": "Tevo Tornado"
},
"machine_width": {
@@ -26,8 +25,8 @@
"machine_depth": {
"default_value": 300
},
- "machine_center_is_zero": {
- "default_value": false
+ "machine_center_is_zero": {
+ "default_value": false
},
"machine_head_polygon": {
"default_value": [
@@ -71,25 +70,43 @@
"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": {
- "default_value": "; start_gcode\nM117 Start Clean ; Indicate nozzle clean in progress on LCD\n;\nM104 S[extruder0_temperature] \nM109 S[extruder0_temperature] \nM109 R[extruder0_temperature] \n;\nM107 ; Turn layer fan off\nG21 ; Set to metric [change to G20 if you want Imperial]\nG90 ; Force coordinates to be absolute relative to the origin\nG28 ; Home X/Y/Z axis\n;\nG1 X3 Y1 Z15 F9000 ; Move safe Z height to shear strings\nG0 X1 Y1 Z0.2 F9000 ; Move in 1mm from edge and up [z] 0.2mm\nG92 E0 ; Set extruder to [0] zero\nG1 X100 E12 F500 ; Extrude 30mm filiment along X axis 100mm long to prime and clean the nozzle\nG92 E0 ; Reset extruder to [0] zero end of cleaning run\nG1 E-1 F500 ; Retract filiment by 1 mm to reduce string effect\nG1 X180 F4000 ; quick wipe away from the filament line / purge\nM117 End Clean ; Indicate nozzle clean in progress on LCD\n;\nM117 Printing...\n; Begin printing with sliced GCode after here\n;"
+ "default_value": "; start_gcode\nM117 Start Clean ; Indicate nozzle clean in progress on LCD\n;\nM104 S{material_print_temperature_layer_0} \nM109 S{material_print_temperature_layer_0} \nM109 R{material_print_temperature_layer_0} \n;\nM107 ; Turn layer fan off\nG21 ; Set to metric [change to G20 if you want Imperial]\nG90 ; Force coordinates to be absolute relative to the origin\nG28 ; Home X/Y/Z axis\n;\nG1 X3 Y1 Z15 F9000 ; Move safe Z height to shear strings\nG0 X1 Y1 Z0.2 F9000 ; Move in 1mm from edge and up [z] 0.2mm\nG92 E0 ; Set extruder to [0] zero\nG1 X100 E12 F500 ; Extrude 30mm filiment along X axis 100mm long to prime and clean the nozzle\nG92 E0 ; Reset extruder to [0] zero end of cleaning run\nG1 E-1 F500 ; Retract filiment by 1 mm to reduce string effect\nG1 X180 F4000 ; quick wipe away from the filament line / purge\nM117 End Clean ; Indicate nozzle clean in progress on LCD\n;\nM117 Printing...\n; Begin printing with sliced GCode after here\n;"
},
"machine_end_gcode": {
"default_value": ";\n; end_gcode\nG92 E0 ; zero the extruded length\nG1 E-5 F9000 ; retract\nM104 S0 ; turn off temperature\nM140 S0 ; turn off bed\nG91 ; relative positioning\nG1 E-1 F300 ; retract the filament a bit before lifting the nozzle, to release some of the pressure\nG1 Z+20 E-5 X-20 Y-20 F7200 ; move Z up a bit and retract filament even more\nG1 X320 Y150 F10000 ; move right mid\nM107 ; turn off layer fan\nM84 ; disable motors\nG90 ; absolute positioning\n;\n;EOF"
diff --git a/resources/definitions/tizyx_evy.def.json b/resources/definitions/tizyx_evy.def.json
new file mode 100644
index 0000000000..a09e8dfc46
--- /dev/null
+++ b/resources/definitions/tizyx_evy.def.json
@@ -0,0 +1,81 @@
+{
+ "name": "TiZYX EVY",
+ "version": 2,
+ "inherits": "fdmprinter",
+ "metadata": {
+ "visible": true,
+ "author": "TiZYX",
+ "manufacturer": "TiZYX",
+ "file_formats": "text/x-gcode",
+
+ "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", "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":
+ {
+ "0": "tizyx_evy_extruder_0"
+ },
+ "platform": "tizyx_k25_platform.stl",
+ "platform_offset": [0, -4, 0],
+ "first_start_actions": ["MachineSettingsAction"],
+ "supported_actions": ["MachineSettingsAction"]
+ },
+
+ "overrides": {
+ "machine_extruder_count": { "default_value": 1 },
+ "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]
+ ]
+ },
+
+ "adhesion_type": { "default_value": "skirt" },
+ "skirt_line_count": {"default_value": 2},
+ "skirt_gap": { "default_value": 2},
+ "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')))" },
+
+ "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_evy_dual.def.json b/resources/definitions/tizyx_evy_dual.def.json
new file mode 100644
index 0000000000..2f4ee8f9a9
--- /dev/null
+++ b/resources/definitions/tizyx_evy_dual.def.json
@@ -0,0 +1,64 @@
+{
+ "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_machine_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 94a20b371e..32fa9b331d 100644
--- a/resources/definitions/tizyx_k25.def.json
+++ b/resources/definitions/tizyx_k25.def.json
@@ -1,50 +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,
- "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 1b5cb1456c..060752387b 100644
--- a/resources/definitions/ubuild-3d_mr_bot_280.def.json
+++ b/resources/definitions/ubuild-3d_mr_bot_280.def.json
@@ -9,8 +9,6 @@
"manufacturer": "uBuild-3D",
"category": "Other",
"file_formats": "text/x-gcode",
- "icon": "icon_uBuild-3D",
- "platform": "mr_bot_280_platform.stl",
"has_materials": true,
"preferred_quality_type": "draft",
"machine_extruder_trains":
@@ -36,7 +34,7 @@
"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/ultimaker.def.json b/resources/definitions/ultimaker.def.json
index a980a1afdf..aec7907dbe 100644
--- a/resources/definitions/ultimaker.def.json
+++ b/resources/definitions/ultimaker.def.json
@@ -7,7 +7,7 @@
"manufacturer": "Ultimaker B.V.",
"category": "Ultimaker",
"visible": false,
- "exclude_materials": [ "generic_hips", "generic_petg" ]
+ "exclude_materials": [ "generic_hips", "generic_petg", "structur3d_dap100silicone" ]
},
"overrides": {
"machine_max_feedrate_e": {
diff --git a/resources/definitions/ultimaker2.def.json b/resources/definitions/ultimaker2.def.json
index a91d2332b0..285f5bed08 100644
--- a/resources/definitions/ultimaker2.def.json
+++ b/resources/definitions/ultimaker2.def.json
@@ -8,20 +8,19 @@
"manufacturer": "Ultimaker B.V.",
"weight": 3,
"file_formats": "text/x-gcode",
- "icon": "icon_ultimaker2.png",
"platform": "ultimaker2_platform.obj",
"platform_texture": "Ultimaker2backplate.png",
"platform_offset": [9, 0, 0],
"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", "UpgradeFirmware"],
+ "supported_actions":["UM2UpgradeSelection"],
"machine_extruder_trains":
{
"0": "ultimaker2_extruder_0"
- }
+ },
+ "firmware_file": "MarlinUltimaker2.hex"
},
"overrides": {
"machine_name": { "default_value": "Ultimaker 2" },
@@ -56,7 +55,7 @@
"default_value": false
},
"gantry_height": {
- "default_value": 48
+ "value": "48"
},
"machine_use_extruder_offset_to_offset_coords": {
"default_value": true
diff --git a/resources/definitions/ultimaker2_extended.def.json b/resources/definitions/ultimaker2_extended.def.json
index af169c94fb..572634c602 100644
--- a/resources/definitions/ultimaker2_extended.def.json
+++ b/resources/definitions/ultimaker2_extended.def.json
@@ -8,13 +8,13 @@
"quality_definition": "ultimaker2",
"weight": 3,
"file_formats": "text/x-gcode",
- "icon": "icon_ultimaker2.png",
"platform": "ultimaker2_platform.obj",
"platform_texture": "Ultimaker2Extendedbackplate.png",
"machine_extruder_trains":
{
"0": "ultimaker2_extended_extruder_0"
- }
+ },
+ "firmware_file": "MarlinUltimaker2extended.hex"
},
"overrides": {
diff --git a/resources/definitions/ultimaker2_extended_plus.def.json b/resources/definitions/ultimaker2_extended_plus.def.json
index f3a8bfcf9f..0242115057 100644
--- a/resources/definitions/ultimaker2_extended_plus.def.json
+++ b/resources/definitions/ultimaker2_extended_plus.def.json
@@ -10,11 +10,11 @@
"file_formats": "text/x-gcode",
"platform": "ultimaker2_platform.obj",
"platform_texture": "Ultimaker2ExtendedPlusbackplate.png",
- "supported_actions": ["UpgradeFirmware"],
"machine_extruder_trains":
{
"0": "ultimaker2_extended_plus_extruder_0"
- }
+ },
+ "firmware_file": "MarlinUltimaker2extended-plus.hex"
},
"overrides": {
diff --git a/resources/definitions/ultimaker2_go.def.json b/resources/definitions/ultimaker2_go.def.json
index c66fb38fc0..9e374b2c88 100644
--- a/resources/definitions/ultimaker2_go.def.json
+++ b/resources/definitions/ultimaker2_go.def.json
@@ -8,16 +8,15 @@
"quality_definition": "ultimaker2",
"weight": 3,
"file_formats": "text/x-gcode",
- "icon": "icon_ultimaker2.png",
"platform": "ultimaker2go_platform.obj",
"platform_texture": "Ultimaker2Gobackplate.png",
"platform_offset": [0, 0, 0],
"first_start_actions": [],
- "supported_actions": ["UpgradeFirmware"],
"machine_extruder_trains":
{
"0": "ultimaker2_go_extruder_0"
- }
+ },
+ "firmware_file": "MarlinUltimaker2go.hex"
},
"overrides": {
diff --git a/resources/definitions/ultimaker2_plus.def.json b/resources/definitions/ultimaker2_plus.def.json
index bc4d3a6230..f95d29c684 100644
--- a/resources/definitions/ultimaker2_plus.def.json
+++ b/resources/definitions/ultimaker2_plus.def.json
@@ -14,12 +14,14 @@
"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": ["UpgradeFirmware"],
+ "supported_actions": [],
"machine_extruder_trains":
{
"0": "ultimaker2_plus_extruder_0"
- }
+ },
+ "firmware_file": "MarlinUltimaker2plus.hex"
},
"overrides": {
@@ -49,7 +51,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 b1daa6b780..a297d33c82 100644
--- a/resources/definitions/ultimaker3.def.json
+++ b/resources/definitions/ultimaker3.def.json
@@ -14,6 +14,7 @@
"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",
@@ -24,7 +25,16 @@
},
"first_start_actions": [ "DiscoverUM3Action" ],
"supported_actions": [ "DiscoverUM3Action" ],
- "supports_usb_connection": false
+ "supports_usb_connection": false,
+ "supports_network_connection": true,
+ "firmware_update_info": {
+ "id": 9066,
+ "check_urls":
+ [
+ "http://software.ultimaker.com/releases/firmware/9066/stable/um-update.swu.version"
+ ],
+ "update_url": "https://ultimaker.com/firmware"
+ }
},
@@ -53,7 +63,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]],
@@ -69,7 +79,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 },
+ "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" },
@@ -109,7 +119,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 eb3cda9320..43f7b94e61 100644
--- a/resources/definitions/ultimaker3_extended.def.json
+++ b/resources/definitions/ultimaker3_extended.def.json
@@ -23,7 +23,15 @@
"1": "ultimaker3_extended_extruder_right"
},
"first_start_actions": [ "DiscoverUM3Action" ],
- "supported_actions": [ "DiscoverUM3Action" ]
+ "supported_actions": [ "DiscoverUM3Action" ],
+ "firmware_update_info": {
+ "id": 9511,
+ "check_urls":
+ [
+ "http://software.ultimaker.com/releases/firmware/9066/stable/um-update.swu.version"
+ ],
+ "update_url": "https://ultimaker.com/firmware"
+ }
},
"overrides": {
diff --git a/resources/definitions/ultimaker_original.def.json b/resources/definitions/ultimaker_original.def.json
index c961423504..71130312e7 100644
--- a/resources/definitions/ultimaker_original.def.json
+++ b/resources/definitions/ultimaker_original.def.json
@@ -8,17 +8,18 @@
"manufacturer": "Ultimaker B.V.",
"weight": 4,
"file_formats": "text/x-gcode",
- "icon": "icon_ultimaker.png",
"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", "UpgradeFirmware"],
+ "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"
- }
+ },
+ "firmware_file": "MarlinUltimaker-{baudrate}.hex",
+ "firmware_hbk_file": "MarlinUltimaker-HBK-{baudrate}.hex"
},
"overrides": {
@@ -45,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 55eddba85f..fd9b91e238 100644
--- a/resources/definitions/ultimaker_original_dual.def.json
+++ b/resources/definitions/ultimaker_original_dual.def.json
@@ -8,19 +8,20 @@
"manufacturer": "Ultimaker B.V.",
"weight": 4,
"file_formats": "text/x-gcode",
- "icon": "icon_ultimaker.png",
"platform": "ultimaker_platform.stl",
"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",
"1": "ultimaker_original_dual_2nd"
},
- "first_start_actions": ["UMOUpgradeSelection", "UMOCheckup", "BedLevel"],
- "supported_actions": ["UMOUpgradeSelection", "UMOCheckup", "BedLevel", "UpgradeFirmware"]
+ "firmware_file": "MarlinUltimaker-{baudrate}-dual.hex",
+ "firmware_hbk_file": "MarlinUltimaker-HBK-{baudrate}-dual.hex",
+ "first_start_actions": ["UMOUpgradeSelection", "BedLevel"],
+ "supported_actions": ["UMOUpgradeSelection", "BedLevel"]
},
"overrides": {
@@ -47,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 71aa53b2bf..949e2e8d0d 100644
--- a/resources/definitions/ultimaker_original_plus.def.json
+++ b/resources/definitions/ultimaker_original_plus.def.json
@@ -7,16 +7,17 @@
"manufacturer": "Ultimaker B.V.",
"weight": 4,
"file_formats": "text/x-gcode",
- "icon": "icon_ultimaker.png",
"platform": "ultimaker2_platform.obj",
"platform_texture": "UltimakerPlusbackplate.png",
"quality_definition": "ultimaker_original",
- "first_start_actions": ["UMOCheckup", "BedLevel"],
- "supported_actions": ["UMOCheckup", "BedLevel", "UpgradeFirmware"],
+ "first_start_actions": ["BedLevel"],
+ "supported_actions": ["BedLevel"],
"machine_extruder_trains":
{
"0": "ultimaker_original_plus_extruder_0"
- }
+ },
+ "firmware_file": "MarlinUltimaker-UMOP-{baudrate}.hex",
+ "firmware_hbk_file": "MarlinUltimaker-UMOP-{baudrate}.hex"
},
"overrides": {
diff --git a/resources/definitions/ultimaker_s5.def.json b/resources/definitions/ultimaker_s5.def.json
index 2e634787af..9410651044 100644
--- a/resources/definitions/ultimaker_s5.def.json
+++ b/resources/definitions/ultimaker_s5.def.json
@@ -30,7 +30,13 @@
"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/um-update.swu.version"],
+ "update_url": "https://ultimaker.com/firmware"
+ }
},
"overrides": {
@@ -56,7 +62,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_extruder_count": { "default_value": 2 },
"extruder_prime_pos_abs": { "default_value": true },
"machine_start_gcode": { "default_value": "" },
@@ -151,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 1612c1bf80..427177176a 100644
--- a/resources/definitions/uni_print_3d.def.json
+++ b/resources/definitions/uni_print_3d.def.json
@@ -26,11 +26,6 @@
"machine_center_is_zero": { "default_value": true },
"machine_nozzle_heat_up_speed": { "default_value": 2.0 },
"machine_nozzle_cool_down_speed": { "default_value": 2.0 },
- "machine_head_shape_min_x": { "default_value": 75 },
- "machine_head_shape_min_y": { "default_value": 18 },
- "machine_head_shape_max_x": { "default_value": 18 },
- "machine_head_shape_max_y": { "default_value": 35 },
- "machine_nozzle_gantry_distance": { "default_value": 55 },
"machine_gcode_flavor": { "default_value": "RepRap (Marlin/Sprinter)" },
"machine_start_gcode": {
diff --git a/resources/definitions/uniqbot_one.def.json b/resources/definitions/uniqbot_one.def.json
index 396e9687b8..ec8336ae50 100644
--- a/resources/definitions/uniqbot_one.def.json
+++ b/resources/definitions/uniqbot_one.def.json
@@ -6,7 +6,6 @@
"author": "Unimatech",
"manufacturer": "Unimatech",
"file_formats": "text/x-gcode",
- "icon": "icon_ultimaker2.png",
"machine_extruder_trains":
{
"0": "uniqbot_one_extruder_0"
@@ -31,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 7059c2e7f0..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":
@@ -30,26 +30,8 @@
"machine_shape": {
"default_value": "elliptic"
},
- "machine_head_shape_min_x": {
- "default_value": 0
- },
- "machine_head_shape_min_y": {
- "default_value": 0
- },
- "machine_head_shape_max_x": {
- "default_value": 0
- },
- "machine_head_shape_max_y": {
- "default_value": 0
- },
"gantry_height": {
- "default_value": 0
- },
- "machine_nozzle_offset_x_1": {
- "default_value": 0
- },
- "machine_nozzle_offset_y_1": {
- "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 0166729951..6bba095978 100644
--- a/resources/definitions/vertex_k8400.def.json
+++ b/resources/definitions/vertex_k8400.def.json
@@ -4,9 +4,8 @@
"inherits": "fdmprinter",
"metadata": {
"visible": true,
- "manufacturer": "Velleman",
+ "manufacturer": "Velleman N.V.",
"file_formats": "text/x-gcode",
- "icon": "icon_ultimaker2",
"platform": "Vertex_build_panel.stl",
"platform_offset": [0, -3, 0],
"supports_usb_connection": true,
@@ -59,7 +58,7 @@
]
},
"gantry_height": {
- "default_value": 18
+ "value": "18"
},
"machine_gcode_flavor": {
"default_value": "RepRap (Marlin/Sprinter)"
diff --git a/resources/definitions/vertex_k8400_dual.def.json b/resources/definitions/vertex_k8400_dual.def.json
index b22dabaa94..9d014b9cf8 100644
--- a/resources/definitions/vertex_k8400_dual.def.json
+++ b/resources/definitions/vertex_k8400_dual.def.json
@@ -4,9 +4,8 @@
"inherits": "fdmprinter",
"metadata": {
"visible": true,
- "manufacturer": "Velleman",
+ "manufacturer": "Velleman N.V.",
"file_formats": "text/x-gcode",
- "icon": "icon_ultimaker2",
"platform": "Vertex_build_panel.stl",
"platform_offset": [0, -3, 0],
"machine_extruder_trains": {
@@ -60,7 +59,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..02697a1152
--- /dev/null
+++ b/resources/definitions/vertex_nano_k8600.def.json
@@ -0,0 +1,83 @@
+{
+ "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
+ },
+ "material_bed_temperature": {
+ "default_value": 0
+ },
+ "material_bed_temperature_layer_0": {
+ "default_value": 0
+ },
+ "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_d4s.def.json b/resources/definitions/wanhao_d4s.def.json
index 1ae16a9d56..c1807923c6 100644
--- a/resources/definitions/wanhao_d4s.def.json
+++ b/resources/definitions/wanhao_d4s.def.json
@@ -7,7 +7,6 @@
"author": "Ricardo Snoek",
"manufacturer": "Wanhao",
"file_formats": "text/x-gcode",
- "icon": "wanhao-icon.png",
"has_materials": true,
"platform": "wanhao_225_145_platform.obj",
"platform_texture": "Wanhaobackplate.png",
@@ -40,10 +39,10 @@
"default_value": "RepRap (Marlin/Sprinter)"
},
"machine_start_gcode": {
- "default_value": "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 min endstops\n G28 Z0 ;move Z to min endstops\n G1 Z15.0 F{travel_speed} ;move the platform down 15mm\n G92 E0 ;zero the extruded length\n G1 F200 E6 ;extrude 6 mm of feed stock\n G92 E0 ;zero the extruded length again\n G1 F{travel_speed} \n ;Put printing message on LCD screen\n M117 Printing..."
+ "default_value": "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 min endstops\n G28 Z0 ;move Z to min endstops\n G1 Z15.0 F{speed_travel} ;move the platform down 15mm\n G92 E0 ;zero the extruded length\n G1 F200 E6 ;extrude 6 mm of feed stock\n G92 E0 ;zero the extruded length again\n G1 F{speed_travel} \n ;Put printing message on LCD screen\n M117 Printing..."
},
"machine_end_gcode": {
- "default_value": "M104 S0 ;extruder heater off \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{travel_speed} ;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"
+ "default_value": "M104 S0 ;extruder heater off \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"
}
}
}
diff --git a/resources/definitions/wanhao_d6.def.json b/resources/definitions/wanhao_d6.def.json
index 6164f4d016..eaaae54826 100644
--- a/resources/definitions/wanhao_d6.def.json
+++ b/resources/definitions/wanhao_d6.def.json
@@ -7,7 +7,6 @@
"author": "Ricardo Snoek",
"manufacturer": "Wanhao",
"file_formats": "text/x-gcode",
- "icon": "wanhao-icon.png",
"has_materials": true,
"platform": "wanhao_200_200_platform.obj",
"platform_texture": "Wanhaobackplate.png",
@@ -18,9 +17,6 @@
0,
-28,
0
- ],
- "supported_actions": [
- "UpgradeFirmware"
]
},
"overrides": {
@@ -40,16 +36,16 @@
"default_value": true
},
"gantry_height": {
- "default_value": 55
+ "value": "55"
},
"machine_gcode_flavor": {
"default_value": "RepRap (Marlin/Sprinter)"
},
"machine_start_gcode": {
- "default_value": "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 min endstops\n G28 Z0 ;move Z to min endstops\n G1 Z15.0 F{travel_speed} ;move the platform down 15mm\n G92 E0 ;zero the extruded length\n G1 F200 E6 ;extrude 6 mm of feed stock\n G92 E0 ;zero the extruded length again\n G1 F{travel_speed} \n ;Put printing message on LCD screen\n M117 Printing..."
+ "default_value": "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 min endstops\n G28 Z0 ;move Z to min endstops\n G1 Z15.0 F{speed_travel} ;move the platform down 15mm\n G92 E0 ;zero the extruded length\n G1 F200 E6 ;extrude 6 mm of feed stock\n G92 E0 ;zero the extruded length again\n G1 F{speed_travel} \n ;Put printing message on LCD screen\n M117 Printing..."
},
"machine_end_gcode": {
- "default_value": "M104 S0 ;extruder heater off \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{travel_speed} ;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"
+ "default_value": "M104 S0 ;extruder heater off \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"
}
}
}
diff --git a/resources/definitions/wanhao_d6_plus.def.json b/resources/definitions/wanhao_d6_plus.def.json
index 04cb6fae9f..b3b5ed9b0a 100644
--- a/resources/definitions/wanhao_d6_plus.def.json
+++ b/resources/definitions/wanhao_d6_plus.def.json
@@ -7,7 +7,6 @@
"author": "Ricardo Snoek",
"manufacturer": "Wanhao",
"file_formats": "text/x-gcode",
- "icon": "wanhao-icon.png",
"has_materials": true,
"platform": "wanhao_200_200_platform.obj",
"platform_texture": "Wanhaobackplate.png",
@@ -40,10 +39,10 @@
"default_value": "RepRap (Marlin/Sprinter)"
},
"machine_start_gcode": {
- "default_value": "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 min endstops\n G28 Z0 ;move Z to min endstops\n G1 Z15.0 F{travel_speed} ;move the platform down 15mm\n G92 E0 ;zero the extruded length\n G1 F200 E6 ;extrude 6 mm of feed stock\n G92 E0 ;zero the extruded length again\n G1 F{travel_speed} \n ;Put printing message on LCD screen\n M117 Printing..."
+ "default_value": "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 min endstops\n G28 Z0 ;move Z to min endstops\n G1 Z15.0 F{speed_travel} ;move the platform down 15mm\n G92 E0 ;zero the extruded length\n G1 F200 E6 ;extrude 6 mm of feed stock\n G92 E0 ;zero the extruded length again\n G1 F{speed_travel} \n ;Put printing message on LCD screen\n M117 Printing..."
},
"machine_end_gcode": {
- "default_value": "M104 S0 ;extruder heater off \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{travel_speed} ;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"
+ "default_value": "M104 S0 ;extruder heater off \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"
}
}
}
diff --git a/resources/definitions/wanhao_d9.def.json b/resources/definitions/wanhao_d9.def.json
new file mode 100644
index 0000000000..39ad139ff8
--- /dev/null
+++ b/resources/definitions/wanhao_d9.def.json
@@ -0,0 +1,41 @@
+{
+ "version": 2,
+ "name": "Wanhao Duplicator 9",
+ "inherits": "fdmprinter",
+ "metadata": {
+ "visible": true,
+ "manufacturer": "Wanhao",
+ "file_formats": "text/x-gcode",
+ "has_materials": true,
+ "platform": "wanhao_300_300_platform.obj",
+ "platform_texture": "Wanhaobackplate.png",
+ "machine_extruder_trains": {
+ "0": "wanhao_d9_extruder_0"
+ },
+ "platform_offset": [ 0, -55, 0]
+ },
+
+ "overrides": {
+ "machine_name": { "default_value": "Wanhao Duplicator 9" },
+ "machine_width": { "default_value": 300 },
+ "machine_height": { "default_value": 400 },
+ "machine_depth": { "default_value": 300 },
+ "machine_heated_bed": { "default_value": true },
+ "machine_gcode_flavor": { "default_value": "RepRap (Marlin/Sprinter)" },
+ "machine_start_gcode": {
+ "default_value": "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 min endstops\n G28 Z0 ;move Z to min endstops\n G1 Z15.0 F{speed_travel} ;move the platform down 15mm\n G92 E0 ;zero the extruded length\n G1 F200 E6 ;extrude 6 mm of feed stock\n G92 E0 ;zero the extruded length again\n G1 F{speed_travel} \n ;Put printing message on LCD screen\n M117 Printing..."
+ },
+ "machine_end_gcode": {
+ "default_value": "M104 S0 ;extruder heater off \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"
+ },
+ "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" },
+ "support_z_distance": { "default_value": 0.22 }
+ }
+}
diff --git a/resources/definitions/wanhao_duplicator5S.def.json b/resources/definitions/wanhao_duplicator5S.def.json
index 1ccc867876..b27a13fda8 100644
--- a/resources/definitions/wanhao_duplicator5S.def.json
+++ b/resources/definitions/wanhao_duplicator5S.def.json
@@ -7,7 +7,6 @@
"author": "Ricardo Snoek",
"manufacturer": "Wanhao",
"file_formats": "text/x-gcode",
- "icon": "wanhao-icon.png",
"has_materials": true,
"platform": "wanhao_300_200_platform.obj",
"platform_texture": "Wanhaobackplate.png",
@@ -43,10 +42,10 @@
"default_value": "RepRap (Marlin/Sprinter)"
},
"machine_start_gcode": {
- "default_value": "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 min endstops\n G28 Z0 ;move Z to min endstops\n G1 Z15.0 F{travel_speed} ;move the platform down 15mm\n G92 E0 ;zero the extruded length\n G1 F200 E6 ;extrude 6 mm of feed stock\n G92 E0 ;zero the extruded length again\n G1 F{travel_speed} \n ;Put printing message on LCD screen\n M117 Printing..."
+ "default_value": "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 min endstops\n G28 Z0 ;move Z to min endstops\n G1 Z15.0 F{speed_travel} ;move the platform down 15mm\n G92 E0 ;zero the extruded length\n G1 F200 E6 ;extrude 6 mm of feed stock\n G92 E0 ;zero the extruded length again\n G1 F{speed_travel} \n ;Put printing message on LCD screen\n M117 Printing..."
},
"machine_end_gcode": {
- "default_value": "M104 S0 ;extruder heater off \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{travel_speed} ;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"
+ "default_value": "M104 S0 ;extruder heater off \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"
}
}
}
diff --git a/resources/definitions/wanhao_duplicator5Smini.def.json b/resources/definitions/wanhao_duplicator5Smini.def.json
index 774360f41e..e3ef0b92fe 100644
--- a/resources/definitions/wanhao_duplicator5Smini.def.json
+++ b/resources/definitions/wanhao_duplicator5Smini.def.json
@@ -7,7 +7,6 @@
"author": "Ricardo Snoek",
"manufacturer": "Wanhao",
"file_formats": "text/x-gcode",
- "icon": "wanhao-icon.png",
"has_materials": true,
"platform": "wanhao_300_200_platform.obj",
"platform_texture": "Wanhaobackplate.png",
@@ -40,10 +39,10 @@
"default_value": "RepRap (Marlin/Sprinter)"
},
"machine_start_gcode": {
- "default_value": "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 min endstops\n G28 Z0 ;move Z to min endstops\n G1 Z15.0 F{travel_speed} ;move the platform down 15mm\n G92 E0 ;zero the extruded length\n G1 F200 E6 ;extrude 6 mm of feed stock\n G92 E0 ;zero the extruded length again\n G1 F{travel_speed} \n ;Put printing message on LCD screen\n M117 Printing..."
+ "default_value": "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 min endstops\n G28 Z0 ;move Z to min endstops\n G1 Z15.0 F{speed_travel} ;move the platform down 15mm\n G92 E0 ;zero the extruded length\n G1 F200 E6 ;extrude 6 mm of feed stock\n G92 E0 ;zero the extruded length again\n G1 F{speed_travel} \n ;Put printing message on LCD screen\n M117 Printing..."
},
"machine_end_gcode": {
- "default_value": "M104 S0 ;extruder heater off \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{travel_speed} ;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"
+ "default_value": "M104 S0 ;extruder heater off \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"
}
}
}
diff --git a/resources/definitions/wanhao_i3.def.json b/resources/definitions/wanhao_i3.def.json
index c349259cad..42b19c8748 100644
--- a/resources/definitions/wanhao_i3.def.json
+++ b/resources/definitions/wanhao_i3.def.json
@@ -7,7 +7,6 @@
"author": "Ricardo Snoek",
"manufacturer": "Wanhao",
"file_formats": "text/x-gcode",
- "icon": "wanhao-icon.png",
"has_materials": true,
"platform": "wanhao_200_200_platform.obj",
"platform_texture": "Wanhaobackplate.png",
@@ -40,10 +39,10 @@
"default_value": "RepRap (Marlin/Sprinter)"
},
"machine_start_gcode": {
- "default_value": "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 min endstops\n G28 Z0 ;move Z to min endstops\n G1 Z15.0 F{travel_speed} ;move the platform down 15mm\n G92 E0 ;zero the extruded length\n G1 F200 E6 ;extrude 6 mm of feed stock\n G92 E0 ;zero the extruded length again\n G1 F{travel_speed} \n ;Put printing message on LCD screen\n M117 Printing..."
+ "default_value": "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 min endstops\n G28 Z0 ;move Z to min endstops\n G1 Z15.0 F{speed_travel} ;move the platform down 15mm\n G92 E0 ;zero the extruded length\n G1 F200 E6 ;extrude 6 mm of feed stock\n G92 E0 ;zero the extruded length again\n G1 F{speed_travel} \n ;Put printing message on LCD screen\n M117 Printing..."
},
"machine_end_gcode": {
- "default_value": "M104 S0 ;extruder heater off \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{travel_speed} ;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"
+ "default_value": "M104 S0 ;extruder heater off \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"
}
}
}
diff --git a/resources/definitions/wanhao_i3mini.def.json b/resources/definitions/wanhao_i3mini.def.json
index 4531483459..0c70391c27 100644
--- a/resources/definitions/wanhao_i3mini.def.json
+++ b/resources/definitions/wanhao_i3mini.def.json
@@ -7,7 +7,6 @@
"author": "Ricardo Snoek",
"manufacturer": "Wanhao",
"file_formats": "text/x-gcode",
- "icon": "wanhao-icon.png",
"has_materials": true,
"platform": "wanhao_110_110_platform.obj",
"platform_texture": "Wanhaobackplate.png",
@@ -40,10 +39,10 @@
"default_value": "RepRap (Marlin/Sprinter)"
},
"machine_start_gcode": {
- "default_value": "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 min endstops\n G28 Z0 ;move Z to min endstops\n G1 Z15.0 F{travel_speed} ;move the platform down 15mm\n G92 E0 ;zero the extruded length\n G1 F200 E6 ;extrude 6 mm of feed stock\n G92 E0 ;zero the extruded length again\n G1 F{travel_speed} \n ;Put printing message on LCD screen\n M117 Printing..."
+ "default_value": "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 min endstops\n G28 Z0 ;move Z to min endstops\n G1 Z15.0 F{speed_travel} ;move the platform down 15mm\n G92 E0 ;zero the extruded length\n G1 F200 E6 ;extrude 6 mm of feed stock\n G92 E0 ;zero the extruded length again\n G1 F{speed_travel} \n ;Put printing message on LCD screen\n M117 Printing..."
},
"machine_end_gcode": {
- "default_value": "M104 S0 ;extruder heater off \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{travel_speed} ;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"
+ "default_value": "M104 S0 ;extruder heater off \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"
}
}
}
diff --git a/resources/definitions/wanhao_i3plus.def.json b/resources/definitions/wanhao_i3plus.def.json
index 5338fbeea2..e454a40ae1 100644
--- a/resources/definitions/wanhao_i3plus.def.json
+++ b/resources/definitions/wanhao_i3plus.def.json
@@ -7,7 +7,6 @@
"author": "Ricardo Snoek",
"manufacturer": "Wanhao",
"file_formats": "text/x-gcode",
- "icon": "wanhao-icon.png",
"has_materials": true,
"platform": "wanhao_200_200_platform.obj",
"platform_texture": "Wanhaobackplate.png",
@@ -40,10 +39,10 @@
"default_value": "RepRap (Marlin/Sprinter)"
},
"machine_start_gcode": {
- "default_value": "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 min endstops\n G28 Z0 ;move Z to min endstops\n G1 Z15.0 F{travel_speed} ;move the platform down 15mm\n G92 E0 ;zero the extruded length\n G1 F200 E6 ;extrude 6 mm of feed stock\n G92 E0 ;zero the extruded length again\n G1 F{travel_speed} \n ;Put printing message on LCD screen\n M117 Printing..."
+ "default_value": "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 min endstops\n G28 Z0 ;move Z to min endstops\n G1 Z15.0 F{speed_travel} ;move the platform down 15mm\n G92 E0 ;zero the extruded length\n G1 F200 E6 ;extrude 6 mm of feed stock\n G92 E0 ;zero the extruded length again\n G1 F{speed_travel} \n ;Put printing message on LCD screen\n M117 Printing..."
},
"machine_end_gcode": {
- "default_value": "M104 S0 ;extruder heater off \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{travel_speed} ;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"
+ "default_value": "M104 S0 ;extruder heater off \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"
}
}
}
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
new file mode 100644
index 0000000000..f9212c9597
--- /dev/null
+++ b/resources/definitions/z-bolt_classic.def.json
@@ -0,0 +1,59 @@
+{
+ "version": 2,
+ "name": "Z-Bolt Classic",
+ "inherits": "fdmprinter",
+ "metadata": {
+ "visible": true,
+ "author": "Z-Bolt",
+ "manufacturer": "Z-Bolt Co.",
+ "file_formats": "text/x-gcode",
+ "platform": "z-bolt_classic_platform.stl",
+ "machine_extruder_trains":
+ {
+ "0": "z-bolt_extruder_0"
+ }
+ },
+
+ "overrides": {
+ "machine_name": { "default_value": "Z-Bolt Classic" },
+ "machine_heated_bed": {
+ "default_value": true
+ },
+ "machine_width": {
+ "default_value": 200
+ },
+ "machine_height": {
+ "default_value": 240
+ },
+ "machine_depth": {
+ "default_value": 200
+ },
+ "machine_center_is_zero": {
+ "default_value": false
+ },
+ "machine_head_with_fans_polygon":
+ {
+ "default_value": [
+ [ -75, 35 ],
+ [ -75, -18 ],
+ [ 18, 35 ],
+ [ 18, -18 ]
+ ]
+ },
+ "gantry_height": {
+ "value": "55"
+ },
+ "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 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 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 S0 ;extruder heater off' + ('\nM140 S0 ;heated bed heater off' if machine_heated_bed else '') + '\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 Z0 ;move X/Y to min endstops, so the head is out of the way\nM84 ;steppers off\nG90 ;absolute positioning'"
+ }
+ }
+}
\ No newline at end of file
diff --git a/resources/definitions/z-bolt_plus.def.json b/resources/definitions/z-bolt_plus.def.json
new file mode 100644
index 0000000000..dace8ea300
--- /dev/null
+++ b/resources/definitions/z-bolt_plus.def.json
@@ -0,0 +1,59 @@
+{
+ "version": 2,
+ "name": "Z-Bolt Plus",
+ "inherits": "fdmprinter",
+ "metadata": {
+ "visible": true,
+ "author": "Z-Bolt",
+ "manufacturer": "Z-Bolt Co.",
+ "file_formats": "text/x-gcode",
+ "platform": "z-bolt_plus_platform.stl",
+ "machine_extruder_trains":
+ {
+ "0": "z-bolt_extruder_0"
+ }
+ },
+
+ "overrides": {
+ "machine_name": { "default_value": "Z-Bolt Plus" },
+ "machine_heated_bed": {
+ "default_value": true
+ },
+ "machine_width": {
+ "default_value": 300
+ },
+ "machine_height": {
+ "default_value": 335
+ },
+ "machine_depth": {
+ "default_value": 200
+ },
+ "machine_center_is_zero": {
+ "default_value": false
+ },
+ "machine_head_with_fans_polygon":
+ {
+ "default_value": [
+ [ -75, 35 ],
+ [ -75, -18 ],
+ [ 18, 35 ],
+ [ 18, -18 ]
+ ]
+ },
+ "gantry_height": {
+ "value": "55"
+ },
+ "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 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 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 S0 ;extruder heater off' + ('\nM140 S0 ;heated bed heater off' if machine_heated_bed else '') + '\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 Z0 ;move X/Y to min endstops, so the head is out of the way\nM84 ;steppers off\nG90 ;absolute positioning'"
+ }
+ }
+}
\ No newline at end of file
diff --git a/resources/definitions/zone3d_printer.def.json b/resources/definitions/zone3d_printer.def.json
index 328505e18a..5aa015cace 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":
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/Mark2_extruder1.def.json b/resources/extruders/Mark2_extruder1.def.json
new file mode 100644
index 0000000000..915c331083
--- /dev/null
+++ b/resources/extruders/Mark2_extruder1.def.json
@@ -0,0 +1,19 @@
+{
+ "id": "Mark2_extruder1",
+ "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..2c05a09391
--- /dev/null
+++ b/resources/extruders/Mark2_extruder2.def.json
@@ -0,0 +1,19 @@
+{
+ "id": "Mark2_extruder2",
+ "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/alfawise_u20_extruder_0.def.json b/resources/extruders/alfawise_u20_extruder_0.def.json
new file mode 100644
index 0000000000..2fbe3f1772
--- /dev/null
+++ b/resources/extruders/alfawise_u20_extruder_0.def.json
@@ -0,0 +1,16 @@
+{
+ "id": "alfawise_u20_extruder_0",
+ "version": 2,
+ "name": "Extruder 1",
+ "inherits": "fdmextruder",
+ "metadata": {
+ "machine": "alfawise_u20",
+ "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/creality_cr10_extruder_0.def.json b/resources/extruders/alfawise_u30_extruder_0.def.json
similarity index 80%
rename from resources/extruders/creality_cr10_extruder_0.def.json
rename to resources/extruders/alfawise_u30_extruder_0.def.json
index 3a259b672b..37f59eb567 100644
--- a/resources/extruders/creality_cr10_extruder_0.def.json
+++ b/resources/extruders/alfawise_u30_extruder_0.def.json
@@ -1,10 +1,10 @@
{
- "id": "creality_cr10_extruder_0",
+ "id": "alfawise_u30_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
"metadata": {
- "machine": "creality_cr10",
+ "machine": "alfawise_u30",
"position": "0"
},
diff --git a/resources/extruders/alya3dp_extruder_0.def.json b/resources/extruders/alya3dp_extruder_0.def.json
index e34db5dfbf..3676f01ad2 100644
--- a/resources/extruders/alya3dp_extruder_0.def.json
+++ b/resources/extruders/alya3dp_extruder_0.def.json
@@ -11,6 +11,6 @@
"overrides": {
"extruder_nr": { "default_value": 0 },
"machine_nozzle_size": { "default_value": 0.4 },
- "material_diameter": { "default_value": 2.85 }
+ "material_diameter": { "default_value": 1.75 }
}
}
diff --git a/resources/extruders/creality_ender3_extruder_0.def.json b/resources/extruders/anet_a6_extruder_0.def.json
similarity index 80%
rename from resources/extruders/creality_ender3_extruder_0.def.json
rename to resources/extruders/anet_a6_extruder_0.def.json
index 431366c777..704d3a55ca 100644
--- a/resources/extruders/creality_ender3_extruder_0.def.json
+++ b/resources/extruders/anet_a6_extruder_0.def.json
@@ -1,10 +1,10 @@
{
- "id": "creality_ender3_extruder_0",
+ "id": "anet_a6_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
"metadata": {
- "machine": "creality_ender3",
+ "machine": "anet_a6",
"position": "0"
},
diff --git a/resources/extruders/creality_cr10s4_extruder_0.def.json b/resources/extruders/anycubic_4max_extruder_0.def.json
similarity index 65%
rename from resources/extruders/creality_cr10s4_extruder_0.def.json
rename to resources/extruders/anycubic_4max_extruder_0.def.json
index 9afe1cee35..5c2ab8d479 100644
--- a/resources/extruders/creality_cr10s4_extruder_0.def.json
+++ b/resources/extruders/anycubic_4max_extruder_0.def.json
@@ -1,16 +1,16 @@
{
- "id": "creality_cr10s4_extruder_0",
+ "id": "anycubic_4max_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
"metadata": {
- "machine": "creality_cr10s4",
+ "machine": "anycubic_4max",
"position": "0"
},
"overrides": {
"extruder_nr": { "default_value": 0 },
"machine_nozzle_size": { "default_value": 0.4 },
- "material_diameter": { "default_value": 2.85 }
+ "material_diameter": { "default_value": 1.75 }
}
}
diff --git a/resources/extruders/creality_cr10s5_extruder_0.def.json b/resources/extruders/anycubic_chiron_extruder_0.def.json
similarity index 65%
rename from resources/extruders/creality_cr10s5_extruder_0.def.json
rename to resources/extruders/anycubic_chiron_extruder_0.def.json
index fed86eb2b5..cc48df08bb 100644
--- a/resources/extruders/creality_cr10s5_extruder_0.def.json
+++ b/resources/extruders/anycubic_chiron_extruder_0.def.json
@@ -1,16 +1,16 @@
{
- "id": "creality_cr10s5_extruder_0",
+ "id": "anycubic_chiron_extruder_0",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
"metadata": {
- "machine": "creality_cr10s5",
+ "machine": "anycubic_chiron",
"position": "0"
},
"overrides": {
"extruder_nr": { "default_value": 0 },
"machine_nozzle_size": { "default_value": 0.4 },
- "material_diameter": { "default_value": 2.85 }
+ "material_diameter": { "default_value": 1.75 }
}
}
diff --git a/resources/extruders/bibo2_dual_extruder_0.def.json b/resources/extruders/bibo2_dual_extruder_0.def.json
new file mode 100644
index 0000000000..f83801fa0c
--- /dev/null
+++ b/resources/extruders/bibo2_dual_extruder_0.def.json
@@ -0,0 +1,46 @@
+{
+ "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"
+ }
+ }
+}
diff --git a/resources/extruders/bibo2_dual_extruder_1.def.json b/resources/extruders/bibo2_dual_extruder_1.def.json
new file mode 100644
index 0000000000..5f479ba54b
--- /dev/null
+++ b/resources/extruders/bibo2_dual_extruder_1.def.json
@@ -0,0 +1,46 @@
+{
+ "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"
+ }
+ }
+}
diff --git a/resources/extruders/cocoon_create_modelmaker_extruder_0.def.json b/resources/extruders/cocoon_create_modelmaker_extruder_0.def.json
new file mode 100644
index 0000000000..26d847483d
--- /dev/null
+++ b/resources/extruders/cocoon_create_modelmaker_extruder_0.def.json
@@ -0,0 +1,16 @@
+{
+ "id": "cocoon_create_modelmaker_extruder_0",
+ "version": 2,
+ "name": "Extruder 1",
+ "inherits": "fdmextruder",
+ "metadata": {
+ "machine": "cocoon_create_modelmaker",
+ "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/cr-x_extruder_0.def.json b/resources/extruders/cr-x_extruder_0.def.json
new file mode 100644
index 0000000000..8135815afb
--- /dev/null
+++ b/resources/extruders/cr-x_extruder_0.def.json
@@ -0,0 +1,27 @@
+{
+ "id": "cr-x_extruder_0",
+ "version": 2,
+ "name": "Left Extruder",
+ "inherits": "fdmextruder",
+ "metadata": {
+ "machine": "Creality CR-X",
+ "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 },
+ "material_diameter": { "default_value": 1.75 },
+ "machine_nozzle_size": { "default_value": 0.4 },
+ "machine_extruder_start_code": {
+ "default_value": "\nT0 ;switch to extruder 1\nG92 E0 ;reset extruder distance\nG1 F2000 E93 ;load filament\nG92 E0 ;reset extruder distance\nM104 S{material_print_temperature}"
+ },
+ "machine_extruder_end_code": {
+ "default_value": "\nG92 E0 ;reset extruder distance\nG1 F800 E-5 ;short retract\nG1 F2400 X295 Y265 ;move near prime tower\nG1 F2000 E-93 ;long retract for filament removal\nG92 E0 ;reset extruder distance\nG90"
+ }
+ }
+}
diff --git a/resources/extruders/cr-x_extruder_1.def.json b/resources/extruders/cr-x_extruder_1.def.json
new file mode 100644
index 0000000000..9313f2ea78
--- /dev/null
+++ b/resources/extruders/cr-x_extruder_1.def.json
@@ -0,0 +1,27 @@
+{
+ "id": "cr-x_extruder_1",
+ "version": 2,
+ "name": "Right Extruder",
+ "inherits": "fdmextruder",
+ "metadata": {
+ "machine": "Creality CR-X",
+ "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 },
+ "material_diameter": { "default_value": 1.75 },
+ "machine_nozzle_size": { "default_value": 0.4 },
+ "machine_extruder_start_code": {
+ "default_value": "\nT1 ;switch to extruder 2\nG92 E0 ;reset extruder distance\nG1 F2000 E93 ;load filament\nG92 E0 ;reset extruder distance\nM104 S{material_print_temperature}"
+ },
+ "machine_extruder_end_code": {
+ "default_value": "\nG92 E0 ;reset extruder distance\nG1 F800 E-5 ;short retract\nG1 F2400 X295 Y265 ;move near prime tower\nG1 F2000 E-93 ;long retract for filament removal\nG92 E0 ;reset extruder distance\nG90"
+ }
+ }
+}
diff --git a/resources/extruders/creality_base_extruder_0.def.json b/resources/extruders/creality_base_extruder_0.def.json
new file mode 100644
index 0000000000..a173d1c2fa
--- /dev/null
+++ b/resources/extruders/creality_base_extruder_0.def.json
@@ -0,0 +1,16 @@
+{
+ "version": 2,
+ "name": "Extruder 1",
+ "inherits": "fdmextruder",
+ "metadata": {
+ "machine": "creality_base",
+ "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/creatable_d3_extruder_0.def.json b/resources/extruders/creatable_d3_extruder_0.def.json
new file mode 100644
index 0000000000..7d45bb8e8a
--- /dev/null
+++ b/resources/extruders/creatable_d3_extruder_0.def.json
@@ -0,0 +1,16 @@
+{
+ "id": "creatable_d3_extruder_0",
+ "version": 2,
+ "name": "Extruder 1",
+ "inherits": "fdmextruder",
+ "metadata": {
+ "machine": "Creatable_D3",
+ "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/cubicon_3dp_110f_extruder_0.def.json b/resources/extruders/cubicon_3dp_110f_extruder_0.def.json
new file mode 100644
index 0000000000..9c854fd2a1
--- /dev/null
+++ b/resources/extruders/cubicon_3dp_110f_extruder_0.def.json
@@ -0,0 +1,27 @@
+{
+ "id": "cubicon_3dp_110f_extruder_0",
+ "version": 2,
+ "name": "Extruder 1",
+ "inherits": "fdmextruder",
+ "metadata": {
+ "machine": "cubicon_3dp_110f",
+ "position": "0"
+ },
+ "overrides": {
+ "extruder_nr": {
+ "default_value": 0
+ },
+ "machine_nozzle_size": {
+ "default_value": 0.4
+ },
+ "machine_nozzle_offset_x": {
+ "default_value": -15
+ },
+ "machine_nozzle_offset_y": {
+ "default_value": -5
+ },
+ "material_diameter": {
+ "default_value": 1.75
+ }
+ }
+}
\ No newline at end of file
diff --git a/resources/extruders/cubicon_3dp_210f_extruder_0.def.json b/resources/extruders/cubicon_3dp_210f_extruder_0.def.json
new file mode 100644
index 0000000000..8a8573760a
--- /dev/null
+++ b/resources/extruders/cubicon_3dp_210f_extruder_0.def.json
@@ -0,0 +1,27 @@
+{
+ "id": "cubicon_3dp_210f_extruder_0",
+ "version": 2,
+ "name": "Extruder 1",
+ "inherits": "fdmextruder",
+ "metadata": {
+ "machine": "cubicon_3dp_210f",
+ "position": "0"
+ },
+ "overrides": {
+ "extruder_nr": {
+ "default_value": 0
+ },
+ "machine_nozzle_size": {
+ "default_value": 0.4
+ },
+ "machine_nozzle_offset_x": {
+ "default_value": -7.25
+ },
+ "machine_nozzle_offset_y": {
+ "default_value": -5.82
+ },
+ "material_diameter": {
+ "default_value": 1.75
+ }
+ }
+}
\ No newline at end of file
diff --git a/resources/extruders/cubicon_3dp_310f_extruder_0.def.json b/resources/extruders/cubicon_3dp_310f_extruder_0.def.json
new file mode 100644
index 0000000000..4edbbd5a6c
--- /dev/null
+++ b/resources/extruders/cubicon_3dp_310f_extruder_0.def.json
@@ -0,0 +1,27 @@
+{
+ "id": "cubicon_3dp_310f_extruder_0",
+ "version": 2,
+ "name": "Extruder 1",
+ "inherits": "fdmextruder",
+ "metadata": {
+ "machine": "cubicon_3dp_310f",
+ "position": "0"
+ },
+ "overrides": {
+ "extruder_nr": {
+ "default_value": 0
+ },
+ "machine_nozzle_size": {
+ "default_value": 0.4
+ },
+ "machine_nozzle_offset_x": {
+ "default_value": -15
+ },
+ "machine_nozzle_offset_y": {
+ "default_value": -5
+ },
+ "material_diameter": {
+ "default_value": 1.75
+ }
+ }
+}
\ No newline at end of file
diff --git a/resources/extruders/deltabot_extruder_0.def.json b/resources/extruders/deltabot_extruder_0.def.json
index 43fce74fa5..e13d6a6ee3 100644
--- a/resources/extruders/deltabot_extruder_0.def.json
+++ b/resources/extruders/deltabot_extruder_0.def.json
@@ -11,6 +11,6 @@
"overrides": {
"extruder_nr": { "default_value": 0 },
"machine_nozzle_size": { "default_value": 0.5 },
- "material_diameter": { "default_value": 2.85 }
+ "material_diameter": { "default_value": 1.75 }
}
}
diff --git a/resources/extruders/deltacomb_extruder_0.def.json b/resources/extruders/deltacomb_extruder_0.def.json
old mode 100644
new mode 100755
index 046becfd82..64c512b7fe
--- a/resources/extruders/deltacomb_extruder_0.def.json
+++ b/resources/extruders/deltacomb_extruder_0.def.json
@@ -9,8 +9,10 @@
},
"overrides": {
- "extruder_nr": { "default_value": 0 },
- "machine_nozzle_size": { "default_value": 0.4 },
- "material_diameter": { "default_value": 1.75 }
+ "extruder_nr": { "default_value": 0 },
+ "machine_nozzle_size": { "default_value": 0.4 },
+ "material_diameter": { "default_value": 1.75 },
+ "machine_nozzle_offset_x": { "default_value": 0.0 },
+ "machine_nozzle_offset_y": { "default_value": 0.0 }
}
}
diff --git a/resources/extruders/deltacomb_extruder_1.def.json b/resources/extruders/deltacomb_extruder_1.def.json
new file mode 100755
index 0000000000..1657688482
--- /dev/null
+++ b/resources/extruders/deltacomb_extruder_1.def.json
@@ -0,0 +1,18 @@
+{
+ "id": "deltacomb_extruder_1",
+ "version": 2,
+ "name": "Extruder 2",
+ "inherits": "fdmextruder",
+ "metadata": {
+ "machine": "deltacomb",
+ "position": "1"
+ },
+
+ "overrides": {
+ "extruder_nr": { "default_value": 1 },
+ "machine_nozzle_size": { "default_value": 0.4 },
+ "material_diameter": { "default_value": 1.75 },
+ "machine_nozzle_offset_x": { "default_value": 0.0 },
+ "machine_nozzle_offset_y": { "default_value": 0.0 }
+ }
+}
diff --git a/resources/extruders/erzay3d_extruder_0.def.json b/resources/extruders/erzay3d_extruder_0.def.json
new file mode 100644
index 0000000000..65bf515263
--- /dev/null
+++ b/resources/extruders/erzay3d_extruder_0.def.json
@@ -0,0 +1,16 @@
+{
+ "id": "erzay3d_extruder_0",
+ "version": 2,
+ "name": "Extruder 1",
+ "inherits": "fdmextruder",
+ "metadata": {
+ "machine": "erzay3d",
+ "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/flsun_qq_extruder.def.json b/resources/extruders/flsun_qq_extruder.def.json
new file mode 100644
index 0000000000..7c93776836
--- /dev/null
+++ b/resources/extruders/flsun_qq_extruder.def.json
@@ -0,0 +1,15 @@
+{
+ "id": "flsun_qq_extruder",
+ "version": 2,
+ "name": "Extruder",
+ "inherits": "fdmextruder",
+ "metadata": {
+ "machine": "flsun_qq",
+ "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/flsun_qq_s_extruder_0.def.json b/resources/extruders/flsun_qq_s_extruder_0.def.json
new file mode 100644
index 0000000000..cba424e182
--- /dev/null
+++ b/resources/extruders/flsun_qq_s_extruder_0.def.json
@@ -0,0 +1,16 @@
+{
+ "id": "flsun_qq_s_extruder_0",
+ "version": 2,
+ "name": "Extruder 1",
+ "inherits": "fdmextruder",
+ "metadata": {
+ "machine": "flsun_qq_s",
+ "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/geeetech_a30_extruder_0.def.json b/resources/extruders/geeetech_a30_extruder_0.def.json
new file mode 100644
index 0000000000..bc1d6a6ed6
--- /dev/null
+++ b/resources/extruders/geeetech_a30_extruder_0.def.json
@@ -0,0 +1,16 @@
+{
+ "id": "geeetech_a30_extruder_0",
+ "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 b490f4a40e..d3146a0576 100644
--- a/resources/extruders/gmax15plus_dual_extruder_0.def.json
+++ b/resources/extruders/gmax15plus_dual_extruder_0.def.json
@@ -15,10 +15,10 @@
},
"machine_nozzle_offset_x": { "default_value": 0.0 },
"machine_nozzle_offset_y": { "default_value": 0.0 },
- "machine_nozzle_size": { "default_value": 0.5 },
+ "machine_nozzle_size": { "default_value": 0.5 },
"material_diameter": { "default_value": 1.75 },
-
- "machine_extruder_start_pos_abs": { "default_value": true },
+
+ "machine_extruder_start_pos_abs": { "default_value": true },
"machine_extruder_start_pos_x": { "value": 40 },
"machine_extruder_start_pos_y": { "value": 210 },
"machine_extruder_end_pos_abs": { "default_value": true },
diff --git a/resources/extruders/gmax15plus_dual_extruder_1.def.json b/resources/extruders/gmax15plus_dual_extruder_1.def.json
index ad3c628d6f..7b7354d794 100644
--- a/resources/extruders/gmax15plus_dual_extruder_1.def.json
+++ b/resources/extruders/gmax15plus_dual_extruder_1.def.json
@@ -15,10 +15,10 @@
},
"machine_nozzle_offset_x": { "default_value": 0.0 },
"machine_nozzle_offset_y": { "default_value": 0.0 },
- "machine_nozzle_size": { "default_value": 0.5 },
+ "machine_nozzle_size": { "default_value": 0.5 },
"material_diameter": { "default_value": 1.75 },
-
- "machine_extruder_start_pos_abs": { "default_value": true },
+
+ "machine_extruder_start_pos_abs": { "default_value": true },
"machine_extruder_start_pos_x": { "value": 40 },
"machine_extruder_start_pos_y": { "value": 210 },
"machine_extruder_end_pos_abs": { "default_value": true },
diff --git a/resources/extruders/grr_neo_extruder_0.def.json b/resources/extruders/grr_neo_extruder_0.def.json
index 9fe86d9eed..6d76c90796 100644
--- a/resources/extruders/grr_neo_extruder_0.def.json
+++ b/resources/extruders/grr_neo_extruder_0.def.json
@@ -11,6 +11,6 @@
"overrides": {
"extruder_nr": { "default_value": 0 },
"machine_nozzle_size": { "default_value": 0.5 },
- "material_diameter": { "default_value": 2.85 }
+ "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..c1e20140f3
--- /dev/null
+++ b/resources/extruders/hms434_tool_1.def.json
@@ -0,0 +1,26 @@
+{
+ "id": "hms434_tool_1",
+ "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..a2015006dc
--- /dev/null
+++ b/resources/extruders/hms434_tool_2.def.json
@@ -0,0 +1,26 @@
+{
+ "id": "hms434_tool_2",
+ "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..b0199d5523
--- /dev/null
+++ b/resources/extruders/hms434_tool_3.def.json
@@ -0,0 +1,26 @@
+{
+ "id": "hms434_tool_3",
+ "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..9346dafd67
--- /dev/null
+++ b/resources/extruders/hms434_tool_4.def.json
@@ -0,0 +1,26 @@
+{
+ "id": "hms434_tool_4",
+ "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..051227fb1b
--- /dev/null
+++ b/resources/extruders/hms434_tool_5.def.json
@@ -0,0 +1,26 @@
+{
+ "id": "hms434_tool_5",
+ "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..056bb66741
--- /dev/null
+++ b/resources/extruders/hms434_tool_6.def.json
@@ -0,0 +1,26 @@
+{
+ "id": "hms434_tool_6",
+ "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..ff8f938e1c
--- /dev/null
+++ b/resources/extruders/hms434_tool_7.def.json
@@ -0,0 +1,26 @@
+{
+ "id": "hms434_tool_7",
+ "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..2e9302e26c
--- /dev/null
+++ b/resources/extruders/hms434_tool_8.def.json
@@ -0,0 +1,26 @@
+{
+ "id": "hms434_tool_8",
+ "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..1d50297343
--- /dev/null
+++ b/resources/extruders/imade3d_jellybox_2_extruder_0.def.json
@@ -0,0 +1,16 @@
+{
+ "id": "imade3d_jellybox_2_extruder_0",
+ "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/jgaurora_a1_extruder_0.def.json b/resources/extruders/jgaurora_a1_extruder_0.def.json
new file mode 100644
index 0000000000..71742b734a
--- /dev/null
+++ b/resources/extruders/jgaurora_a1_extruder_0.def.json
@@ -0,0 +1,16 @@
+{
+ "id": "jgaurora_a1_extruder_0",
+ "version": 2,
+ "name": "Extruder 1",
+ "inherits": "fdmextruder",
+ "metadata": {
+ "machine": "jgaurora_a1",
+ "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
new file mode 100644
index 0000000000..fbc6ba77e6
--- /dev/null
+++ b/resources/extruders/jgaurora_a5_extruder_0.def.json
@@ -0,0 +1,16 @@
+{
+ "id": "jgaurora_a5_extruder_0",
+ "version": 2,
+ "name": "Extruder 1",
+ "inherits": "fdmextruder",
+ "metadata": {
+ "machine": "jgaurora_a5",
+ "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_jgmaker_magic_extruder_0.def.json b/resources/extruders/jgaurora_jgmaker_magic_extruder_0.def.json
new file mode 100644
index 0000000000..41593a4821
--- /dev/null
+++ b/resources/extruders/jgaurora_jgmaker_magic_extruder_0.def.json
@@ -0,0 +1,16 @@
+{
+ "id": "jgaurora_jgmaker_magic_extruder_0",
+ "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
new file mode 100644
index 0000000000..987425b28a
--- /dev/null
+++ b/resources/extruders/jgaurora_z_603s_extruder_0.def.json
@@ -0,0 +1,16 @@
+{
+ "id": "jgaurora_z_603s_extruder_0",
+ "version": 2,
+ "name": "Extruder 1",
+ "inherits": "fdmextruder",
+ "metadata": {
+ "machine": "jgaurora_z_603s",
+ "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/kupido_extruder_0.def.json b/resources/extruders/kupido_extruder_0.def.json
index d93395e667..ef988d4fde 100644
--- a/resources/extruders/kupido_extruder_0.def.json
+++ b/resources/extruders/kupido_extruder_0.def.json
@@ -11,6 +11,6 @@
"overrides": {
"extruder_nr": { "default_value": 0 },
"machine_nozzle_size": { "default_value": 0.4 },
- "material_diameter": { "default_value": 2.85 }
+ "material_diameter": { "default_value": 1.75 }
}
}
diff --git a/resources/extruders/makeR_pegasus_extruder_0.def.json b/resources/extruders/makeR_pegasus_extruder_0.def.json
index 8d2a98340a..e37891abde 100644
--- a/resources/extruders/makeR_pegasus_extruder_0.def.json
+++ b/resources/extruders/makeR_pegasus_extruder_0.def.json
@@ -11,6 +11,6 @@
"overrides": {
"extruder_nr": { "default_value": 0 },
"machine_nozzle_size": { "default_value": 0.4 },
- "material_diameter": { "default_value": 2.85 }
+ "material_diameter": { "default_value": 1.75 }
}
}
diff --git a/resources/extruders/maker_starter_extruder_0.def.json b/resources/extruders/maker_starter_extruder_0.def.json
index 5c60e536b7..ee94250248 100644
--- a/resources/extruders/maker_starter_extruder_0.def.json
+++ b/resources/extruders/maker_starter_extruder_0.def.json
@@ -11,6 +11,6 @@
"overrides": {
"extruder_nr": { "default_value": 0 },
"machine_nozzle_size": { "default_value": 0.4 },
- "material_diameter": { "default_value": 2.85 }
+ "material_diameter": { "default_value": 1.75 }
}
}
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 eef47c9b6f..e4a899d7af 100644
--- a/resources/extruders/monoprice_select_mini_v1_extruder_0.def.json
+++ b/resources/extruders/monoprice_select_mini_v1_extruder_0.def.json
@@ -11,6 +11,6 @@
"overrides": {
"extruder_nr": { "default_value": 0 },
"machine_nozzle_size": { "default_value": 0.4 },
- "material_diameter": { "default_value": 2.85 }
+ "material_diameter": { "default_value": 1.75 }
}
}
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 e0899304dd..b727cfce1f 100644
--- a/resources/extruders/monoprice_select_mini_v2_extruder_0.def.json
+++ b/resources/extruders/monoprice_select_mini_v2_extruder_0.def.json
@@ -11,6 +11,6 @@
"overrides": {
"extruder_nr": { "default_value": 0 },
"machine_nozzle_size": { "default_value": 0.4 },
- "material_diameter": { "default_value": 2.85 }
+ "material_diameter": { "default_value": 1.75 }
}
}
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..999fe37d28
--- /dev/null
+++ b/resources/extruders/nwa3d_a31_extruder_0.def.json
@@ -0,0 +1,16 @@
+{
+ "id": "nwa3d_a31_extruder_0",
+ "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
new file mode 100644
index 0000000000..5c3cc6a127
--- /dev/null
+++ b/resources/extruders/nwa3d_a5_extruder_0.def.json
@@ -0,0 +1,16 @@
+{
+ "id": "nwa3d_a5_extruder_0",
+ "version": 2,
+ "name": "Regular 0.4mm Nozzle",
+ "inherits": "fdmextruder",
+ "metadata": {
+ "machine": "nwa3d_a5",
+ "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/printrbot_play_heated_extruder_0.def.json b/resources/extruders/printrbot_play_heated_extruder_0.def.json
index ba8bc5c34c..0a3eeb3d06 100644
--- a/resources/extruders/printrbot_play_heated_extruder_0.def.json
+++ b/resources/extruders/printrbot_play_heated_extruder_0.def.json
@@ -11,6 +11,6 @@
"overrides": {
"extruder_nr": { "default_value": 0 },
"machine_nozzle_size": { "default_value": 0.4 },
- "material_diameter": { "default_value": 2.85 }
+ "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..8658944ebd
--- /dev/null
+++ b/resources/extruders/stereotech_start_extruder_0.def.json
@@ -0,0 +1,16 @@
+{
+ "id": "stereotech_start_extruder_0",
+ "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..ffbf5bde2f
--- /dev/null
+++ b/resources/extruders/stereotech_ste320_1st.def.json
@@ -0,0 +1,46 @@
+{
+ "id": "stereotech_ste320_1st",
+ "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..ae1b8f0f15
--- /dev/null
+++ b/resources/extruders/stereotech_ste320_2nd.def.json
@@ -0,0 +1,46 @@
+{
+ "id": "stereotech_ste320_2nd",
+ "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..1df8eb0ebb
--- /dev/null
+++ b/resources/extruders/strateo3d_left_extruder.def.json
@@ -0,0 +1,17 @@
+{
+ "id": "strateo3d_left_extruder",
+ "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..ea59870329
--- /dev/null
+++ b/resources/extruders/strateo3d_right_extruder.def.json
@@ -0,0 +1,17 @@
+{
+ "id": "strateo3d_right_extruder",
+ "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
new file mode 100644
index 0000000000..8436dc0a94
--- /dev/null
+++ b/resources/extruders/structur3d_discov3ry1_complete_um2plus_extruder_0.def.json
@@ -0,0 +1,16 @@
+{
+ "id": "structur3d_discov3ry1_complete_um2plus_extruder_0",
+ "version": 2,
+ "name": "Discov3ry Extruder",
+ "inherits": "fdmextruder",
+ "metadata": {
+ "machine": "structur3d_discov3ry1_complete_um2plus",
+ "position": "0"
+ },
+
+ "overrides": {
+ "extruder_nr": { "default_value": 0 },
+ "machine_nozzle_size": { "default_value": 0.84 },
+ "material_diameter": { "default_value": 3.175 }
+ }
+}
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..59e9311e50
--- /dev/null
+++ b/resources/extruders/tizyx_evy_dual_extruder_0.def.JSON
@@ -0,0 +1,18 @@
+{
+ "id": "tizyx_evy_dual_extruder_0",
+ "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..cf5dc76caa
--- /dev/null
+++ b/resources/extruders/tizyx_evy_dual_extruder_1.def.JSON
@@ -0,0 +1,18 @@
+{
+ "id": "tizyx_evy_dual_extruder_1",
+ "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
new file mode 100644
index 0000000000..bd3c4c9792
--- /dev/null
+++ b/resources/extruders/tizyx_evy_extruder_0.def.JSON
@@ -0,0 +1,18 @@
+{
+ "id": "tizyx_evy_extruder_0",
+ "version": 2,
+ "name": "Extruder 1",
+ "inherits": "fdmextruder",
+ "metadata": {
+ "machine": "tizyx_evy",
+ "position": "0"
+ },
+
+ "overrides": {
+ "extruder_nr": {
+ "default_value": 0,
+ "maximum_value": "0"
+ },
+ "material_diameter": { "default_value": 1.75 }
+ }
+}
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_d9_extruder_0.def.json b/resources/extruders/wanhao_d9_extruder_0.def.json
new file mode 100644
index 0000000000..76d501e5a2
--- /dev/null
+++ b/resources/extruders/wanhao_d9_extruder_0.def.json
@@ -0,0 +1,16 @@
+{
+ "id": "wanhao_d9_extruder_0",
+ "version": 2,
+ "name": "Extruder 1",
+ "inherits": "fdmextruder",
+ "metadata": {
+ "machine": "wanhao_d9",
+ "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/z-bolt_extruder_0.def.json b/resources/extruders/z-bolt_extruder_0.def.json
new file mode 100644
index 0000000000..70e9f6177c
--- /dev/null
+++ b/resources/extruders/z-bolt_extruder_0.def.json
@@ -0,0 +1,15 @@
+{
+ "id": "z-bolt_extruder_0",
+ "version": 2,
+ "name": "Extruder 1",
+ "inherits": "fdmextruder",
+ "metadata": {
+ "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/i18n/cura.pot b/resources/i18n/cura.pot
index 2fe966fe99..8acdb06149 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: 2018-09-19 17:07+0200\n"
+"POT-Creation-Date: 2019-07-16 14:38+0200\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:27
msgctxt "@action"
msgid "Machine Settings"
msgstr ""
@@ -48,15 +48,15 @@ msgstr ""
#: /home/ruben/Projects/Cura/plugins/GCodeWriter/GCodeWriter.py:73
#: /home/ruben/Projects/Cura/plugins/GCodeWriter/GCodeWriter.py:89
msgctxt "@warning:status"
-msgid "Please generate G-code before saving."
+msgid "Please prepare G-code before exporting."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/ModelChecker/ModelChecker.py:30
+#: /home/ruben/Projects/Cura/plugins/ModelChecker/ModelChecker.py:31
msgctxt "@info:title"
msgid "3D Model Assistant"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/ModelChecker/ModelChecker.py:80
+#: /home/ruben/Projects/Cura/plugins/ModelChecker/ModelChecker.py:90
#, python-brace-format
msgctxt "@info:status"
msgid ""
@@ -69,9 +69,9 @@ msgid ""
"guide
"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/ChangeLogPlugin/ChangeLog.py:32
-msgctxt "@item:inmenu"
-msgid "Show Changelog"
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.py:25
+msgctxt "@action"
+msgid "Update Firmware"
msgstr ""
#: /home/ruben/Projects/Cura/plugins/ProfileFlattener/ProfileFlattener.py:23
@@ -84,38 +84,37 @@ msgctxt "@info:status"
msgid "Profile has been flattened & activated."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:40
+#: /home/ruben/Projects/Cura/plugins/AMFReader/__init__.py:15
+msgctxt "@item:inlistbox"
+msgid "AMF File"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:37
msgctxt "@item:inmenu"
msgid "USB printing"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:41
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:38
msgctxt "@action:button Preceded by 'Ready to'."
msgid "Print via USB"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:42
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:39
msgctxt "@info:tooltip"
msgid "Print via USB"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:83
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:75
msgctxt "@info:status"
msgid "Connected via USB"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:103
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:100
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 ""
-
#: /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"
@@ -126,6 +125,11 @@ msgctxt "X3g Writer File Description"
msgid "X3g File"
msgstr ""
+#: /home/ruben/Projects/Cura/plugins/X3GWriter/__init__.py:15
+msgctxt "X3G Writer File Description"
+msgid "X3G File"
+msgstr ""
+
#: /home/ruben/Projects/Cura/plugins/GCodeGzWriter/__init__.py:17
#: /home/ruben/Projects/Cura/plugins/GCodeGzReader/__init__.py:17
msgctxt "@item:inlistbox"
@@ -137,7 +141,8 @@ msgctxt "@error:not supported"
msgid "GCodeGzWriter does not support text mode."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UFPWriter/__init__.py:38
+#: /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 ""
@@ -159,7 +164,7 @@ msgid "Save to Removable Drive {0}"
msgstr ""
#: /home/ruben/Projects/Cura/plugins/RemovableDriveOutputDevice/RemovableDriveOutputDevice.py:64
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:131
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/MeshFormatHandler.py:106
msgctxt "@info:status"
msgid "There are no file formats available to write with!"
msgstr ""
@@ -196,9 +201,10 @@ msgid "Could not save to removable drive {0}: {1}"
msgstr ""
#: /home/ruben/Projects/Cura/plugins/RemovableDriveOutputDevice/RemovableDriveOutputDevice.py:137
-#: /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:1567
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py:188
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:134
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:141
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1622
msgctxt "@info:title"
msgid "Error"
msgstr ""
@@ -227,8 +233,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/CuraApplication.py:1557
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1651
+#: /home/ruben/Projects/Cura/cura/OAuth2/AuthorizationService.py:197
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1612
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1712
msgctxt "@info:title"
msgid "Warning"
msgstr ""
@@ -255,115 +262,109 @@ 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:86
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:75
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:93
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:87
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:76
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:94
msgctxt "@properties:tooltip"
msgid "Print over network"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:88
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:95
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 ""
+"Connected over the network. Please approve the access request on the printer."
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:100
+msgctxt "@info:status"
+msgid "Connected over the network. No access to control the printer."
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:105
+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
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:108
msgctxt "@info:title"
msgid "Authentication status"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:103
-msgctxt "@info:status"
-msgid ""
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:104
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:110
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:114
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:116
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:120
msgctxt "@info:title"
msgid "Authentication Status"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:105
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:111
+#: /home/ruben/Projects/Cura/cura/OAuth2/AuthorizationService.py:198
msgctxt "@action:button"
msgid "Retry"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:106
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:112
msgctxt "@info:tooltip"
msgid "Re-send the access request"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:109
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:115
msgctxt "@info:status"
msgid "Access to the printer accepted"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:113
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:119
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:115
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/UM3InfoComponents.qml:29
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/UM3InfoComponents.qml:73
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:121
+#: /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:117
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/UM3InfoComponents.qml:28
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/UM3InfoComponents.qml:72
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:123
+#: /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:202
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:208
msgctxt "@label"
msgid "Unable to start a new print job."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:204
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:210
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:210
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:232
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:216
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:238
msgctxt "@window:title"
msgid "Mismatched configuration"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:224
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:230
msgctxt "@label"
msgid "Are you sure you wish to print with the selected configuration?"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:226
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:232
msgctxt "@label"
msgid ""
"There is a mismatch between the configuration or calibration of the printer "
@@ -371,55 +372,58 @@ msgid ""
"that are inserted in your printer."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:253
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:197
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:259
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:176
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:181
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:260
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:216
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:232
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:266
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:194
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:211
msgctxt "@info:status"
msgid "Sending data to printer"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:261
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:217
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:233
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:267
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:196
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:213
msgctxt "@info:title"
msgid "Sending Data"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:262
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:234
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxProgressButton.qml:18
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxConfirmUninstallResetDialog.qml:80
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:378
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintWindow.qml:92
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/MoreInfoWindow.qml:143
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:268
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:214
+#: /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:410
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintWindow.qml:20
+#: /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:391
-#: /home/ruben/Projects/Cura/resources/qml/OpenFilesIncludingProjectsDialog.qml:87
-#: /home/ruben/Projects/Cura/resources/qml/WorkspaceSummaryDialog.qml:279
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/OpenFilesIncludingProjectsDialog.qml:87
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:283
msgctxt "@action:button"
msgid "Cancel"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:325
-#, python-brace-format
-msgctxt "@info:status"
-msgid "No Printcore loaded in slot {slot_number}"
-msgstr ""
-
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:331
#, python-brace-format
msgctxt "@info:status"
+msgid "No Printcore loaded in slot {slot_number}"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:337
+#, python-brace-format
+msgctxt "@info:status"
msgid "No material loaded in slot {slot_number}"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:354
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:360
#, python-brace-format
msgctxt "@label"
msgid ""
@@ -427,23 +431,23 @@ msgid ""
"{remote_printcore_name}) selected for extruder {extruder_id}"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:363
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:369
#, 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:549
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:555
msgctxt "@window:title"
msgid "Sync with your printer"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:551
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:557
msgctxt "@label"
msgid "Would you like to use your current printer configuration in Cura?"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:553
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:559
msgctxt "@label"
msgid ""
"The PrintCores and/or materials on your printer differ from those within "
@@ -451,54 +455,170 @@ msgid ""
"and materials that are inserted in your printer."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:89
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:96
msgctxt "@info:status"
msgid "Connected over the network"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:310
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:289
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:370
msgctxt "@info:status"
msgid "Print job was successfully sent to the printer."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:312
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:291
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:371
msgctxt "@info:title"
msgid "Data Sent"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:313
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:292
msgctxt "@action:button"
msgid "View in Monitor"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:420
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:411
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:318
#, python-brace-format
msgctxt "@info:status"
msgid "Printer '{printer_name}' has finished printing '{job_name}'."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:422
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:413
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:322
#, python-brace-format
msgctxt "@info:status"
msgid "The print job '{job_name}' was finished."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:423
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:414
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:316
msgctxt "@info:status"
msgid "Print finished"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/DiscoverUM3Action.py:26
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:595
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:629
+msgctxt "@label:material"
+msgid "Empty"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:596
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:630
+msgctxt "@label:material"
+msgid "Unknown"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:169
+msgctxt "@action:button"
+msgid "Print via Cloud"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:170
+msgctxt "@properties:tooltip"
+msgid "Print via Cloud"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:171
+msgctxt "@info:status"
+msgid "Connected via Cloud"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:182
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:359
+msgctxt "@info:title"
+msgid "Cloud error"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:199
+msgctxt "@info:status"
+msgid "Could not export print job."
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:358
+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:187
+msgctxt "@info:description"
+msgid "There was an error connecting to the cloud."
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudProgressMessage.py:14
+msgctxt "@info:status"
+msgid "Sending Print Job"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudProgressMessage.py:15
+msgctxt "@info:status"
+msgid "Uploading via Ultimaker Cloud"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py:621
+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:627
+msgctxt ""
+"@info:status Ultimaker Cloud is a brand name and shouldn't be translated."
+msgid "Connect to Ultimaker Cloud"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py:628
+msgctxt "@action"
+msgid "Don't ask me again for this printer."
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py:631
+msgctxt "@action"
+msgid "Get started"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py:637
+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:643
+msgctxt "@info:status"
+msgid "Connected!"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py:645
+msgctxt "@action"
+msgid "Review your connection"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/DiscoverUM3Action.py:30
msgctxt "@action"
msgid "Connect via Network"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/MonitorStage/__init__.py:12
+#: /home/ruben/Projects/Cura/plugins/MonitorStage/__init__.py:14
msgctxt "@item:inmenu"
msgid "Monitor"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py:68
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py:118
+msgctxt "@info"
+msgid "Could not access update information."
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerMessage.py:17
#, python-brace-format
msgctxt ""
"@info Don't translate {machine_name}, since it gets replaced by a printer "
@@ -508,38 +628,39 @@ msgid ""
"update the firmware on your printer."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py:72
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerMessage.py:21
#, python-format
msgctxt "@info:title The %s gets replaced with the printer name."
msgid "New %s firmware available"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py:75
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerMessage.py:27
msgctxt "@action:button"
msgid "How to update"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py:91
-msgctxt "@info"
-msgid "Could not access update information."
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/SimulationView/__init__.py:14
+#: /home/ruben/Projects/Cura/plugins/SimulationView/__init__.py:15
msgctxt "@item:inlistbox"
msgid "Layer view"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.py:102
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.py:114
msgctxt "@info:status"
msgid "Cura does not accurately display layers when Wire Printing is enabled"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.py:103
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.py:115
msgctxt "@info:title"
msgid "Simulation View"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.py:28
+#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.py:35
+msgctxt "@item:inmenu"
+msgid "Post Processing"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.py:36
+msgctxt "@item:inmenu"
msgid "Modify G-Code"
msgstr ""
@@ -553,39 +674,6 @@ msgctxt "@info:tooltip"
msgid "Create a volume in which supports are not printed."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/SliceInfo.py:43
-msgctxt "@info"
-msgid "Cura collects anonymized usage statistics."
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/SliceInfo.py:46
-msgctxt "@info:title"
-msgid "Collecting Data"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/SliceInfo.py:48
-msgctxt "@action:button"
-msgid "More info"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/SliceInfo.py:49
-msgctxt "@action:tooltip"
-msgid "See more information on what data Cura sends."
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/SliceInfo.py:51
-msgctxt "@action:button"
-msgid "Allow"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/SliceInfo.py:52
-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"
@@ -616,24 +704,24 @@ msgctxt "@item:inlistbox"
msgid "GIF Image"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:333
+#: /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:333
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:364
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:388
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:397
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:406
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:415
+#: /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:363
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:361
#, python-brace-format
msgctxt "@info:status"
msgid ""
@@ -641,7 +729,7 @@ msgid ""
"errors: {0}"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:387
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:385
#, python-brace-format
msgctxt "@info:status"
msgid ""
@@ -649,13 +737,13 @@ msgid ""
"errors on one or more models: {error_labels}"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:396
+#: /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:405
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:403
#, python-format
msgctxt "@info:status"
msgid ""
@@ -663,20 +751,21 @@ msgid ""
"%s."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:414
+#: /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. Please "
-"scale or rotate models to fit."
+"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:49
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py:242
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py:50
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py:256
msgctxt "@info:status"
msgid "Processing Layers"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py:242
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py:256
msgctxt "@info:title"
msgid "Information"
msgstr ""
@@ -692,13 +781,11 @@ msgid "Configure Per Model Settings"
msgstr ""
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.py:175
-#: /home/ruben/Projects/Cura/resources/qml/PrepareSidebar.qml:576
msgctxt "@title:tab"
msgid "Recommended"
msgstr ""
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.py:177
-#: /home/ruben/Projects/Cura/resources/qml/PrepareSidebar.qml:581
msgctxt "@title:tab"
msgid "Custom"
msgstr ""
@@ -709,13 +796,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:711
+#: /home/ruben/Projects/Cura/plugins/3MFReader/ThreeMFWorkspaceReader.py:191
+#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:775
msgctxt "@label"
msgid "Nozzle"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/3MFReader/ThreeMFWorkspaceReader.py:468
+#: /home/ruben/Projects/Cura/plugins/3MFReader/ThreeMFWorkspaceReader.py:474
#, python-brace-format
msgctxt "@info:status Don't translate the XML tags or !"
msgid ""
@@ -724,7 +811,7 @@ msgid ""
"instead."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/3MFReader/ThreeMFWorkspaceReader.py:471
+#: /home/ruben/Projects/Cura/plugins/3MFReader/ThreeMFWorkspaceReader.py:477
msgctxt "@info:title"
msgid "Open Project File"
msgstr ""
@@ -739,24 +826,67 @@ msgctxt "@item:inlistbox"
msgid "G File"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:317
+#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:328
msgctxt "@info:status"
msgid "Parsing G-code"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:319
-#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:466
+#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:330
+#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:483
msgctxt "@info:title"
msgid "G-code Details"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:464
+#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:481
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 ""
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/DrivePluginExtension.py:64
+msgctxt "@item:inmenu"
+msgid "Manage backups"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/DrivePluginExtension.py:107
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/DrivePluginExtension.py:113
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/DriveApiService.py:55
+#: /home/ruben/Projects/Cura/cura/Backups/Backup.py:104
+msgctxt "@info:title"
+msgid "Backup"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/DriveApiService.py:55
+msgctxt "@info:backup_status"
+msgid "There was an error listing your backups."
+msgstr ""
+
+#: /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 ""
+
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/UploadBackupJob.py:15
+msgctxt "@info:title"
+msgid "Backups"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/UploadBackupJob.py:27
+msgctxt "@info:backup_status"
+msgid "Uploading your backup..."
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/UploadBackupJob.py:36
+msgctxt "@info:backup_status"
+msgid "There was an error while uploading your backup."
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/UploadBackupJob.py:39
+msgctxt "@info:backup_status"
+msgid "Your backup has finished uploading."
+msgstr ""
+
#: /home/ruben/Projects/Cura/plugins/CuraProfileWriter/__init__.py:14
#: /home/ruben/Projects/Cura/plugins/CuraProfileReader/__init__.py:14
msgctxt "@item:inlistbox"
@@ -768,7 +898,7 @@ msgctxt "@item:inmenu"
msgid "Profile Assistant"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/__init__.py:17
+#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/__init__.py:18
msgctxt "@item:inlistbox"
msgid "Profile Assistant"
msgstr ""
@@ -788,101 +918,40 @@ msgctxt "@error:zip"
msgid "Error writing 3mf file."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UM2UpgradeSelection.py:17
+#: /home/ruben/Projects/Cura/plugins/PreviewStage/__init__.py:13
+msgctxt "@item:inmenu"
+msgid "Preview"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UM2UpgradeSelection.py:19
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOUpgradeSelection.py:18
msgctxt "@action"
msgid "Select upgrades"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UpgradeFirmwareMachineAction.py:12
-msgctxt "@action"
-msgid "Upgrade Firmware"
-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:98
-msgctxt "@tooltip"
-msgid "Outer Wall"
+#: /home/ruben/Projects/Cura/cura/API/Account.py:82
+msgctxt "@info:title"
+msgid "Login failed"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:99
-msgctxt "@tooltip"
-msgid "Inner Walls"
+#: /home/ruben/Projects/Cura/cura/Settings/cura_empty_instance_containers.py:33
+msgctxt "@info:not supported profile"
+msgid "Not supported"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:100
-msgctxt "@tooltip"
-msgid "Skin"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:101
-msgctxt "@tooltip"
-msgid "Infill"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:102
-msgctxt "@tooltip"
-msgid "Support Infill"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:103
-msgctxt "@tooltip"
-msgid "Support Interface"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:104
-msgctxt "@tooltip"
-msgid "Support"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:105
-msgctxt "@tooltip"
-msgid "Skirt"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:106
-msgctxt "@tooltip"
-msgid "Travel"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:107
-msgctxt "@tooltip"
-msgid "Retractions"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:108
-msgctxt "@tooltip"
-msgid "Other"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:229
-msgctxt "@label unknown material"
-msgid "Unknown"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:314
-#, python-brace-format
-msgctxt "@label"
-msgid "Pre-sliced file {0}"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:186
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:121
+#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:203
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:122
msgctxt "@title:window"
msgid "File Already Exists"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:187
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:122
+#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:204
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:123
#, python-brace-format
msgctxt "@label Don't translate the XML tag !"
msgid ""
@@ -890,44 +959,36 @@ msgid ""
"overwrite it?"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/Settings/ExtrudersModel.py:212
-msgctxt "@menuitem"
-msgid "Not overridden"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:120
+#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:427
+#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:430
msgctxt "@info:status"
+msgid "Invalid file URL:"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:925
+msgctxt "@info:message Followed by a list of settings."
msgid ""
-"The selected material is incompatible with the selected machine or "
-"configuration."
+"Settings have been changed to match the current availability of extruders:"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:121
-msgctxt "@info:title"
-msgid "Incompatible Material"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:863
-#, 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:865
+#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:927
msgctxt "@info:title"
msgid "Settings updated"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:131
+#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:1481
+msgctxt "@info:title"
+msgid "Extruder(s) Disabled"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:132
#, 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:139
#, python-brace-format
msgctxt "@info:status Don't translate the XML tag !"
msgid ""
@@ -935,98 +996,198 @@ msgid ""
"failure."
msgstr ""
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:143
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:144
#, 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:145
msgctxt "@info:title"
msgid "Export succeeded"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:170
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:194
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:313
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:172
#, python-brace-format
-msgctxt "@info:status Don't translate the XML tags or !"
-msgid ""
-"Failed to import profile from {0}: {1}"
-"message>"
+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:190
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:176
#, python-brace-format
-msgctxt "@info:status Don't translate the XML tags or !"
+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:192
+#, 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:218
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:228
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:196
#, python-brace-format
-msgctxt "@info:status Don't translate the XML tags or !"
+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:220
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:230
+#, 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:243
#, python-brace-format
-msgctxt "@info:status Don't translate the XML tags or !"
+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:316
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:315
+#, python-brace-format
+msgctxt "@info:status Don't translate the XML tags or !"
+msgid "Failed to import profile from {0}:"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:318
#, 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:321
#, 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:324
#, 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:359
msgctxt "@label"
msgid "Custom profile"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:356
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:375
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:389
#, 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:59
+#: /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:306
+#, python-brace-format
+msgctxt "@label"
+msgid "Pre-sliced file {0}"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/cura/UI/WelcomePagesModel.py:56
+#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/ProfileCreatorTabControls.qml:62
+msgctxt "@action:button"
+msgid "Next"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/cura/UI/ObjectsModel.py:61
#, 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/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:124
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:168
+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:91
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:48
+msgctxt "@action:button"
+msgid "Add"
+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:109
@@ -1040,47 +1201,81 @@ msgctxt "@item:inlistbox"
msgid "All Files (*)"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/Machines/MaterialManager.py:609
+#: /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
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:269
+msgctxt "@label"
+msgid "Unknown"
+msgstr ""
+
+#: /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/Machines/MaterialManager.py:689
msgctxt "@label"
msgid "Custom Material"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/Machines/MaterialManager.py:610
+#: /home/ruben/Projects/Cura/cura/Machines/MaterialManager.py:690
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/ConfigurationMenu.qml:203
msgctxt "@label"
msgid "Custom"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/BuildVolume.py:81
+#: /home/ruben/Projects/Cura/cura/BuildVolume.py:89
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:91
msgctxt "@info:title"
msgid "Build Volume"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/Backups/Backup.py:97
+#: /home/ruben/Projects/Cura/cura/Backups/Backup.py:99
msgctxt "@info:backup_failed"
msgid "Could not create archive from user data directory: {}"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/Backups/Backup.py:102
-msgctxt "@info:title"
-msgid "Backup"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/cura/Backups/Backup.py:112
+#: /home/ruben/Projects/Cura/cura/Backups/Backup.py:114
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:122
+#: /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/AuthorizationHelpers.py:79
+msgctxt "@message"
+msgid "Could not read response."
+msgstr ""
+
+#: /home/ruben/Projects/Cura/cura/OAuth2/AuthorizationService.py:197
+msgctxt "@info"
+msgid "Unable to reach the Ultimaker account server."
+msgstr ""
+
+#: /home/ruben/Projects/Cura/cura/OAuth2/AuthorizationRequestHandler.py:66
+msgctxt "@message"
+msgid "Please give the required permissions when authorizing this application."
+msgstr ""
+
+#: /home/ruben/Projects/Cura/cura/OAuth2/AuthorizationRequestHandler.py:73
+msgctxt "@message"
+msgid "Something unexpected happened when trying to log in, please try again."
msgstr ""
#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:27
@@ -1089,42 +1284,46 @@ msgid "Multiplying and placing objects"
msgstr ""
#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:28
+msgctxt "@info:title"
+msgid "Placing Objects"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:100
+#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsJob.py:103
+#: /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
msgctxt "@info:title"
msgid "Placing Object"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:100
-#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsJob.py:96
-#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsAllBuildPlatesJob.py:150
-msgctxt "@info:status"
-msgid "Unable to find a location within the build volume for all objects"
-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:97
-#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsAllBuildPlatesJob.py:151
+#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsJob.py:104
+#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsAllBuildPlatesJob.py:150
msgctxt "@info:title"
msgid "Can't Find Location"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/CrashHandler.py:87
+#: /home/ruben/Projects/Cura/cura/CrashHandler.py:83
msgctxt "@title:window"
msgid "Cura can't start"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/CrashHandler.py:93
+#: /home/ruben/Projects/Cura/cura/CrashHandler.py:89
msgctxt "@label crash message"
msgid ""
"
"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/CrashHandler.py:222
+#: /home/ruben/Projects/Cura/cura/CrashHandler.py:218
msgctxt "@title:groupbox"
msgid "Error traceback"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/CrashHandler.py:303
+#: /home/ruben/Projects/Cura/cura/CrashHandler.py:299
msgctxt "@title:groupbox"
msgid "Logs"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/CrashHandler.py:326
+#: /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:345
+#: /home/ruben/Projects/Cura/cura/CrashHandler.py:342
msgctxt "@action:button"
msgid "Send report"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:454
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:504
msgctxt "@info:progress"
msgid "Loading machines..."
msgstr ""
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:748
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:819
msgctxt "@info:progress"
msgid "Setting up scene..."
msgstr ""
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:784
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:854
msgctxt "@info:progress"
msgid "Loading interface..."
msgstr ""
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:997
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1133
#, python-format
msgctxt ""
"@info 'width', 'depth' and 'height' are variable names that must NOT be "
@@ -1275,229 +1476,176 @@ msgctxt ""
msgid "%(width).1f x %(depth).1f x %(height).1f mm"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1556
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1611
#, 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:1566
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1621
#, 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:1650
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1711
msgctxt "@info:status"
msgid "The selected model was too small to load."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:61
-msgctxt "@title"
-msgid "Machine Settings"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:80
-msgctxt "@title:tab"
-msgid "Printer"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:99
-msgctxt "@label"
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:58
+msgctxt "@title:label"
msgid "Printer Settings"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:110
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:72
msgctxt "@label"
msgid "X (Width)"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:111
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:121
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:131
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:237
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:386
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:402
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:420
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:432
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:857
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:76
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:90
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:104
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:194
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:213
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:232
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:253
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:272
+#: /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:120
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:86
msgctxt "@label"
msgid "Y (Depth)"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:130
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:100
msgctxt "@label"
msgid "Z (Height)"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:142
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:114
msgctxt "@label"
msgid "Build plate shape"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:151
-msgctxt "@option:check"
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:127
+msgctxt "@label"
msgid "Origin at center"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:159
-msgctxt "@option:check"
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:139
+msgctxt "@label"
msgid "Heated bed"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:170
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:151
msgctxt "@label"
msgid "G-code flavor"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:183
-msgctxt "@label"
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:176
+msgctxt "@title:label"
msgid "Printhead Settings"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:193
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:190
msgctxt "@label"
msgid "X min"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:194
-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:203
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:209
msgctxt "@label"
msgid "Y min"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:204
-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:213
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:228
msgctxt "@label"
msgid "X max"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:214
-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:223
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:249
msgctxt "@label"
msgid "Y max"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:224
-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:236
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:268
msgctxt "@label"
-msgid "Gantry height"
+msgid "Gantry Height"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:238
-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:257
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:282
msgctxt "@label"
msgid "Number of Extruders"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:313
-msgctxt "@label"
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:341
+msgctxt "@title:label"
msgid "Start G-code"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:323
-msgctxt "@tooltip"
-msgid "G-code commands to be executed at the very start."
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:332
-msgctxt "@label"
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:355
+msgctxt "@title:label"
msgid "End G-code"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:342
-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:373
-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:385
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsExtruderTab.qml:75
msgctxt "@label"
msgid "Nozzle size"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:401
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsExtruderTab.qml:89
msgctxt "@label"
msgid "Compatible material diameter"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:403
-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:419
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsExtruderTab.qml:105
msgctxt "@label"
msgid "Nozzle offset X"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:431
+#: /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/MachineSettingsExtruderTab.qml:162
+msgctxt "@title:label"
msgid "Extruder Start G-code"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:470
-msgctxt "@label"
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsExtruderTab.qml:176
+msgctxt "@title:label"
msgid "Extruder End G-code"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxProgressButton.qml:17
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxProgressButton.qml:18
msgctxt "@action:button"
msgid "Install"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxProgressButton.qml:19
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxProgressButton.qml:20
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailTileActions.qml:46
msgctxt "@action:button"
msgid "Installed"
msgstr ""
@@ -1508,67 +1656,81 @@ msgid ""
"Could not connect to the Cura Package database. Please check your connection."
msgstr ""
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/SmallRatingWidget.qml:27
+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:26
+#: /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:75
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:66
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:544
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledPage.qml:70
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxHeader.qml:44
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:80
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:417
msgctxt "@title:tab"
msgid "Materials"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml:80
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml:91
+msgctxt "@label"
+msgid "Your rating"
+msgstr ""
+
+#: /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:86
+#: /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:92
+#: /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:98
+#: /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:117
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml:159
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:255
-msgctxt "@label"
-msgid "Unknown"
+#: /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:44
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml:30
+#: /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:45
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml:31
+#: /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:46
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml:32
+#: /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"
msgstr ""
#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/Toolbox.qml:13
msgctxt "@title"
-msgid "Toolbox"
+msgid "Marketplace"
msgstr ""
#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxBackColumn.qml:25
@@ -1578,7 +1740,7 @@ msgstr ""
#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxConfirmUninstallResetDialog.qml:20
msgctxt "@title:window"
-msgid "Confirm uninstall "
+msgid "Confirm uninstall"
msgstr ""
#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxConfirmUninstallResetDialog.qml:50
@@ -1598,17 +1760,27 @@ msgctxt "@text:window"
msgid "Profiles"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxConfirmUninstallResetDialog.qml:89
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxConfirmUninstallResetDialog.qml:90
msgctxt "@action:button"
msgid "Confirm"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxFooter.qml:17
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/RatingWidget.qml:54
+msgctxt "@label"
+msgid "You need to login first before you can rate"
+msgstr ""
+
+#: /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 ""
+
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxFooter.qml:19
msgctxt "@info"
msgid "You will need to restart Cura before changes in packages have effect."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxFooter.qml:34
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxFooter.qml:45
msgctxt "@info:button"
msgid "Quit Cura"
msgstr ""
@@ -1628,22 +1800,27 @@ msgctxt "@label"
msgid "Generic Materials"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxHeader.qml:54
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxHeader.qml:59
msgctxt "@title:tab"
msgid "Installed"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml:19
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml:22
msgctxt "@label"
msgid "Will install upon restarting"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml:51
+#: /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 ""
+
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml:71
msgctxt "@action:button"
msgid "Downgrade"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml:51
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml:71
msgctxt "@action:button"
msgid "Uninstall"
msgstr ""
@@ -1661,12 +1838,12 @@ msgid ""
"Do you agree with the terms below?"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxLicenseDialog.qml:54
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxLicenseDialog.qml:55
msgctxt "@action:button"
msgid "Accept"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxLicenseDialog.qml:65
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxLicenseDialog.qml:66
msgctxt "@action:button"
msgid "Decline"
msgstr ""
@@ -1676,22 +1853,42 @@ msgctxt "@label"
msgid "Featured"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:31
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:66
msgctxt "@label"
msgid "Compatibility"
msgstr ""
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:203
+msgctxt "@action:label"
+msgid "Technical Data Sheet"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:212
+msgctxt "@action:label"
+msgid "Safety Data Sheet"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:221
+msgctxt "@action:label"
+msgid "Printing Guidelines"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:230
+msgctxt "@action:label"
+msgid "Website"
+msgstr ""
+
#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxLoadingPage.qml:16
msgctxt "@info"
msgid "Fetching packages..."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxAuthorPage.qml:88
+#: /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:94
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxAuthorPage.qml:98
msgctxt "@label"
msgid "Email"
msgstr ""
@@ -1703,427 +1900,613 @@ msgid ""
"adjustment."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/ChangeLogPlugin/ChangeLog.qml:18
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:31
+msgctxt "@title"
+msgid "Update Firmware"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:39
msgctxt "@label"
-msgid "Changelog"
+msgid ""
+"Firmware is the piece of software running directly on your 3D printer. This "
+"firmware controls the step motors, regulates the temperature and ultimately "
+"makes your printer work."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/ChangeLogPlugin/ChangeLog.qml:37
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/FirmwareUpdateWindow.qml:84
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/UM3InfoComponents.qml:56
-#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.qml:464
-#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:508
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:121
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:148
-#: /home/ruben/Projects/Cura/resources/qml/EngineLog.qml:38
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:46
+msgctxt "@label"
+msgid ""
+"The firmware shipping with new printers works, but new versions tend to have "
+"more features and improvements."
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:58
msgctxt "@action:button"
-msgid "Close"
+msgid "Automatically upgrade Firmware"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/FirmwareUpdateWindow.qml:22
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:69
+msgctxt "@action:button"
+msgid "Upload custom Firmware"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:83
+msgctxt "@label"
+msgid ""
+"Firmware can not be updated because there is no connection with the printer."
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:91
+msgctxt "@label"
+msgid ""
+"Firmware can not be updated because the connection with the printer does not "
+"support upgrading firmware."
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:98
+msgctxt "@title:window"
+msgid "Select custom firmware"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:119
msgctxt "@title:window"
msgid "Firmware Update"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/FirmwareUpdateWindow.qml:42
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:143
msgctxt "@label"
msgid "Updating firmware."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/FirmwareUpdateWindow.qml:44
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:145
msgctxt "@label"
msgid "Firmware update completed."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/FirmwareUpdateWindow.qml:46
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:147
msgctxt "@label"
msgid "Firmware update failed due to an unknown error."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/FirmwareUpdateWindow.qml:48
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:149
msgctxt "@label"
msgid "Firmware update failed due to an communication error."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/FirmwareUpdateWindow.qml:50
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:151
msgctxt "@label"
msgid "Firmware update failed due to an input/output error."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/FirmwareUpdateWindow.qml:52
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:153
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:144
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobCard.qml:181
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:153
+msgctxt "@label"
+msgid "Glass"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:43
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:208
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobCard.qml:249
+msgctxt "@info"
+msgid "Please update your printer's firmware to manage the queue remotely."
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:241
+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:300
+msgctxt "@label:status"
+msgid "Loading..."
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:304
+msgctxt "@label:status"
+msgid "Unavailable"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:308
+msgctxt "@label:status"
+msgid "Unreachable"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:312
+msgctxt "@label:status"
+msgid "Idle"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:353
+msgctxt "@label"
+msgid "Untitled"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:374
+msgctxt "@label"
+msgid "Anonymous"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:401
+msgctxt "@label:status"
+msgid "Requires configuration changes"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:439
+msgctxt "@action:button"
+msgid "Details"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobCard.qml:130
+msgctxt "@label"
+msgid "Unavailable printer"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobCard.qml:132
+msgctxt "@label"
+msgid "First available"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml:31
+msgctxt "@label"
+msgid "Queued"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml:67
+msgctxt "@label link to connect manager"
+msgid "Manage in browser"
+msgstr ""
+
+#: /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:116
+msgctxt "@label"
+msgid "Print jobs"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml:132
+msgctxt "@label"
+msgid "Total print time"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml:148
+msgctxt "@label"
+msgid "Waiting for"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:50
msgctxt "@window:title"
msgid "Existing Connection"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:45
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:52
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:62
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:69
msgctxt "@title:window"
msgid "Connect to Networked Printer"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:72
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:81
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:82
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:42
-msgctxt "@action:button"
-msgid "Add"
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:81
+msgctxt "@label"
+msgid "Select your printer from the list below:"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:92
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:101
msgctxt "@action:button"
msgid "Edit"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:103
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:128
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:48
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:117
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:112
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:146
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:55
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:121
msgctxt "@action:button"
msgid "Remove"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:111
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:120
msgctxt "@action:button"
msgid "Refresh"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:204
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:215
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:231
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:244
+#: /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:268
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:283
+#: /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:280
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:297
+#: /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:302
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:321
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:306
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:325
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:316
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:336
msgctxt "@label"
msgid "The printer at this address has not yet responded."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:321
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/UM3InfoComponents.qml:39
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:341
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/UM3InfoComponents.qml:74
msgctxt "@action:button"
msgid "Connect"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:335
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:354
+msgctxt "@title:window"
+msgid "Invalid IP address"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:355
+#: /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:366
msgctxt "@title:window"
msgid "Printer Address"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:358
-msgctxt "@alabel"
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:389
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddPrinterByIpContent.qml:102
+msgctxt "@label"
msgid "Enter the IP address or hostname of your printer on the network."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:387
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/MoreInfoWindow.qml:132
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:419
+#: /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/PrintWindow.qml:34
-msgctxt "@title:window"
-msgid "Print over network"
+#: /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/PrintWindow.qml:65
-msgctxt "@label"
-msgid "Printer selection"
+#: /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/PrintWindow.qml:105
+#: /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:88
+msgctxt "@label:status"
+msgid "Aborting..."
+msgstr ""
+
+#: /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:94
+msgctxt "@label:status"
+msgid "Paused"
+msgstr ""
+
+#: /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:98
+msgctxt "@label:status"
+msgid "Action required"
+msgstr ""
+
+#: /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/PrintJobInfoBlock.qml:142
-msgctxt "@label"
-msgid "Waiting for: Unavailable printer"
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintWindow.qml:47
+msgctxt "@title:window"
+msgid "Print over network"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintJobInfoBlock.qml:144
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintWindow.qml:79
msgctxt "@label"
-msgid "Waiting for: First available"
+msgid "Printer selection"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintJobInfoBlock.qml:148
-msgctxt "@label"
-msgid "Waiting for: "
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintJobInfoBlock.qml:213
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:54
msgctxt "@label"
msgid "Move to top"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintJobInfoBlock.qml:234
-msgctxt "@window:title"
-msgid "Move print job to top"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintJobInfoBlock.qml:236
-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 ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintJobInfoBlock.qml:245
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:70
msgctxt "@label"
msgid "Delete"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintJobInfoBlock.qml:264
-msgctxt "@window:title"
-msgid "Delete print job"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintJobInfoBlock.qml:266
-msgctxt "@label %1 is the name of a print job."
-msgid "Are you sure you want to delete %1?"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/ClusterMonitorItem.qml:32
-msgctxt "@label link to connect manager"
-msgid "Manage queue"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/ClusterMonitorItem.qml:54
-msgctxt "@label"
-msgid "Queued"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/ClusterControlItem.qml:44
-msgctxt "@label"
-msgid "Printing"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/ClusterControlItem.qml:54
-msgctxt "@label link to connect manager"
-msgid "Manage printers"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/ClusterControlItem.qml:212
-msgctxt "@label"
-msgid "Not available"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/ClusterControlItem.qml:215
-msgctxt "@label"
-msgid "Unreachable"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/ClusterControlItem.qml:221
-msgctxt "@label"
-msgid "Available"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/ClusterControlItem.qml:416
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:100
#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:289
msgctxt "@label"
msgid "Resume"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/ClusterControlItem.qml:416
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:102
+msgctxt "@label"
+msgid "Pausing..."
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:104
+msgctxt "@label"
+msgid "Resuming..."
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:106
#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:284
#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:293
msgctxt "@label"
msgid "Pause"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/ClusterControlItem.qml:444
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:124
+msgctxt "@label"
+msgid "Aborting..."
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:124
msgctxt "@label"
msgid "Abort"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/ClusterControlItem.qml:464
+#: /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 ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:144
+msgctxt "@window:title"
+msgid "Move print job to top"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:153
+msgctxt "@label %1 is the name of a print job."
+msgid "Are you sure you want to delete %1?"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:154
+msgctxt "@window:title"
+msgid "Delete print job"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:163
+msgctxt "@label %1 is the name of a print job."
+msgid "Are you sure you want to abort %1?"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:164
#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:335
msgctxt "@window:title"
msgid "Abort print"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/ClusterControlItem.qml:466
-msgctxt "@label %1 is the name of a print job."
-msgid "Are you sure you want to abort %1?"
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:20
+msgctxt "@title:window"
+msgid "Configuration Changes"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/ClusterControlItem.qml:665
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/ClusterControlItem.qml:673
-msgctxt "@label:status"
-msgid "Aborted"
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:27
+msgctxt "@action:button"
+msgid "Override"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/ClusterControlItem.qml:667
-msgctxt "@label:status"
-msgid "Finished"
+#: /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: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/ClusterControlItem.qml:670
-msgctxt "@label:status"
-msgid "Preparing"
+#: /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/ClusterControlItem.qml:675
-msgctxt "@label:status"
-msgid "Pausing"
+#: /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/ClusterControlItem.qml:677
-msgctxt "@label:status"
-msgid "Paused"
+#: /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/ClusterControlItem.qml:679
-msgctxt "@label:status"
-msgid "Resuming"
+#: /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/ClusterControlItem.qml:681
-msgctxt "@label:status"
-msgid "Action required"
+#: /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/UM3InfoComponents.qml:38
+#: /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/UM3NetworkPrinting/resources/qml/UM3InfoComponents.qml:117
-msgctxt "@info:tooltip"
-msgid "Load the configuration of the printer into Cura"
+#: /home/ruben/Projects/Cura/plugins/SettingsGuide/resources/qml/SettingsGuide.qml:16
+msgctxt "@title"
+msgid "Cura Settings Guide"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/UM3InfoComponents.qml:118
-msgctxt "@action:button"
-msgid "Activate Configuration"
+#: /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.\n"
+"- Check if you are signed in to discover cloud-connected printers."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:130
+#: /home/ruben/Projects/Cura/plugins/MonitorStage/MonitorMain.qml:117
+msgctxt "@info"
+msgid "Please connect your printer to the network."
+msgstr ""
+
+#: /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:20
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:49
msgctxt "@label"
msgid "Color scheme"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:145
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:107
msgctxt "@label:listbox"
msgid "Material Color"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:149
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:111
msgctxt "@label:listbox"
msgid "Line Type"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:153
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:115
msgctxt "@label:listbox"
msgid "Feedrate"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:157
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:119
msgctxt "@label:listbox"
msgid "Layer thickness"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:198
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:156
msgctxt "@label"
msgid "Compatibility Mode"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:284
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:230
msgctxt "@label"
-msgid "Show Travels"
+msgid "Travels"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:290
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:236
msgctxt "@label"
-msgid "Show Helpers"
+msgid "Helpers"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:296
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:242
msgctxt "@label"
-msgid "Show Shell"
+msgid "Shell"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:302
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:248
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedInfillDensitySelector.qml:65
msgctxt "@label"
-msgid "Show Infill"
+msgid "Infill"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:355
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:298
msgctxt "@label"
msgid "Only Show Top Layers"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:366
+#: /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/SimulationView.qml:379
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:322
msgctxt "@label"
msgid "Top / Bottom"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:383
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:326
msgctxt "@label"
msgid "Inner Wall"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:448
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:384
msgctxt "@label"
msgid "min"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:500
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:433
msgctxt "@label"
msgid "max"
msgstr ""
@@ -2138,41 +2521,41 @@ msgctxt "@label"
msgid "Post Processing Scripts"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.qml:225
+#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.qml:233
msgctxt "@action"
msgid "Add a script"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.qml:271
+#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.qml:279
msgctxt "@label"
msgid "Settings"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.qml:474
+#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.qml:493
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 these 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 these data to Ultimaker and help us improve Cura"
+msgid "Allow sending anonymous data"
msgstr ""
#: /home/ruben/Projects/Cura/plugins/ImageReader/ConfigUI.qml:19
@@ -2223,15 +2606,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
@@ -2239,6 +2617,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."
@@ -2279,18 +2662,18 @@ msgctxt "@label"
msgid "Modify settings for infill of other models"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:341
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:346
msgctxt "@action:button"
msgid "Select settings"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:383
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:388
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/resources/qml/Preferences/SettingVisibilityPage.qml:98
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/SettingVisibilityPage.qml:94
msgctxt "@label:textbox"
msgid "Filter..."
msgstr ""
@@ -2317,13 +2700,13 @@ msgid "Create new"
msgstr ""
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:70
-#: /home/ruben/Projects/Cura/resources/qml/WorkspaceSummaryDialog.qml:72
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:73
msgctxt "@action:title"
msgid "Summary - Cura Project"
msgstr ""
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:92
-#: /home/ruben/Projects/Cura/resources/qml/WorkspaceSummaryDialog.qml:96
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:97
msgctxt "@action:label"
msgid "Printer settings"
msgstr ""
@@ -2340,18 +2723,19 @@ msgid "Update"
msgstr ""
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:143
-#: /home/ruben/Projects/Cura/resources/qml/WorkspaceSummaryDialog.qml:105
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:106
msgctxt "@action:label"
msgid "Type"
msgstr ""
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:159
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:121
msgctxt "@action:label"
msgid "Printer Group"
msgstr ""
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:180
-#: /home/ruben/Projects/Cura/resources/qml/WorkspaceSummaryDialog.qml:196
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:226
msgctxt "@action:label"
msgid "Profile settings"
msgstr ""
@@ -2363,19 +2747,20 @@ msgstr ""
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:216
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:308
-#: /home/ruben/Projects/Cura/resources/qml/WorkspaceSummaryDialog.qml:220
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:121
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:250
msgctxt "@action:label"
msgid "Name"
msgstr ""
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:231
-#: /home/ruben/Projects/Cura/resources/qml/WorkspaceSummaryDialog.qml:204
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:234
msgctxt "@action:label"
msgid "Not in profile"
msgstr ""
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:236
-#: /home/ruben/Projects/Cura/resources/qml/WorkspaceSummaryDialog.qml:209
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:239
msgctxt "@action:label"
msgid "%1 override"
msgid_plural "%1 overrides"
@@ -2405,7 +2790,6 @@ msgid "How should the conflict in the material be resolved?"
msgstr ""
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:327
-#: /home/ruben/Projects/Cura/resources/qml/WorkspaceSummaryDialog.qml:237
msgctxt "@action:label"
msgid "Setting visibility"
msgstr ""
@@ -2416,13 +2800,11 @@ msgid "Mode"
msgstr ""
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:352
-#: /home/ruben/Projects/Cura/resources/qml/WorkspaceSummaryDialog.qml:246
msgctxt "@action:label"
msgid "Visible settings:"
msgstr ""
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:357
-#: /home/ruben/Projects/Cura/resources/qml/WorkspaceSummaryDialog.qml:251
msgctxt "@action:label"
msgid "%1 out of %2"
msgstr ""
@@ -2437,106 +2819,168 @@ msgctxt "@action:button"
msgid "Open"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/ProfileCreatorTabControls.qml:34
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/pages/BackupsPage.qml:28
+msgctxt "@title"
+msgid "My Backups"
+msgstr ""
+
+#: /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 ""
+
+#: /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 ""
+
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/pages/WelcomePage.qml:34
+msgctxt "@description"
+msgid "Backup and synchronize your Cura settings."
+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 ""
+
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/main.qml:24
+msgctxt "@title:window"
+msgid "Cura Backups"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListItemDetails.qml:21
+msgctxt "@backuplist:label"
+msgid "Cura Version"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListItemDetails.qml:29
+msgctxt "@backuplist:label"
+msgid "Machines"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListItemDetails.qml:37
+msgctxt "@backuplist:label"
+msgid "Materials"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListItemDetails.qml:45
+msgctxt "@backuplist:label"
+msgid "Profiles"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListItemDetails.qml:53
+msgctxt "@backuplist:label"
+msgid "Plugins"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListItem.qml:71
+msgctxt "@button"
+msgid "Restore"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListItem.qml:99
+msgctxt "@dialog:title"
+msgid "Delete Backup"
+msgstr ""
+
+#: /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 ""
+
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListItem.qml:108
+msgctxt "@dialog:title"
+msgid "Restore Backup"
+msgstr ""
+
+#: /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 ""
+
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListFooter.qml:22
+msgctxt "@button"
+msgid "Want more?"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListFooter.qml:31
+msgctxt "@button"
+msgid "Backup Now"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListFooter.qml:43
+msgctxt "@checkbox:description"
+msgid "Auto Backup"
+msgstr ""
+
+#: /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 ""
+
+#: /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:138
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:154
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:152
+#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/ProfileCreatorTabControls.qml:60
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:174
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:159
msgctxt "@action:button"
msgid "Export"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/ProfileCreatorTabControls.qml:140
-msgctxt "@action:button"
-msgid "Next"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/ProfileCreatorPageCategoryView.qml:163
+#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/ProfileCreatorPageCategoryView.qml:209
msgctxt "@label"
msgid "Tip"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/CuraPrintProfileCreatorView.qml:80
-#: /home/ruben/Projects/Cura/resources/qml/PrepareSidebar.qml:341
-msgctxt "@label Hours and minutes"
-msgid "00h 00min"
+#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/ProfileCreatorMaterialMenu.qml:20
+#: /home/ruben/Projects/Cura/resources/qml/Menus/MaterialMenu.qml:66
+msgctxt "@label:category menu label"
+msgid "Generic"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/CuraPrintProfileCreatorView.qml:142
-#: /home/ruben/Projects/Cura/resources/qml/PrepareSidebar.qml:441
-msgctxt "@label"
-msgid "Cost specification"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/CuraPrintProfileCreatorView.qml:147
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/CuraPrintProfileCreatorView.qml:156
-#: /home/ruben/Projects/Cura/resources/qml/PrepareSidebar.qml:446
-#: /home/ruben/Projects/Cura/resources/qml/PrepareSidebar.qml:455
-msgctxt "@label m for meter"
-msgid "%1m"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/CuraPrintProfileCreatorView.qml:148
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/CuraPrintProfileCreatorView.qml:157
-#: /home/ruben/Projects/Cura/resources/qml/PrepareSidebar.qml:447
-#: /home/ruben/Projects/Cura/resources/qml/PrepareSidebar.qml:456
-msgctxt "@label g for grams"
-msgid "%1g"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/CuraPrintProfileCreatorView.qml:155
-#: /home/ruben/Projects/Cura/resources/qml/PrepareSidebar.qml:454
-msgctxt "@label"
-msgid "Total:"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/CuraPrintProfileCreatorView.qml:205
-msgctxt ""
-"@label Print estimates: m for meters, g for grams, %4 is currency and %3 is "
-"print cost"
-msgid "%1m / ~ %2g / ~ %4 %3"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/CuraPrintProfileCreatorView.qml:210
-msgctxt "@label Print estimates: m for meters, g for grams"
-msgid "%1m / ~ %2g"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/ProfileCreatorPage.qml:143
+#: /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:26
+#: /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
+#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UM2UpgradeSelectionMachineAction.qml:30
msgctxt "@label"
msgid "Please select any upgrades made to this Ultimaker 2."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UM2UpgradeSelectionMachineAction.qml:47
+#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UM2UpgradeSelectionMachineAction.qml:44
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 "
@@ -2544,7 +2988,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 "
@@ -2552,156 +2996,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/UpgradeFirmwareMachineAction.qml:30
-msgctxt "@title"
-msgid "Upgrade Firmware"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UpgradeFirmwareMachineAction.qml:41
-msgctxt "@label"
-msgid ""
-"Firmware is the piece of software running directly on your 3D printer. This "
-"firmware controls the step motors, regulates the temperature and ultimately "
-"makes your printer work."
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UpgradeFirmwareMachineAction.qml:51
-msgctxt "@label"
-msgid ""
-"The firmware shipping with new printers works, but new versions tend to have "
-"more features and improvements."
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UpgradeFirmwareMachineAction.qml:65
-msgctxt "@action:button"
-msgid "Automatically upgrade Firmware"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UpgradeFirmwareMachineAction.qml:75
-msgctxt "@action:button"
-msgid "Upload custom Firmware"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UpgradeFirmwareMachineAction.qml:87
-msgctxt "@title:window"
-msgid "Select custom firmware"
-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"
@@ -2713,7 +3027,6 @@ msgid "Printer does not accept commands"
msgstr ""
#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:133
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:197
msgctxt "@label:MonitorStatus"
msgid "In maintenance. Please check the printer"
msgstr ""
@@ -2724,19 +3037,16 @@ msgid "Lost connection with the printer"
msgstr ""
#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:146
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:187
msgctxt "@label:MonitorStatus"
msgid "Printing..."
msgstr ""
#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:149
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:189
msgctxt "@label:MonitorStatus"
msgid "Paused"
msgstr ""
#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:152
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:191
msgctxt "@label:MonitorStatus"
msgid "Preparing..."
msgstr ""
@@ -2756,231 +3066,174 @@ msgctxt "@label"
msgid "Are you sure you want to abort the print?"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/DiscardOrKeepProfileChangesDialog.qml:15
-msgctxt "@title:window"
-msgid "Discard or Keep changes"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/DiscardOrKeepProfileChangesDialog.qml:57
-msgctxt "@text:window"
-msgid ""
-"You have customized some profile settings.\n"
-"Would you like to keep or discard those settings?"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/DiscardOrKeepProfileChangesDialog.qml:110
-msgctxt "@title:column"
-msgid "Profile settings"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/DiscardOrKeepProfileChangesDialog.qml:117
-msgctxt "@title:column"
-msgid "Default"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/DiscardOrKeepProfileChangesDialog.qml:124
-msgctxt "@title:column"
-msgid "Customized"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/DiscardOrKeepProfileChangesDialog.qml:157
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:639
-msgctxt "@option:discardOrKeep"
-msgid "Always ask me this"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/DiscardOrKeepProfileChangesDialog.qml:158
-msgctxt "@option:discardOrKeep"
-msgid "Discard and never ask again"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/DiscardOrKeepProfileChangesDialog.qml:159
-msgctxt "@option:discardOrKeep"
-msgid "Keep and never ask again"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/DiscardOrKeepProfileChangesDialog.qml:196
-msgctxt "@action:button"
-msgid "Discard"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/DiscardOrKeepProfileChangesDialog.qml:209
-msgctxt "@action:button"
-msgid "Keep"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/DiscardOrKeepProfileChangesDialog.qml:222
-msgctxt "@action:button"
-msgid "Create New Profile"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:71
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:73
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:102
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:103
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:127
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:137
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:147
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:157
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:207
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:209
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:224
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:258
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:275
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:293
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:302
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:316
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:323
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:334
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:347
msgctxt "@label"
msgid "Adhesion Information"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:378
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:373
+#: /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:35
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:72
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:99
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:40
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:73
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:117
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:131
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:160
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:148
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:223
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:239
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:287
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:253
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:240
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:290
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:254
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:304
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:312
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:313
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:317
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:335
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:343
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:347
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:353
msgctxt "@info:status Don't translate the XML tag !"
msgid "Successfully exported material to %1"
msgstr ""
@@ -2990,253 +3243,277 @@ msgctxt "@title:tab"
msgid "Setting Visibility"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/SettingVisibilityPage.qml:50
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/SettingVisibilityPage.qml:46
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:48
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:61
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:68
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:75
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:83
msgctxt "@title:column"
msgid "Unit"
msgstr ""
#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:15
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:537
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:410
msgctxt "@title:tab"
msgid "General"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:141
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:130
msgctxt "@label"
msgid "Interface"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:152
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:141
msgctxt "@label"
msgid "Language:"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:220
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:208
msgctxt "@label"
msgid "Currency:"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:234
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:221
msgctxt "@label"
msgid "Theme:"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:294
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:277
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:311
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:294
msgctxt "@info:tooltip"
msgid "Slice automatically when changing settings."
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:319
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:302
msgctxt "@option:check"
msgid "Slice automatically"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:333
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:316
msgctxt "@label"
msgid "Viewport behavior"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:341
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:324
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:350
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:333
msgctxt "@option:check"
msgid "Display overhang"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:357
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:341
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:362
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:346
msgctxt "@action:button"
msgid "Center camera when item is selected"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:371
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:356
msgctxt "@info:tooltip"
msgid "Should the default zoom behavior of cura be inverted?"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:376
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:361
msgctxt "@action:button"
msgid "Invert the direction of camera zoom."
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:386
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:371
msgctxt "@info:tooltip"
msgid "Should zooming move in the direction of the mouse?"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:391
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:371
+msgctxt "@info:tooltip"
+msgid ""
+"Zooming towards the mouse is not supported in the orthogonal perspective."
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:376
msgctxt "@action:button"
msgid "Zoom toward mouse direction"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:401
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:402
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:406
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:407
msgctxt "@option:check"
msgid "Ensure models are kept apart"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:415
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:416
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:420
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:421
msgctxt "@option:check"
msgid "Automatically drop models to the build plate"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:432
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:433
msgctxt "@info:tooltip"
msgid "Show caution message in g-code reader."
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:441
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:442
msgctxt "@option:check"
msgid "Caution message in g-code reader"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:449
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:450
msgctxt "@info:tooltip"
msgid "Should layer be forced into compatibility mode?"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:454
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:455
msgctxt "@option:check"
msgid "Force layer view compatibility mode (restart required)"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:470
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:465
+msgctxt "@info:tooltip"
+msgid "What type of camera rendering should be used?"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:472
+msgctxt "@window:text"
+msgid "Camera rendering: "
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:483
+msgid "Perspective"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:484
+msgid "Orthogonal"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:515
msgctxt "@label"
msgid "Opening and saving files"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:477
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:522
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:482
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:527
msgctxt "@option:check"
msgid "Scale large models"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:492
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:537
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:497
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:542
msgctxt "@option:check"
msgid "Scale extremely small models"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:507
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:552
msgctxt "@info:tooltip"
msgid "Should models be selected after they are loaded?"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:512
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:557
msgctxt "@option:check"
msgid "Select models when loaded"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:522
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:567
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:527
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:572
msgctxt "@option:check"
msgid "Add machine prefix to job name"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:537
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:582
msgctxt "@info:tooltip"
msgid "Should a summary be shown when saving a project file?"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:541
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:586
msgctxt "@option:check"
msgid "Show summary dialog when saving project"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:551
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:596
msgctxt "@info:tooltip"
msgid "Default behavior when opening a project file"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:559
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:604
msgctxt "@window:text"
msgid "Default behavior when opening a project file: "
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:573
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:618
msgctxt "@option:openProject"
msgid "Always ask me this"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:574
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:619
msgctxt "@option:openProject"
msgid "Always open as a project"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:575
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:620
msgctxt "@option:openProject"
msgid "Always import models"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:611
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:656
msgctxt "@info:tooltip"
msgid ""
"When you have made changes to a profile and switched to a different one, a "
@@ -3244,44 +3521,50 @@ 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:620
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:665
msgctxt "@label"
msgid "Profiles"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:625
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:670
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:640
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:684
+#: /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:685
msgctxt "@option:discardOrKeep"
msgid "Always discard changed settings"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:641
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:686
msgctxt "@option:discardOrKeep"
msgid "Always transfer changed settings to new profile"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:675
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:720
msgctxt "@label"
msgid "Privacy"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:683
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:727
msgctxt "@info:tooltip"
msgid "Should Cura check for updates when the program is started?"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:688
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:732
msgctxt "@option:check"
msgid "Check for updates on start"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:699
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:742
msgctxt "@info:tooltip"
msgid ""
"Should anonymous data about your print be sent to Ultimaker? Note, no "
@@ -3289,366 +3572,230 @@ msgid ""
"stored."
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:704
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:747
msgctxt "@option:check"
msgid "Send (anonymous) print information"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:713
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:756
msgctxt "@action:button"
msgid "More information"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:731
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:774
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/PrintSetupSelectorHeader.qml:27
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ProfileMenu.qml:23
msgctxt "@label"
msgid "Experimental"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:738
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:781
msgctxt "@info:tooltip"
msgid "Use multi build plate functionality"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:743
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:786
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:542
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:415
msgctxt "@title:tab"
msgid "Printers"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:55
-#: /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:134
msgctxt "@action:button"
msgid "Rename"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:147
-msgctxt "@label"
-msgid "Printer type:"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:156
-msgctxt "@label"
-msgid "Connection:"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:162
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/OutputDeviceHeader.qml:47
-msgctxt "@info:status"
-msgid "The printer is not connected."
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:168
-msgctxt "@label"
-msgid "State:"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:181
-msgctxt "@label:MonitorStatus"
-msgid "Waiting for a printjob"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:193
-msgctxt "@label:MonitorStatus"
-msgid "Waiting for someone to clear the build plate"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:199
-msgctxt "@label:MonitorStatus"
-msgid "Aborting print..."
-msgstr ""
-
#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:36
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:546
+#: /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:89
msgctxt "@label"
msgid "Create"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:102
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:105
msgctxt "@label"
msgid "Duplicate"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:174
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:181
msgctxt "@title:window"
msgid "Create Profile"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:225
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:183
+msgctxt "@info"
+msgid "Please provide a name for this profile."
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:239
msgctxt "@title:window"
msgid "Duplicate Profile"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:256
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:270
msgctxt "@title:window"
msgid "Rename Profile"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:269
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:283
msgctxt "@title:window"
msgid "Import Profile"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:295
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:309
msgctxt "@title:window"
msgid "Export Profile"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:350
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:364
msgctxt "@label %1 is printer name"
msgid "Printer: %1"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:403
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:420
msgctxt "@label"
-msgid "Protected profiles"
+msgid "Default profiles"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:403
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:420
msgctxt "@label"
msgid "Custom profiles"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:480
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:500
msgctxt "@action:button"
msgid "Update profile with current settings/overrides"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:487
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:507
msgctxt "@action:button"
msgid "Discard current changes"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:504
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:524
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:511
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:531
msgctxt "@action:label"
msgid "Your current settings match the selected profile."
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:530
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:550
msgctxt "@title:tab"
msgid "Global Settings"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/AddMachineDialog.qml:18
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:946
-msgctxt "@title:window"
-msgid "Add Printer"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/AddMachineDialog.qml:194
-msgctxt "@label"
-msgid "Printer Name:"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/AddMachineDialog.qml:217
+#: /home/ruben/Projects/Cura/resources/qml/MainWindow/MainWindowHeader.qml:89
msgctxt "@action:button"
-msgid "Add Printer"
+msgid "Marketplace"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/JobSpecs.qml:84
+#: /home/ruben/Projects/Cura/resources/qml/MainWindow/ApplicationMenu.qml:27
+#: /home/ruben/Projects/Cura/resources/qml/Menus/FileMenu.qml:13
+msgctxt "@title:menu menubar:toplevel"
+msgid "&File"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/MainWindow/ApplicationMenu.qml:31
+msgctxt "@title:menu menubar:toplevel"
+msgid "&Edit"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/MainWindow/ApplicationMenu.qml:48
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ViewMenu.qml:12
+msgctxt "@title:menu menubar:toplevel"
+msgid "&View"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/MainWindow/ApplicationMenu.qml:50
+#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:13
+msgctxt "@title:menu menubar:toplevel"
+msgid "&Settings"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/MainWindow/ApplicationMenu.qml:55
+msgctxt "@title:menu menubar:toplevel"
+msgid "E&xtensions"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/MainWindow/ApplicationMenu.qml:89
+msgctxt "@title:menu menubar:toplevel"
+msgid "P&references"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/MainWindow/ApplicationMenu.qml:97
+msgctxt "@title:menu menubar:toplevel"
+msgid "&Help"
+msgstr ""
+
+#: /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: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 ""
+
+#: /home/ruben/Projects/Cura/resources/qml/JobSpecs.qml:88
msgctxt "@text Print job name"
msgid "Untitled"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:15
-msgctxt "@title:window"
-msgid "About Cura"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:43
-msgctxt "@label"
-msgid "version: %1"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:56
-msgctxt "@label"
-msgid "End-to-end solution for fused filament 3D printing."
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:69
-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/AboutDialog.qml:118
-msgctxt "@label"
-msgid "Graphical user interface"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:119
-msgctxt "@label"
-msgid "Application framework"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:120
-msgctxt "@label"
-msgid "G-code generator"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:121
-msgctxt "@label"
-msgid "Interprocess communication library"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:123
-msgctxt "@label"
-msgid "Programming language"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:124
-msgctxt "@label"
-msgid "GUI framework"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:125
-msgctxt "@label"
-msgid "GUI framework bindings"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:126
-msgctxt "@label"
-msgid "C/C++ Binding library"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:127
-msgctxt "@label"
-msgid "Data interchange format"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:128
-msgctxt "@label"
-msgid "Support library for scientific computing"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:129
-msgctxt "@label"
-msgid "Support library for faster math"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:130
-msgctxt "@label"
-msgid "Support library for handling STL files"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:131
-msgctxt "@label"
-msgid "Support library for handling 3MF files"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:132
-msgctxt "@label"
-msgid "Serial communication library"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:133
-msgctxt "@label"
-msgid "ZeroConf discovery library"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:134
-msgctxt "@label"
-msgid "Polygon clipping library"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:135
-msgctxt "@Label"
-msgid "Python HTTP library"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:137
-msgctxt "@label"
-msgid "Font"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:138
-msgctxt "@label"
-msgid "SVG icons"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:139
-msgctxt "@label"
-msgid "Linux cross-distribution application deployment"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:42
-msgctxt "@label"
-msgid "Profile:"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:103
-msgctxt "@tooltip"
-msgid ""
-"Some setting/override values are different from the values stored in the "
-"profile.\n"
-"\n"
-"Click to open the profile manager."
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:199
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:68
msgctxt "@label:textbox"
-msgid "Search..."
+msgid "search settings"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:544
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:466
msgctxt "@action:menu"
msgid "Copy value to all extruders"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:553
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:475
msgctxt "@action:menu"
msgid "Copy all changed values to all extruders"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:590
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:512
msgctxt "@action:menu"
msgid "Hide this setting"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:608
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:525
msgctxt "@action:menu"
msgid "Don't show this setting"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:612
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:529
msgctxt "@action:menu"
msgid "Keep this setting visible"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:636
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:416
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:548
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:434
msgctxt "@action:menu"
msgid "Configure setting visibility..."
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:643
-msgctxt "@action:inmenu"
-msgid "Collapse All"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:648
-msgctxt "@action:inmenu"
-msgid "Expand All"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingCategory.qml:249
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingCategory.qml:237
msgctxt "@label"
msgid ""
"Some hidden settings use values different from their normal calculated "
@@ -3657,29 +3804,36 @@ msgid ""
"Click to make these settings visible."
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:61
+#: /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:66
+#: /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:154
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:186
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:157
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:190
msgctxt "@label"
msgid "The value is resolved from per-extruder values "
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:188
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:228
msgctxt "@label"
msgid ""
"This setting has a value that is different from the profile.\n"
@@ -3687,7 +3841,7 @@ msgid ""
"Click to restore the value of the profile."
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:286
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:322
msgctxt "@label"
msgid ""
"This setting is normally calculated, but it currently has an absolute value "
@@ -3696,79 +3850,178 @@ msgid ""
"Click to restore the calculated value."
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ManualPrinterControl.qml:129
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/PrintSetupSelectorContents.qml:144
+msgctxt "@button"
+msgid "Recommended"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/PrintSetupSelectorContents.qml:158
+msgctxt "@button"
+msgid "Custom"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedInfillDensitySelector.qml:193
+msgctxt "@label"
+msgid "Gradual infill"
+msgstr ""
+
+#: /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 ""
+
+#: /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: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/RecommendedAdhesionSelector.qml:29
+msgctxt "@label"
+msgid "Adhesion"
+msgstr ""
+
+#: /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
+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"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/PrintSetupSelectorHeader.qml:14
+msgctxt "@label:Should be short"
+msgid "Off"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Custom/GlobalProfileSelector.qml:27
+msgctxt "@label"
+msgid "Profile"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Custom/GlobalProfileSelector.qml:94
+msgctxt "@tooltip"
+msgid ""
+"Some setting/override values are different from the values stored in the "
+"profile.\n"
+"\n"
+"Click to open the profile manager."
+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."
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ManualPrinterControl.qml:52
msgctxt "@label"
msgid "Printer control"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ManualPrinterControl.qml:144
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ManualPrinterControl.qml:67
msgctxt "@label"
msgid "Jog Position"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ManualPrinterControl.qml:162
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ManualPrinterControl.qml:85
msgctxt "@label"
msgid "X/Y"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ManualPrinterControl.qml:269
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ManualPrinterControl.qml:192
msgctxt "@label"
msgid "Z"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ManualPrinterControl.qml:334
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ManualPrinterControl.qml:257
msgctxt "@label"
msgid "Jog Distance"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ManualPrinterControl.qml:443
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ManualPrinterControl.qml:301
msgctxt "@label"
msgid "Send G-code"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ManualPrinterControl.qml:506
+#: /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:36
-#: /home/ruben/Projects/Cura/resources/qml/SidebarHeader.qml:272
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:38
msgctxt "@label"
msgid "Extruder"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:66
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:68
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:98
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:100
msgctxt "@tooltip"
msgid "The current temperature of this hotend."
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:172
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:174
msgctxt "@tooltip of temperature input"
msgid "The temperature to pre-heat the hotend to."
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:336
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/HeatedBedBox.qml:331
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:338
+#: /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:339
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/HeatedBedBox.qml:334
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:341
+#: /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:365
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:367
msgctxt "@tooltip of pre-heat"
msgid ""
"Heat the hotend in advance before printing. You can continue adjusting your "
@@ -3776,45 +4029,49 @@ msgid ""
"up when you're ready to print."
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:401
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:403
msgctxt "@tooltip"
msgid "The colour of the material in this extruder."
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:433
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:435
msgctxt "@tooltip"
msgid "The material in this extruder."
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:465
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:467
msgctxt "@tooltip"
msgid "The nozzle inserted in this extruder."
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/HeatedBedBox.qml:25
-#: /home/ruben/Projects/Cura/resources/qml/SidebarHeader.qml:493
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/OutputDeviceHeader.qml:55
+msgctxt "@info:status"
+msgid "The printer is not connected."
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/HeatedBedBox.qml:26
msgctxt "@label"
msgid "Build plate"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/HeatedBedBox.qml:55
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/HeatedBedBox.qml:56
msgctxt "@tooltip"
msgid ""
"The target temperature of the heated bed. The bed will heat up or cool down "
"towards this temperature. If this is 0, the bed heating is turned off."
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/HeatedBedBox.qml:87
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/HeatedBedBox.qml:88
msgctxt "@tooltip"
msgid "The current temperature of the heated bed."
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/HeatedBedBox.qml:160
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/HeatedBedBox.qml:161
msgctxt "@tooltip of temperature input"
msgid "The temperature to pre-heat the bed to."
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/HeatedBedBox.qml:360
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/HeatedBedBox.qml:361
msgctxt "@tooltip of pre-heat"
msgid ""
"Heat the bed in advance before printing. You can continue adjusting your "
@@ -3827,16 +4084,11 @@ msgctxt "@label:category menu label"
msgid "Material"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Menus/MaterialMenu.qml:37
+#: /home/ruben/Projects/Cura/resources/qml/Menus/MaterialMenu.qml:42
msgctxt "@label:category menu label"
msgid "Favorites"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Menus/MaterialMenu.qml:61
-msgctxt "@label:category menu label"
-msgid "Generic"
-msgstr ""
-
#: /home/ruben/Projects/Cura/resources/qml/Menus/PrinterMenu.qml:25
msgctxt "@label:category menu label"
msgid "Network enabled printers"
@@ -3847,17 +4099,62 @@ msgctxt "@label:category menu label"
msgid "Local printers"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Menus/ViewMenu.qml:12
-msgctxt "@title:menu menubar:toplevel"
-msgid "&View"
+#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:15
+msgctxt "@title:menu menubar:settings"
+msgid "&Printer"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Menus/ViewMenu.qml:39
+#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:32
+msgctxt "@title:menu"
+msgid "&Material"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:41
+msgctxt "@action:inmenu"
+msgid "Set as Active Extruder"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:47
+msgctxt "@action:inmenu"
+msgid "Enable Extruder"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:54
+msgctxt "@action:inmenu"
+msgid "Disable Extruder"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:68
+msgctxt "@title:menu"
+msgid "&Build plate"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:71
+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:54
+#: /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 ""
@@ -3867,16 +4164,31 @@ msgctxt "@action:inmenu"
msgid "Visible Settings"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingVisibilityPresetsMenu.qml:43
+#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingVisibilityPresetsMenu.qml:42
msgctxt "@action:inmenu"
msgid "Show All Settings"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingVisibilityPresetsMenu.qml:54
+#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingVisibilityPresetsMenu.qml:53
msgctxt "@action:inmenu"
msgid "Manage Setting Visibility..."
msgstr ""
+#: /home/ruben/Projects/Cura/resources/qml/Menus/FileMenu.qml:32
+msgctxt "@title:menu menubar:file"
+msgid "&Save..."
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Menus/FileMenu.qml:53
+msgctxt "@title:menu menubar:file"
+msgid "&Export..."
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Menus/FileMenu.qml:64
+msgctxt "@action:inmenu menubar:file"
+msgid "Export Selection..."
+msgstr ""
+
#: /home/ruben/Projects/Cura/resources/qml/Menus/ContextMenu.qml:27
msgctxt "@label"
msgid "Print Selected Model With:"
@@ -3896,523 +4208,496 @@ msgctxt "@label"
msgid "Number of Copies"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/ConfigurationListView.qml:33
-msgctxt "@label:header configurations"
-msgid "Available configurations"
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/AutoConfiguration.qml:18
+msgctxt "@header"
+msgid "Configurations"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/PrintCoreConfiguration.qml:28
-msgctxt "@label:extruder label"
-msgid "Extruder"
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/ConfigurationMenu.qml:110
+msgctxt "@label"
+msgid "Select configuration"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/SyncButton.qml:16
-msgctxt "@label:extruder label"
-msgid "Yes"
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/ConfigurationMenu.qml:221
+msgctxt "@label"
+msgid "Configurations"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/SyncButton.qml:16
-msgctxt "@label:extruder label"
-msgid "No"
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/ConfigurationListView.qml:57
+msgctxt "@label"
+msgid "Loading available configurations from the printer..."
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Menus/RecentFilesMenu.qml:13
+#: /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 ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/CustomConfiguration.qml:25
+msgctxt "@header"
+msgid "Custom"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/CustomConfiguration.qml:61
+msgctxt "@label"
+msgid "Printer"
+msgstr ""
+
+#: /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:250
+msgctxt "@label"
+msgid "Material"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/CustomConfiguration.qml:375
+msgctxt "@label"
+msgid "Use glue for better adhesion with this material combination."
+msgstr ""
+
+#: /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 ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/ConfigurationItem.qml:129
+msgctxt "@label"
+msgid "Marketplace"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Menus/RecentFilesMenu.qml:15
msgctxt "@title:menu menubar:file"
msgid "Open &Recent"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/PrepareSidebar.qml:150
-msgctxt "@label:listbox"
-msgid "Print Setup"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/PrepareSidebar.qml:150
-msgctxt "@label:listbox"
-msgid ""
-"Print Setup disabled\n"
-"G-code files cannot be modified"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/PrepareSidebar.qml:359
-msgctxt "@tooltip"
-msgid "Time specification"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/PrepareSidebar.qml:577
-msgctxt "@tooltip"
-msgid ""
-"Recommended Print Setup
Print with the recommended settings "
-"for the selected printer, material and quality."
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/PrepareSidebar.qml:582
-msgctxt "@tooltip"
-msgid ""
-"Custom Print Setup
Print with finegrained control over every "
-"last bit of the slicing process."
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/PrintMonitor.qml:106
+#: /home/ruben/Projects/Cura/resources/qml/PrintMonitor.qml:140
msgctxt "@label"
msgid "Active print"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/PrintMonitor.qml:114
+#: /home/ruben/Projects/Cura/resources/qml/PrintMonitor.qml:148
msgctxt "@label"
msgid "Job Name"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/PrintMonitor.qml:122
+#: /home/ruben/Projects/Cura/resources/qml/PrintMonitor.qml:156
msgctxt "@label"
msgid "Printing Time"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/PrintMonitor.qml:130
+#: /home/ruben/Projects/Cura/resources/qml/PrintMonitor.qml:164
msgctxt "@label"
msgid "Estimated time left"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:78
+#: /home/ruben/Projects/Cura/resources/qml/ViewsSelector.qml:50
+msgctxt "@label"
+msgid "View type"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/ObjectSelector.qml:59
+msgctxt "@label"
+msgid "Object list"
+msgstr ""
+
+#: /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:42
+msgctxt "@button"
+msgid "Sign out"
+msgstr ""
+
+#: /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:40
+msgctxt "@label"
+msgid "The next generation 3D printing workflow"
+msgstr ""
+
+#: /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 print profiles from leading brands"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Account/GeneralOperations.qml:78
+msgctxt "@button"
+msgid "Create account"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/OutputProcessWidget.qml:59
+msgctxt "@label"
+msgid "No time estimation available"
+msgstr ""
+
+#: /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:127
+msgctxt "@button"
+msgid "Preview"
+msgstr ""
+
+#: /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:67
+msgctxt "@label:PrintjobStatus"
+msgid "Unable to slice"
+msgstr ""
+
+#: /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:104
+msgctxt "@label"
+msgid "Start the slicing process"
+msgstr ""
+
+#: /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 estimation"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/PrintJobInformation.qml:114
+msgctxt "@label"
+msgid "Material estimation"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/PrintJobInformation.qml:164
+msgctxt "@label m for meter"
+msgid "%1m"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/PrintJobInformation.qml:165
+msgctxt "@label g for grams"
+msgid "%1g"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/PrinterSelector/MachineSelectorList.qml:19
+msgctxt "@label"
+msgid "Connected printers"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/PrinterSelector/MachineSelectorList.qml:19
+msgctxt "@label"
+msgid "Preset printers"
+msgstr ""
+
+#: /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:182
+msgctxt "@button"
+msgid "Manage printers"
+msgstr ""
+
+#: /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:88
msgctxt "@action:inmenu"
msgid "Toggle Full Screen"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:85
+#: /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:95
+#: /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:105
+#: /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:113
+#: /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:120
+#: /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:127
+#: /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:134
+#: /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:141
+#: /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:148
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:166
msgctxt "@action:inmenu"
msgid "Configure Cura..."
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:155
+#: /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:161
+#: /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:168
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:186
msgctxt "@action:inmenu"
msgid "Manage Materials..."
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:176
+#: /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:184
+#: /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:196
+#: /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:202
+#: /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:209
+#: /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:217
+#: /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:225
+#: /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:232
+#: /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:242
+#: /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:251
+#: /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:260
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:286
msgctxt "@action:inmenu"
msgid "Delete Model"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:268
+#: /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:274
+#: /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:294
+#: /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:304
+#: /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:314
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:340
msgctxt "@action:inmenu"
msgid "&Multiply Model..."
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:321
+#: /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:331
+#: /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:341
+#: /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:350
+#: /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:357
+#: /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:365
+#: /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:372
+#: /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:379
+#: /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:386
+#: /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:394
+#: /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:401
-msgctxt "@action:inmenu menubar:help"
-msgid "Show Engine &Log..."
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:409
+#: /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:423
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:441
msgctxt "@action:menu"
-msgid "Browse packages..."
+msgid "&Marketplace"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:430
-msgctxt "@action:inmenu menubar:view"
-msgid "Expand/Collapse Sidebar"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:27
-msgctxt "@label:PrintjobStatus"
-msgid "Please load a 3D model"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:37
-msgctxt "@label:PrintjobStatus"
-msgid "Ready to slice"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:39
-msgctxt "@label:PrintjobStatus"
-msgid "Slicing..."
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:41
-msgctxt "@label:PrintjobStatus %1 is target operation"
-msgid "Ready to %1"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:43
-msgctxt "@label:PrintjobStatus"
-msgid "Unable to Slice"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:45
-msgctxt "@label:PrintjobStatus"
-msgid "Slicing unavailable"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:172
-msgctxt "@info:tooltip"
-msgid "Slice current printjob"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:172
-msgctxt "@info:tooltip"
-msgid "Cancel slicing process"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:184
-msgctxt "@label:Printjob"
-msgid "Prepare"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:184
-msgctxt "@label:Printjob"
-msgid "Cancel"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:320
-msgctxt "@info:tooltip"
-msgid "Select the active output device"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/OpenFilesIncludingProjectsDialog.qml:19
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:760
-msgctxt "@title:window"
-msgid "Open file(s)"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/OpenFilesIncludingProjectsDialog.qml:64
-msgctxt "@text:window"
-msgid ""
-"We have found one or more project file(s) within the files you have "
-"selected. You can open only one project file at a time. We suggest to only "
-"import models from those files. Would you like to proceed?"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/OpenFilesIncludingProjectsDialog.qml:99
-msgctxt "@action:button"
-msgid "Import all as models"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:19
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:24
msgctxt "@title:window"
msgid "Ultimaker Cura"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:104
-msgctxt "@title:menu menubar:toplevel"
-msgid "&File"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:120
-msgctxt "@title:menu menubar:file"
-msgid "&Save..."
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:141
-msgctxt "@title:menu menubar:file"
-msgid "&Export..."
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:151
-msgctxt "@action:inmenu menubar:file"
-msgid "Export Selection..."
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:168
-msgctxt "@title:menu menubar:toplevel"
-msgid "&Edit"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:185
-msgctxt "@title:menu"
-msgid "&View"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:190
-msgctxt "@title:menu"
-msgid "&Settings"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:192
-msgctxt "@title:menu menubar:settings"
-msgid "&Printer"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:201
-msgctxt "@title:menu"
-msgid "&Material"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:210
-msgctxt "@action:inmenu"
-msgid "Set as Active Extruder"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:216
-#: /home/ruben/Projects/Cura/resources/qml/SidebarHeader.qml:188
-msgctxt "@action:inmenu"
-msgid "Enable Extruder"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:223
-#: /home/ruben/Projects/Cura/resources/qml/SidebarHeader.qml:194
-msgctxt "@action:inmenu"
-msgid "Disable Extruder"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:235
-msgctxt "@title:menu"
-msgid "&Build plate"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:236
-msgctxt "@title:settings"
-msgid "&Profile"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:246
-msgctxt "@title:menu menubar:toplevel"
-msgid "E&xtensions"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:280
-msgctxt "@title:menu menubar:toplevel"
-msgid "&Toolbox"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:287
-msgctxt "@title:menu menubar:toplevel"
-msgid "P&references"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:295
-msgctxt "@title:menu menubar:toplevel"
-msgid "&Help"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:341
+#: /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:370
-msgctxt "@action:button"
-msgid "Open File"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:540
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:413
msgctxt "@title:tab"
msgid "Settings"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:586
-msgctxt "@title:window"
-msgid "New project"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:587
-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 ""
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:715
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:539
msgctxt "@title:window"
msgid "Closing Cura"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:716
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:728
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:540
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:552
msgctxt "@label"
msgid "Are you sure you want to exit Cura?"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:861
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:590
+#: /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:691
msgctxt "@window:title"
msgid "Install Package"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:868
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:699
msgctxt "@title:window"
msgid "Open File(s)"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:871
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:702
msgctxt "@text:window"
msgid ""
"We have found one or more G-Code files within the files you have selected. "
@@ -4420,135 +4705,14 @@ msgid ""
"file, please just select only one."
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/WorkspaceSummaryDialog.qml:14
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:805
msgctxt "@title:window"
-msgid "Save Project"
+msgid "Add Printer"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/WorkspaceSummaryDialog.qml:120
-msgctxt "@action:label"
-msgid ""
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/WorkspaceSummaryDialog.qml:137
-msgctxt "@action:label"
-msgid "Build plate"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/WorkspaceSummaryDialog.qml:169
-msgctxt "@action:label"
-msgid "Extruder %1"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/WorkspaceSummaryDialog.qml:179
-msgctxt "@action:label"
-msgid "%1 & material"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/WorkspaceSummaryDialog.qml:268
-msgctxt "@action:label"
-msgid "Don't show project summary on save again"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/WorkspaceSummaryDialog.qml:287
-msgctxt "@action:button"
-msgid "Save"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:192
-msgctxt "@label"
-msgid "Layer Height"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:277
-msgctxt "@tooltip"
-msgid ""
-"This quality profile is not available for you current material and nozzle "
-"configuration. Please change these to enable this quality profile"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:450
-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/SidebarSimple.qml:467
-msgctxt "@label"
-msgid "Print Speed"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:479
-msgctxt "@label"
-msgid "Slower"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:490
-msgctxt "@label"
-msgid "Faster"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:518
-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/SidebarSimple.qml:541
-msgctxt "@label"
-msgid "Infill"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:777
-msgctxt "@label"
-msgid ""
-"Gradual infill will gradually increase the amount of infill towards the top."
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:789
-msgctxt "@label"
-msgid "Enable gradual"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:856
-msgctxt "@label"
-msgid "Generate Support"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:890
-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/SidebarSimple.qml:962
-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/SidebarSimple.qml:985
-msgctxt "@label"
-msgid "Build Plate Adhesion"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:1040
-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/SidebarSimple.qml:1080
-msgctxt "@label"
-msgid ""
-"Need help improving your prints? Read the Ultimaker "
-"Troubleshooting Guides"
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:813
+msgctxt "@title:window"
+msgid "What's New"
msgstr ""
#: /home/ruben/Projects/Cura/resources/qml/ExtruderButton.qml:16
@@ -4558,80 +4722,493 @@ msgid_plural "Print Selected Models with %1"
msgstr[0] ""
msgstr[1] ""
-#: /home/ruben/Projects/Cura/resources/qml/AskOpenAsProjectOrModelsDialog.qml:20
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/DiscardOrKeepProfileChangesDialog.qml:15
+msgctxt "@title:window"
+msgid "Discard or Keep changes"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/DiscardOrKeepProfileChangesDialog.qml:57
+msgctxt "@text:window"
+msgid ""
+"You have customized some profile settings.\n"
+"Would you like to keep or discard those settings?"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/DiscardOrKeepProfileChangesDialog.qml:110
+msgctxt "@title:column"
+msgid "Profile settings"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/DiscardOrKeepProfileChangesDialog.qml:117
+msgctxt "@title:column"
+msgid "Default"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/DiscardOrKeepProfileChangesDialog.qml:124
+msgctxt "@title:column"
+msgid "Customized"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/DiscardOrKeepProfileChangesDialog.qml:158
+msgctxt "@option:discardOrKeep"
+msgid "Discard and never ask again"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/DiscardOrKeepProfileChangesDialog.qml:159
+msgctxt "@option:discardOrKeep"
+msgid "Keep and never ask again"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/DiscardOrKeepProfileChangesDialog.qml:196
+msgctxt "@action:button"
+msgid "Discard"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/DiscardOrKeepProfileChangesDialog.qml:209
+msgctxt "@action:button"
+msgid "Keep"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/DiscardOrKeepProfileChangesDialog.qml:222
+msgctxt "@action:button"
+msgid "Create New Profile"
+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
+msgctxt "@label"
+msgid "version: %1"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:71
+msgctxt "@label"
+msgid "End-to-end solution for fused filament 3D printing."
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:84
+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
+msgctxt "@label"
+msgid "Graphical user interface"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:135
+msgctxt "@label"
+msgid "Application framework"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:136
+msgctxt "@label"
+msgid "G-code generator"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:137
+msgctxt "@label"
+msgid "Interprocess communication library"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:139
+msgctxt "@label"
+msgid "Programming language"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:140
+msgctxt "@label"
+msgid "GUI framework"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:141
+msgctxt "@label"
+msgid "GUI framework bindings"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:142
+msgctxt "@label"
+msgid "C/C++ Binding library"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:143
+msgctxt "@label"
+msgid "Data interchange format"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:144
+msgctxt "@label"
+msgid "Support library for scientific computing"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:145
+msgctxt "@label"
+msgid "Support library for faster math"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:146
+msgctxt "@label"
+msgid "Support library for handling STL files"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:147
+msgctxt "@label"
+msgid "Support library for handling planar objects"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:148
+msgctxt "@label"
+msgid "Support library for handling triangular meshes"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:149
+msgctxt "@label"
+msgid "Support library for analysis of complex networks"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:150
+msgctxt "@label"
+msgid "Support library for handling 3MF files"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:151
+msgctxt "@label"
+msgid "Support library for file metadata and streaming"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:152
+msgctxt "@label"
+msgid "Serial communication library"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:153
+msgctxt "@label"
+msgid "ZeroConf discovery library"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:154
+msgctxt "@label"
+msgid "Polygon clipping library"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:155
+msgctxt "@Label"
+msgid "Python HTTP library"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:157
+msgctxt "@label"
+msgid "Font"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:158
+msgctxt "@label"
+msgid "SVG icons"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:159
+msgctxt "@label"
+msgid "Linux cross-distribution application deployment"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/OpenFilesIncludingProjectsDialog.qml:64
+msgctxt "@text:window"
+msgid ""
+"We have found one or more project file(s) within the files you have "
+"selected. You can open only one project file at a time. We suggest to only "
+"import models from those files. Would you like to proceed?"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/OpenFilesIncludingProjectsDialog.qml:99
+msgctxt "@action:button"
+msgid "Import all as models"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:15
+msgctxt "@title:window"
+msgid "Save Project"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:149
+msgctxt "@action:label"
+msgid "Build plate"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:183
+msgctxt "@action:label"
+msgid "Extruder %1"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:198
+msgctxt "@action:label"
+msgid "%1 & material"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:200
+msgctxt "@action:label"
+msgid "Material"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:272
+msgctxt "@action:label"
+msgid "Don't show project summary on save again"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:291
+msgctxt "@action:button"
+msgid "Save"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AskOpenAsProjectOrModelsDialog.qml:20
msgctxt "@title:window"
msgid "Open project file"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/AskOpenAsProjectOrModelsDialog.qml:93
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AskOpenAsProjectOrModelsDialog.qml:93
msgctxt "@text:window"
msgid ""
"This is a Cura project file. Would you like to open it as a project or "
"import the models from it?"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/AskOpenAsProjectOrModelsDialog.qml:103
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AskOpenAsProjectOrModelsDialog.qml:103
msgctxt "@text:window"
msgid "Remember my choice"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/AskOpenAsProjectOrModelsDialog.qml:122
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AskOpenAsProjectOrModelsDialog.qml:122
msgctxt "@action:button"
msgid "Open as project"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/AskOpenAsProjectOrModelsDialog.qml:131
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AskOpenAsProjectOrModelsDialog.qml:131
msgctxt "@action:button"
msgid "Import models"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/EngineLog.qml:15
-msgctxt "@title:window"
-msgid "Engine Log"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/SidebarHeader.qml:70
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/DropDownWidget.qml:93
msgctxt "@label"
-msgid "Printer type"
+msgid "Empty"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/SidebarHeader.qml:376
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddNetworkOrLocalPrinterContent.qml:24
msgctxt "@label"
-msgid "Material"
+msgid "Add a printer"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/SidebarHeader.qml:543
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddNetworkOrLocalPrinterContent.qml:39
msgctxt "@label"
-msgid "Use glue with this material combination"
+msgid "Add a networked printer"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/SidebarHeader.qml:575
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddNetworkOrLocalPrinterContent.qml:81
msgctxt "@label"
-msgid "Check compatibility"
+msgid "Add a non-networked printer"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/SidebarHeader.qml:593
-msgctxt "@tooltip"
-msgid "Click to check the material compatibility on Ultimaker.com."
+#: /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/ObjectsList.qml:211
-msgctxt "@option:check"
-msgid "See only current build plate"
+#: /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/ObjectsList.qml:227
-msgctxt "@action:button"
-msgid "Arrange to all build plates"
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddPrinterByIpContent.qml:158
+msgctxt "@button"
+msgid "Add"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/ObjectsList.qml:247
-msgctxt "@action:button"
-msgid "Arrange current build plate"
+#: /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:207
+msgctxt "@label"
+msgid "Printer name"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddLocalPrinterScrollView.qml:220
+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 ""
+
#: MachineSettingsAction/plugin.json
msgctxt "description"
-msgid "Provides a way to change machine settings (such as build volume, nozzle size, etc.)."
+msgid ""
+"Provides a way to change machine settings (such as build volume, nozzle "
+"size, etc.)."
msgstr ""
#: MachineSettingsAction/plugin.json
@@ -4681,7 +5258,9 @@ msgstr ""
#: ModelChecker/plugin.json
msgctxt "description"
-msgid "Checks models and print configuration for possible printing issues and give suggestions."
+msgid ""
+"Checks models and print configuration for possible printing issues and give "
+"suggestions."
msgstr ""
#: ModelChecker/plugin.json
@@ -4699,29 +5278,40 @@ msgctxt "name"
msgid "God Mode"
msgstr ""
-#: ChangeLogPlugin/plugin.json
+#: FirmwareUpdater/plugin.json
msgctxt "description"
-msgid "Shows changes since latest checked version."
+msgid "Provides a machine actions for updating firmware."
msgstr ""
-#: ChangeLogPlugin/plugin.json
+#: FirmwareUpdater/plugin.json
msgctxt "name"
-msgid "Changelog"
+msgid "Firmware Updater"
msgstr ""
#: ProfileFlattener/plugin.json
msgctxt "description"
-msgid "Create a flattend quality changes profile."
+msgid "Create a flattened quality changes profile."
msgstr ""
#: ProfileFlattener/plugin.json
msgctxt "name"
-msgid "Profile flatener"
+msgid "Profile Flattener"
+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."
+msgid ""
+"Accepts G-Code and sends them to a printer. Plugin can also update firmware."
msgstr ""
#: USBPrinting/plugin.json
@@ -4729,26 +5319,6 @@ msgctxt "name"
msgid "USB printing"
msgstr ""
-#: UserAgreement/plugin.json
-msgctxt "description"
-msgid "Ask the user once if he/she agrees with our license."
-msgstr ""
-
-#: UserAgreement/plugin.json
-msgctxt "name"
-msgid "UserAgreement"
-msgstr ""
-
-#: X3GWriter/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 ""
-
-#: X3GWriter/plugin.json
-msgctxt "name"
-msgid "X3GWriter"
-msgstr ""
-
#: GCodeGzWriter/plugin.json
msgctxt "description"
msgid "Writes g-code to a compressed archive."
@@ -4799,6 +5369,18 @@ msgctxt "name"
msgid "UM3 Network Connection"
msgstr ""
+#: SettingsGuide/plugin.json
+msgctxt "description"
+msgid ""
+"Provides extra information and explanations about settings in Cura, with "
+"images and animations."
+msgstr ""
+
+#: SettingsGuide/plugin.json
+msgctxt "name"
+msgid "Settings Guide"
+msgstr ""
+
#: MonitorStage/plugin.json
msgctxt "description"
msgid "Provides a monitor stage in Cura."
@@ -4851,7 +5433,8 @@ msgstr ""
#: SupportEraser/plugin.json
msgctxt "description"
-msgid "Creates an eraser mesh to block the printing of support in certain places"
+msgid ""
+"Creates an eraser mesh to block the printing of support in certain places"
msgstr ""
#: SupportEraser/plugin.json
@@ -4859,6 +5442,16 @@ 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."
@@ -4939,6 +5532,16 @@ 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."
@@ -4949,6 +5552,16 @@ 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."
@@ -4959,6 +5572,16 @@ 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."
@@ -5049,6 +5672,16 @@ 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."
@@ -5061,7 +5694,9 @@ msgstr ""
#: CuraPrintProfileCreator/plugin.json
msgctxt "description"
-msgid "Allows material manufacturers to create new material and quality profiles using a drop-in UI."
+msgid ""
+"Allows material manufacturers to create new material and quality profiles "
+"using a drop-in UI."
msgstr ""
#: CuraPrintProfileCreator/plugin.json
@@ -5079,9 +5714,21 @@ 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.)."
+msgid ""
+"Provides machine actions for Ultimaker machines (such as bed leveling "
+"wizard, selecting upgrades, etc.)."
msgstr ""
#: UltimakerMachineActions/plugin.json
@@ -5098,4 +5745,3 @@ msgstr ""
msgctxt "name"
msgid "Cura Profile Reader"
msgstr ""
-
diff --git a/resources/i18n/de_DE/cura.po b/resources/i18n/de_DE/cura.po
index 2b118f942e..48c0d976b5 100644
--- a/resources/i18n/de_DE/cura.po
+++ b/resources/i18n/de_DE/cura.po
@@ -1,24 +1,24 @@
# Cura
-# Copyright (C) 2018 Ultimaker
+# Copyright (C) 2019 Ultimaker B.V.
# This file is distributed under the same license as the Cura package.
-# Ruben Dulek , 2018.
+# Ruben Dulek , 2019.
#
msgid ""
msgstr ""
-"Project-Id-Version: Cura 3.5\n"
+"Project-Id-Version: Cura 4.2\n"
"Report-Msgid-Bugs-To: r.dulek@ultimaker.com\n"
-"POT-Creation-Date: 2018-09-19 17:07+0200\n"
-"PO-Revision-Date: 2018-09-28 14:42+0200\n"
-"Last-Translator: Bothof \n"
-"Language-Team: German\n"
+"POT-Creation-Date: 2019-07-16 14:38+0200\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:27
msgctxt "@action"
msgid "Machine Settings"
msgstr "Geräteeinstellungen"
@@ -48,15 +48,15 @@ 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
msgctxt "@warning:status"
-msgid "Please generate G-code before saving."
-msgstr "Generieren Sie vor dem Speichern bitte einen G-Code."
+msgid "Please prepare G-code before exporting."
+msgstr "Vor dem Exportieren bitte G-Code vorbereiten."
-#: /home/ruben/Projects/Cura/plugins/ModelChecker/ModelChecker.py:30
+#: /home/ruben/Projects/Cura/plugins/ModelChecker/ModelChecker.py:31
msgctxt "@info:title"
msgid "3D Model Assistant"
msgstr "3D-Modell-Assistent"
-#: /home/ruben/Projects/Cura/plugins/ModelChecker/ModelChecker.py:80
+#: /home/ruben/Projects/Cura/plugins/ModelChecker/ModelChecker.py:90
#, python-brace-format
msgctxt "@info:status"
msgid ""
@@ -70,10 +70,10 @@ 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 "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"
@@ -85,37 +85,36 @@ 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:40
+#: /home/ruben/Projects/Cura/plugins/AMFReader/__init__.py:15
+msgctxt "@item:inlistbox"
+msgid "AMF File"
+msgstr "AMF-Datei"
+
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:37
msgctxt "@item:inmenu"
msgid "USB printing"
msgstr "USB-Drucken"
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:41
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:38
msgctxt "@action:button Preceded by 'Ready to'."
msgid "Print via USB"
msgstr "Über USB drucken"
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:42
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:39
msgctxt "@info:tooltip"
msgid "Print via USB"
msgstr "Über USB drucken"
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:83
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:75
msgctxt "@info:status"
msgid "Connected via USB"
msgstr "Über USB verbunden"
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:103
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:100
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/X3GWriter/build/GPX-prefix/src/GPX/slicerplugins/cura15.06/X3gWriter/__init__.py:16
msgctxt "X3g Writer Plugin Description"
msgid "Writes X3g to files"
@@ -126,6 +125,11 @@ msgctxt "X3g Writer File Description"
msgid "X3g File"
msgstr "X3g-Datei"
+#: /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/GCodeGzWriter/__init__.py:17
#: /home/ruben/Projects/Cura/plugins/GCodeGzReader/__init__.py:17
msgctxt "@item:inlistbox"
@@ -137,7 +141,8 @@ msgctxt "@error:not supported"
msgid "GCodeGzWriter does not support text mode."
msgstr "GCodeWriter unterstützt keinen Textmodus."
-#: /home/ruben/Projects/Cura/plugins/UFPWriter/__init__.py:38
+#: /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"
@@ -159,7 +164,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/ClusterUM3OutputDevice.py:131
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/MeshFormatHandler.py:106
msgctxt "@info:status"
msgid "There are no file formats available to write with!"
msgstr "Es sind keine Dateiformate zum Schreiben vorhanden!"
@@ -196,9 +201,10 @@ 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/cura/Settings/CuraContainerRegistry.py:133
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:140
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1567
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py:188
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:134
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:141
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1622
msgctxt "@info:title"
msgid "Error"
msgstr "Fehler"
@@ -227,8 +233,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/CuraApplication.py:1557
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1651
+#: /home/ruben/Projects/Cura/cura/OAuth2/AuthorizationService.py:197
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1612
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1712
msgctxt "@info:title"
msgid "Warning"
msgstr "Warnhinweis"
@@ -255,274 +262,385 @@ 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:86
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:75
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:93
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:87
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:76
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:94
msgctxt "@properties:tooltip"
msgid "Print over network"
msgstr "Drücken über Netzwerk"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:88
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:95
msgctxt "@info:status"
msgid "Connected over the network."
msgstr "Über Netzwerk verbunden."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:91
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:98
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
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:100
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
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:105
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
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:108
msgctxt "@info:title"
msgid "Authentication status"
msgstr "Authentifizierungsstatus"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:103
-msgctxt "@info:status"
-msgid ""
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:104
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:110
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:114
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:116
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:120
msgctxt "@info:title"
msgid "Authentication Status"
msgstr "Authentifizierungsstatus"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:105
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:111
+#: /home/ruben/Projects/Cura/cura/OAuth2/AuthorizationService.py:198
msgctxt "@action:button"
msgid "Retry"
msgstr "Erneut versuchen"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:106
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:112
msgctxt "@info:tooltip"
msgid "Re-send the access request"
msgstr "Zugriffanforderung erneut senden"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:109
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:115
msgctxt "@info:status"
msgid "Access to the printer accepted"
msgstr "Zugriff auf den Drucker genehmigt"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:113
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:119
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:115
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/UM3InfoComponents.qml:29
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/UM3InfoComponents.qml:73
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:121
+#: /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:117
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/UM3InfoComponents.qml:28
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/UM3InfoComponents.qml:72
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:123
+#: /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:202
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:208
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:204
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:210
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:210
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:232
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:216
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:238
msgctxt "@window:title"
msgid "Mismatched configuration"
msgstr "Konfiguration nicht übereinstimmend"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:224
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:230
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:226
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:232
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:253
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:197
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:259
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:176
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:181
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:260
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:216
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:232
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:266
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:194
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:211
msgctxt "@info:status"
msgid "Sending data to printer"
msgstr "Daten werden zum Drucker gesendet"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:261
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:217
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:233
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:267
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:196
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:213
msgctxt "@info:title"
msgid "Sending Data"
msgstr "Daten werden gesendet"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:262
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:234
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxProgressButton.qml:18
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxConfirmUninstallResetDialog.qml:80
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:378
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintWindow.qml:92
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/MoreInfoWindow.qml:143
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:268
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:214
+#: /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:410
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintWindow.qml:20
+#: /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:391
-#: /home/ruben/Projects/Cura/resources/qml/OpenFilesIncludingProjectsDialog.qml:87
-#: /home/ruben/Projects/Cura/resources/qml/WorkspaceSummaryDialog.qml:279
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/OpenFilesIncludingProjectsDialog.qml:87
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:283
msgctxt "@action:button"
msgid "Cancel"
msgstr "Abbrechen"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:325
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:331
#, 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:331
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:337
#, 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:354
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:360
#, 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:363
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:369
#, 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:549
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:555
msgctxt "@window:title"
msgid "Sync with your printer"
msgstr "Synchronisieren Ihres Druckers"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:551
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:557
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:553
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:559
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:89
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:96
msgctxt "@info:status"
msgid "Connected over the network"
msgstr "Über Netzwerk verbunden"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:310
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:289
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:370
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:312
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:291
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:371
msgctxt "@info:title"
msgid "Data Sent"
msgstr "Daten gesendet"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:313
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:292
msgctxt "@action:button"
msgid "View in Monitor"
msgstr "In Monitor überwachen"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:420
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:411
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:318
#, python-brace-format
msgctxt "@info:status"
msgid "Printer '{printer_name}' has finished printing '{job_name}'."
msgstr "Drucker '{printer_name}' hat '{job_name}' vollständig gedrückt."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:422
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:413
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:322
#, 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:423
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:414
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:316
msgctxt "@info:status"
msgid "Print finished"
msgstr "Druck vollendet"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/DiscoverUM3Action.py:26
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:595
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:629
+msgctxt "@label:material"
+msgid "Empty"
+msgstr "Leer"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:596
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:630
+msgctxt "@label:material"
+msgid "Unknown"
+msgstr "Unbekannt"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:169
+msgctxt "@action:button"
+msgid "Print via Cloud"
+msgstr "Über Cloud drucken"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:170
+msgctxt "@properties:tooltip"
+msgid "Print via Cloud"
+msgstr "Über Cloud drucken"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:171
+msgctxt "@info:status"
+msgid "Connected via Cloud"
+msgstr "Über Cloud verbunden"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:182
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:359
+msgctxt "@info:title"
+msgid "Cloud error"
+msgstr "Cloudfehler"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:199
+msgctxt "@info:status"
+msgid "Could not export print job."
+msgstr "Druckauftrag konnte nicht exportiert werden."
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:358
+msgctxt "@info:text"
+msgid "Could not upload the data to the printer."
+msgstr "Daten konnten nicht in Drucker geladen werden."
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/Utils.py:51
+msgctxt "@info:status"
+msgid "tomorrow"
+msgstr "morgen"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/Utils.py:54
+msgctxt "@info:status"
+msgid "today"
+msgstr "heute"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py:187
+msgctxt "@info:description"
+msgid "There was an error connecting to the cloud."
+msgstr "Es liegt ein Fehler beim Verbinden mit der Cloud vor."
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudProgressMessage.py:14
+msgctxt "@info:status"
+msgid "Sending Print Job"
+msgstr "Druckauftrag senden"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudProgressMessage.py:15
+msgctxt "@info:status"
+msgid "Uploading via Ultimaker Cloud"
+msgstr "Über Ultimaker Cloud hochladen"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py:621
+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/UM3OutputDevicePlugin.py:627
+msgctxt "@info:status Ultimaker Cloud is a brand name and shouldn't be translated."
+msgid "Connect to Ultimaker Cloud"
+msgstr "Verbinden mit Ultimaker Cloud"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py:628
+msgctxt "@action"
+msgid "Don't ask me again for this printer."
+msgstr "Nicht mehr für diesen Drucker nachfragen."
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py:631
+msgctxt "@action"
+msgid "Get started"
+msgstr "Erste Schritte"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py:637
+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."
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py:643
+msgctxt "@info:status"
+msgid "Connected!"
+msgstr "Verbunden!"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py:645
+msgctxt "@action"
+msgid "Review your connection"
+msgstr "Ihre Verbindung überprüfen"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/DiscoverUM3Action.py:30
msgctxt "@action"
msgid "Connect via Network"
msgstr "Anschluss über Netzwerk"
-#: /home/ruben/Projects/Cura/plugins/MonitorStage/__init__.py:12
+#: /home/ruben/Projects/Cura/plugins/MonitorStage/__init__.py:14
msgctxt "@item:inmenu"
msgid "Monitor"
msgstr "Überwachen"
-#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py:68
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py:118
+msgctxt "@info"
+msgid "Could not access update information."
+msgstr "Zugriff auf Update-Informationen nicht möglich."
+
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerMessage.py:17
#, python-brace-format
msgctxt "@info Don't translate {machine_name}, since it gets replaced by a printer name!"
msgid "New features are available for your {machine_name}! It is recommended to update the firmware on your printer."
msgstr "Für Ihren {machine_name} sind neue Funktionen verfügbar! Es wird empfohlen, ein Firmware-Update für Ihren Drucker auszuführen."
-#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py:72
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerMessage.py:21
#, python-format
msgctxt "@info:title The %s gets replaced with the printer name."
msgid "New %s firmware available"
msgstr "Neue Firmware für %s verfügbar"
-#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py:75
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerMessage.py:27
msgctxt "@action:button"
msgid "How to update"
msgstr "Anleitung für die Aktualisierung"
-#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py:91
-msgctxt "@info"
-msgid "Could not access update information."
-msgstr "Zugriff auf Update-Informationen nicht möglich."
-
-#: /home/ruben/Projects/Cura/plugins/SimulationView/__init__.py:14
+#: /home/ruben/Projects/Cura/plugins/SimulationView/__init__.py:15
msgctxt "@item:inlistbox"
msgid "Layer view"
msgstr "Schichtenansicht"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.py:102
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.py:114
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:103
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.py:115
msgctxt "@info:title"
msgid "Simulation View"
msgstr "Simulationsansicht"
-#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.py:28
+#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.py:35
+msgctxt "@item:inmenu"
+msgid "Post Processing"
+msgstr "Nachbearbeitung"
+
+#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.py:36
+msgctxt "@item:inmenu"
msgid "Modify G-Code"
msgstr "G-Code ändern"
@@ -536,36 +654,6 @@ 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:43
-msgctxt "@info"
-msgid "Cura collects anonymized usage statistics."
-msgstr "Cura erfasst anonymisierte Nutzungsstatistiken."
-
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/SliceInfo.py:46
-msgctxt "@info:title"
-msgid "Collecting Data"
-msgstr "Daten werden erfasst"
-
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/SliceInfo.py:48
-msgctxt "@action:button"
-msgid "More info"
-msgstr "Mehr Infos"
-
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/SliceInfo.py:49
-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:51
-msgctxt "@action:button"
-msgid "Allow"
-msgstr "Zulassen"
-
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/SliceInfo.py:52
-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"
@@ -596,56 +684,56 @@ msgctxt "@item:inlistbox"
msgid "GIF Image"
msgstr "GIF-Bilddatei"
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:333
+#: /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:333
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:364
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:388
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:397
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:406
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:415
+#: /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:363
+#: /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:387
+#: /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:396
+#: /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:405
+#: /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:414
+#: /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. Please scale or rotate models to fit."
-msgstr "Es ist kein Objekt zum Schneiden vorhanden, da keines der Modelle der Druckabmessung entspricht. Bitte die Modelle passend skalieren oder drehen."
+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 "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:49
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py:242
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py:50
+#: /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:242
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py:256
msgctxt "@info:title"
msgid "Information"
msgstr "Informationen"
@@ -661,13 +749,11 @@ msgid "Configure Per Model Settings"
msgstr "Pro Objekteinstellungen konfigurieren"
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.py:175
-#: /home/ruben/Projects/Cura/resources/qml/PrepareSidebar.qml:576
msgctxt "@title:tab"
msgid "Recommended"
msgstr "Empfohlen"
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.py:177
-#: /home/ruben/Projects/Cura/resources/qml/PrepareSidebar.qml:581
msgctxt "@title:tab"
msgid "Custom"
msgstr "Benutzerdefiniert"
@@ -678,19 +764,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:711
+#: /home/ruben/Projects/Cura/plugins/3MFReader/ThreeMFWorkspaceReader.py:191
+#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:775
msgctxt "@label"
msgid "Nozzle"
msgstr "Düse"
-#: /home/ruben/Projects/Cura/plugins/3MFReader/ThreeMFWorkspaceReader.py:468
+#: /home/ruben/Projects/Cura/plugins/3MFReader/ThreeMFWorkspaceReader.py:474
#, 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:471
+#: /home/ruben/Projects/Cura/plugins/3MFReader/ThreeMFWorkspaceReader.py:477
msgctxt "@info:title"
msgid "Open Project File"
msgstr "Projektdatei öffnen"
@@ -705,22 +791,65 @@ msgctxt "@item:inlistbox"
msgid "G File"
msgstr "G-Datei"
-#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:317
+#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:328
msgctxt "@info:status"
msgid "Parsing G-code"
msgstr "G-Code parsen"
-#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:319
-#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:466
+#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:330
+#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:483
msgctxt "@info:title"
msgid "G-code Details"
msgstr "G-Code-Details"
-#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:464
+#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:481
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."
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/DrivePluginExtension.py:64
+msgctxt "@item:inmenu"
+msgid "Manage backups"
+msgstr "Backups verwalten"
+
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/DrivePluginExtension.py:107
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/DrivePluginExtension.py:113
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/DriveApiService.py:55
+#: /home/ruben/Projects/Cura/cura/Backups/Backup.py:104
+msgctxt "@info:title"
+msgid "Backup"
+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 "Beim Versuch, Ihre Backups aufzulisten, trat ein Fehler auf."
+
+#: /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 "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 "Backups"
+
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/UploadBackupJob.py:27
+msgctxt "@info:backup_status"
+msgid "Uploading your backup..."
+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 "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 "Ihr Backup wurde erfolgreich hochgeladen."
+
#: /home/ruben/Projects/Cura/plugins/CuraProfileWriter/__init__.py:14
#: /home/ruben/Projects/Cura/plugins/CuraProfileReader/__init__.py:14
msgctxt "@item:inlistbox"
@@ -732,7 +861,7 @@ msgctxt "@item:inmenu"
msgid "Profile Assistant"
msgstr "Profilassistent"
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/__init__.py:17
+#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/__init__.py:18
msgctxt "@item:inlistbox"
msgid "Profile Assistant"
msgstr "Profilassistent"
@@ -752,231 +881,266 @@ msgctxt "@error:zip"
msgid "Error writing 3mf file."
msgstr "Fehler beim Schreiben von 3MF-Datei."
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UM2UpgradeSelection.py:17
+#: /home/ruben/Projects/Cura/plugins/PreviewStage/__init__.py:13
+msgctxt "@item:inmenu"
+msgid "Preview"
+msgstr "Vorschau"
+
+#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UM2UpgradeSelection.py:19
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOUpgradeSelection.py:18
msgctxt "@action"
msgid "Select upgrades"
msgstr "Upgrades wählen"
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UpgradeFirmwareMachineAction.py:12
-msgctxt "@action"
-msgid "Upgrade Firmware"
-msgstr "Firmware aktualisieren"
-
-#: /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:98
-msgctxt "@tooltip"
-msgid "Outer Wall"
-msgstr "Außenwand"
+#: /home/ruben/Projects/Cura/cura/API/Account.py:82
+msgctxt "@info:title"
+msgid "Login failed"
+msgstr "Login fehlgeschlagen"
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:99
-msgctxt "@tooltip"
-msgid "Inner Walls"
-msgstr "Innenwände"
+#: /home/ruben/Projects/Cura/cura/Settings/cura_empty_instance_containers.py:33
+msgctxt "@info:not supported profile"
+msgid "Not supported"
+msgstr "Nicht unterstützt"
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:100
-msgctxt "@tooltip"
-msgid "Skin"
-msgstr "Außenhaut"
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:101
-msgctxt "@tooltip"
-msgid "Infill"
-msgstr "Füllung"
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:102
-msgctxt "@tooltip"
-msgid "Support Infill"
-msgstr "Stützstruktur-Füllung"
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:103
-msgctxt "@tooltip"
-msgid "Support Interface"
-msgstr "Stützstruktur-Schnittstelle"
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:104
-msgctxt "@tooltip"
-msgid "Support"
-msgstr "Stützstruktur"
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:105
-msgctxt "@tooltip"
-msgid "Skirt"
-msgstr "Skirt"
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:106
-msgctxt "@tooltip"
-msgid "Travel"
-msgstr "Bewegungen"
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:107
-msgctxt "@tooltip"
-msgid "Retractions"
-msgstr "Einzüge"
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:108
-msgctxt "@tooltip"
-msgid "Other"
-msgstr "Sonstige"
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:229
-msgctxt "@label unknown material"
-msgid "Unknown"
-msgstr "Unbekannt"
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:314
-#, python-brace-format
-msgctxt "@label"
-msgid "Pre-sliced file {0}"
-msgstr "Vorgeschnittene Datei {0}"
-
-#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:186
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:121
+#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:203
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:122
msgctxt "@title:window"
msgid "File Already Exists"
msgstr "Datei bereits vorhanden"
-#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:187
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:122
+#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:204
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:123
#, 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/ExtrudersModel.py:212
-msgctxt "@menuitem"
-msgid "Not overridden"
-msgstr "Nicht überschrieben"
-
-#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:120
+#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:427
+#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:430
msgctxt "@info:status"
-msgid "The selected material is incompatible with the selected machine or configuration."
-msgstr "Das gewählte Material ist mit der gewählten Maschine oder Konfiguration nicht kompatibel."
+msgid "Invalid file URL:"
+msgstr "Ungültige Datei-URL:"
-#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:121
-msgctxt "@info:title"
-msgid "Incompatible Material"
-msgstr "Material nicht kompatibel"
+#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:925
+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:863
-#, 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:865
+#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:927
msgctxt "@info:title"
msgid "Settings updated"
msgstr "Einstellungen aktualisiert"
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:131
+#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:1481
+msgctxt "@info:title"
+msgid "Extruder(s) Disabled"
+msgstr "Extruder deaktiviert"
+
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:132
#, 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:139
#, 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:144
#, 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:145
msgctxt "@info:title"
msgid "Export succeeded"
msgstr "Export erfolgreich ausgeführt"
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:170
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:194
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:313
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:172
#, python-brace-format
-msgctxt "@info:status Don't translate the XML tags or !"
-msgid "Failed to import profile from {0}: {1}"
-msgstr "Import des Profils aus Datei {0} fehlgeschlagen: {1}"
+msgctxt "@info:status Don't translate the XML tags !"
+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:176
#, python-brace-format
-msgctxt "@info:status Don't translate the XML tags or !"
+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:192
+#, 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:218
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:228
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:196
#, python-brace-format
-msgctxt "@info:status Don't translate the XML tags or !"
+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:220
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:230
+#, 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:243
#, python-brace-format
-msgctxt "@info:status Don't translate the XML tags or !"
+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:316
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:315
+#, python-brace-format
+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:"
+
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:318
#, 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:321
#, 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:324
#, 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:359
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:375
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:389
#, 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:59
+#: /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:306
+#, python-brace-format
+msgctxt "@label"
+msgid "Pre-sliced file {0}"
+msgstr "Vorgeschnittene Datei {0}"
+
+#: /home/ruben/Projects/Cura/cura/UI/WelcomePagesModel.py:56
+#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/ProfileCreatorTabControls.qml:62
+msgctxt "@action:button"
+msgid "Next"
+msgstr "Weiter"
+
+#: /home/ruben/Projects/Cura/cura/UI/ObjectsModel.py:61
#, 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/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:124
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:168
+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:91
+#: /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/ExtrudersModel.py:208
+msgctxt "@menuitem"
+msgid "Not overridden"
+msgstr "Nicht überschrieben"
#: /home/ruben/Projects/Cura/cura/Machines/Models/QualityManagementModel.py:109
#, python-brace-format
@@ -989,45 +1153,79 @@ msgctxt "@item:inlistbox"
msgid "All Files (*)"
msgstr "Alle Dateien (*)"
-#: /home/ruben/Projects/Cura/cura/Machines/MaterialManager.py:609
+#: /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
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:269
+msgctxt "@label"
+msgid "Unknown"
+msgstr "Unbekannt"
+
+#: /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/Machines/MaterialManager.py:689
msgctxt "@label"
msgid "Custom Material"
msgstr "Benutzerdefiniertes Material"
-#: /home/ruben/Projects/Cura/cura/Machines/MaterialManager.py:610
+#: /home/ruben/Projects/Cura/cura/Machines/MaterialManager.py:690
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/ConfigurationMenu.qml:203
msgctxt "@label"
msgid "Custom"
msgstr "Benutzerdefiniert"
-#: /home/ruben/Projects/Cura/cura/BuildVolume.py:81
+#: /home/ruben/Projects/Cura/cura/BuildVolume.py:89
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:91
msgctxt "@info:title"
msgid "Build Volume"
msgstr "Produktabmessungen"
-#: /home/ruben/Projects/Cura/cura/Backups/Backup.py:97
+#: /home/ruben/Projects/Cura/cura/Backups/Backup.py:99
msgctxt "@info:backup_failed"
msgid "Could not create archive from user data directory: {}"
msgstr "Konnte kein Archiv von Benutzer-Datenverzeichnis {} erstellen"
-#: /home/ruben/Projects/Cura/cura/Backups/Backup.py:102
-msgctxt "@info:title"
-msgid "Backup"
-msgstr "Backup"
-
-#: /home/ruben/Projects/Cura/cura/Backups/Backup.py:112
+#: /home/ruben/Projects/Cura/cura/Backups/Backup.py:114
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:122
+#: /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/AuthorizationHelpers.py:79
+msgctxt "@message"
+msgid "Could not read response."
+msgstr "Antwort konnte nicht gelesen werden."
+
+#: /home/ruben/Projects/Cura/cura/OAuth2/AuthorizationService.py:197
+msgctxt "@info"
+msgid "Unable to reach the Ultimaker account server."
+msgstr "Der Ultimaker-Konto-Server konnte nicht erreicht werden."
+
+#: /home/ruben/Projects/Cura/cura/OAuth2/AuthorizationRequestHandler.py:66
+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:73
+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:27
msgctxt "@info:status"
@@ -1035,42 +1233,46 @@ msgid "Multiplying and placing objects"
msgstr "Objekte vervielfältigen und platzieren"
#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:28
+msgctxt "@info:title"
+msgid "Placing Objects"
+msgstr "Objekte platzieren"
+
+#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:100
+#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsJob.py:103
+#: /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
msgctxt "@info:title"
msgid "Placing Object"
msgstr "Objekt-Platzierung"
-#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:100
-#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsJob.py:96
-#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsAllBuildPlatesJob.py:150
-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/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:97
-#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsAllBuildPlatesJob.py:151
+#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsJob.py:104
+#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsAllBuildPlatesJob.py:150
msgctxt "@info:title"
msgid "Can't Find Location"
msgstr "Kann Position nicht finden"
-#: /home/ruben/Projects/Cura/cura/CrashHandler.py:87
+#: /home/ruben/Projects/Cura/cura/CrashHandler.py:83
msgctxt "@title:window"
msgid "Cura can't start"
msgstr "Cura kann nicht starten"
-#: /home/ruben/Projects/Cura/cura/CrashHandler.py:93
+#: /home/ruben/Projects/Cura/cura/CrashHandler.py:89
msgctxt "@label crash message"
msgid ""
"
Oops, Ultimaker Cura has encountered something that doesn't seem right.
\n"
@@ -1085,32 +1287,32 @@ msgstr ""
"
Senden Sie uns diesen Absturzbericht bitte, um das Problem zu beheben.
"
-#: /home/ruben/Projects/Cura/cura/CrashHandler.py:222
+#: /home/ruben/Projects/Cura/cura/CrashHandler.py:218
msgctxt "@title:groupbox"
msgid "Error traceback"
msgstr "Fehler-Rückverfolgung"
-#: /home/ruben/Projects/Cura/cura/CrashHandler.py:303
+#: /home/ruben/Projects/Cura/cura/CrashHandler.py:299
msgctxt "@title:groupbox"
msgid "Logs"
msgstr "Protokolle"
-#: /home/ruben/Projects/Cura/cura/CrashHandler.py:326
+#: /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:345
+#: /home/ruben/Projects/Cura/cura/CrashHandler.py:342
msgctxt "@action:button"
msgid "Send report"
msgstr "Bericht senden"
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:454
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:504
msgctxt "@info:progress"
msgid "Loading machines..."
msgstr "Geräte werden geladen..."
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:748
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:819
msgctxt "@info:progress"
msgid "Setting up scene..."
msgstr "Die Szene wird eingerichtet..."
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:784
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:854
msgctxt "@info:progress"
msgid "Loading interface..."
msgstr "Die Benutzeroberfläche wird geladen..."
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:997
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1133
#, 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:1556
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1611
#, 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:1566
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1621
#, 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:1650
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1711
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:61
-msgctxt "@title"
-msgid "Machine Settings"
-msgstr "Geräteeinstellungen"
-
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:80
-msgctxt "@title:tab"
-msgid "Printer"
-msgstr "Drucker"
-
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:99
-msgctxt "@label"
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:58
+msgctxt "@title:label"
msgid "Printer Settings"
msgstr "Druckereinstellungen"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:110
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:72
msgctxt "@label"
msgid "X (Width)"
msgstr "X (Breite)"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:111
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:121
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:131
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:237
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:386
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:402
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:420
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:432
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:857
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:76
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:90
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:104
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:194
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:213
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:232
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:253
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:272
+#: /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:120
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:86
msgctxt "@label"
msgid "Y (Depth)"
msgstr "Y (Tiefe)"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:130
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:100
msgctxt "@label"
msgid "Z (Height)"
msgstr "Z (Höhe)"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:142
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:114
msgctxt "@label"
msgid "Build plate shape"
msgstr "Druckbettform"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:151
-msgctxt "@option:check"
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:127
+msgctxt "@label"
msgid "Origin at center"
msgstr "Ausgang in Mitte"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:159
-msgctxt "@option:check"
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:139
+msgctxt "@label"
msgid "Heated bed"
msgstr "Heizbares Bett"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:170
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:151
msgctxt "@label"
msgid "G-code flavor"
msgstr "G-Code-Variante"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:183
-msgctxt "@label"
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:176
+msgctxt "@title:label"
msgid "Printhead Settings"
msgstr "Druckkopfeinstellungen"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:193
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:190
msgctxt "@label"
msgid "X min"
msgstr "X min."
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:194
-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:203
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:209
msgctxt "@label"
msgid "Y min"
msgstr "Y min."
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:204
-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:213
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:228
msgctxt "@label"
msgid "X max"
msgstr "X max."
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:214
-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:223
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:249
msgctxt "@label"
msgid "Y max"
msgstr "Y max."
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:224
-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:236
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:268
msgctxt "@label"
-msgid "Gantry height"
+msgid "Gantry Height"
msgstr "Brückenhöhe"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:238
-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:257
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:282
msgctxt "@label"
msgid "Number of Extruders"
msgstr "Anzahl Extruder"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:313
-msgctxt "@label"
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:341
+msgctxt "@title:label"
msgid "Start G-code"
-msgstr "Start G-code"
+msgstr "Start G-Code"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:323
-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:332
-msgctxt "@label"
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:355
+msgctxt "@title:label"
msgid "End G-code"
-msgstr "Ende G-code"
+msgstr "Ende G-Code"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:342
-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:373
-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:385
+#: /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:401
+#: /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:403
-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:419
+#: /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:431
+#: /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/MachineSettingsExtruderTab.qml:162
+msgctxt "@title:label"
msgid "Extruder Start G-code"
msgstr "G-Code Extruder-Start"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:470
-msgctxt "@label"
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsExtruderTab.qml:176
+msgctxt "@title:label"
msgid "Extruder End G-code"
msgstr "G-Code Extruder-Ende"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxProgressButton.qml:17
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxProgressButton.qml:18
msgctxt "@action:button"
msgid "Install"
msgstr "Installieren"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxProgressButton.qml:19
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxProgressButton.qml:20
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailTileActions.qml:46
msgctxt "@action:button"
msgid "Installed"
msgstr "Installiert"
@@ -1435,68 +1601,82 @@ msgctxt "@info"
msgid "Could not connect to the Cura Package database. Please check your connection."
msgstr "Verbindung zur Cura Paket-Datenbank konnte nicht hergestellt werden. Bitte überprüfen Sie Ihre Verbindung."
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/SmallRatingWidget.qml:27
+msgctxt "@label"
+msgid "ratings"
+msgstr "Bewertungen"
+
#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledPage.qml:38
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxHeader.qml:26
+#: /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:75
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:66
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:544
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledPage.qml:70
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxHeader.qml:44
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:80
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:417
msgctxt "@title:tab"
msgid "Materials"
msgstr "Materialien"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml:80
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml:91
+msgctxt "@label"
+msgid "Your rating"
+msgstr "Ihre Bewertung"
+
+#: /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:86
+#: /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:92
+#: /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:98
+#: /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:117
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml:159
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:255
-msgctxt "@label"
-msgid "Unknown"
-msgstr "Unbekannt"
+#: /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 "Anmeldung für Installation oder Update erforderlich"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailTileActions.qml:44
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml:30
+#: /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:45
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml:31
+#: /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:46
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml:32
+#: /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"
msgstr "Aktualisiert"
#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/Toolbox.qml:13
msgctxt "@title"
-msgid "Toolbox"
-msgstr "Toolbox"
+msgid "Marketplace"
+msgstr "Marktplatz"
#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxBackColumn.qml:25
msgctxt "@action:button"
@@ -1505,8 +1685,8 @@ msgstr "Zurück"
#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxConfirmUninstallResetDialog.qml:20
msgctxt "@title:window"
-msgid "Confirm uninstall "
-msgstr "Deinstallieren bestätigen "
+msgid "Confirm uninstall"
+msgstr "Deinstallieren bestätigen"
#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxConfirmUninstallResetDialog.qml:50
msgctxt "@text:window"
@@ -1523,17 +1703,27 @@ msgctxt "@text:window"
msgid "Profiles"
msgstr "Profile"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxConfirmUninstallResetDialog.qml:89
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxConfirmUninstallResetDialog.qml:90
msgctxt "@action:button"
msgid "Confirm"
msgstr "Bestätigen"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxFooter.qml:17
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/RatingWidget.qml:54
+msgctxt "@label"
+msgid "You need to login first before you can rate"
+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 "Vor der Bewertung müssen Sie das Paket installierten"
+
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxFooter.qml:19
msgctxt "@info"
msgid "You will need to restart Cura before changes in packages have effect."
msgstr "Cura muss neu gestartet werden, um die Änderungen der Pakete zu übernehmen."
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxFooter.qml:34
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxFooter.qml:45
msgctxt "@info:button"
msgid "Quit Cura"
msgstr "Quit Cura"
@@ -1553,22 +1743,27 @@ msgctxt "@label"
msgid "Generic Materials"
msgstr "Generische Materialien"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxHeader.qml:54
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxHeader.qml:59
msgctxt "@title:tab"
msgid "Installed"
msgstr "Installiert"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml:19
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml:22
msgctxt "@label"
msgid "Will install upon restarting"
msgstr "Installiert nach Neustart"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml:51
+#: /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 "Anmeldung für Update erforderlich"
+
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml:71
msgctxt "@action:button"
msgid "Downgrade"
msgstr "Downgraden"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml:51
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml:71
msgctxt "@action:button"
msgid "Uninstall"
msgstr "Deinstallieren"
@@ -1589,12 +1784,12 @@ msgstr ""
"Sie müssen diese Lizenz akzeptieren, um das Plugin zu installieren.\n"
"Stimmen Sie den nachfolgenden Bedingungen zu?"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxLicenseDialog.qml:54
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxLicenseDialog.qml:55
msgctxt "@action:button"
msgid "Accept"
msgstr "Akzeptieren"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxLicenseDialog.qml:65
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxLicenseDialog.qml:66
msgctxt "@action:button"
msgid "Decline"
msgstr "Ablehnen"
@@ -1604,22 +1799,42 @@ msgctxt "@label"
msgid "Featured"
msgstr "Unterstützter"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:31
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:66
msgctxt "@label"
msgid "Compatibility"
msgstr "Kompatibilität"
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:203
+msgctxt "@action:label"
+msgid "Technical Data Sheet"
+msgstr "Technisches Datenblatt"
+
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:212
+msgctxt "@action:label"
+msgid "Safety Data Sheet"
+msgstr "Sicherheitsdatenblatt"
+
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:221
+msgctxt "@action:label"
+msgid "Printing Guidelines"
+msgstr "Druckrichtlinien"
+
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:230
+msgctxt "@action:label"
+msgid "Website"
+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:88
+#: /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:94
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxAuthorPage.qml:98
msgctxt "@label"
msgid "Email"
msgstr "E-Mail"
@@ -1629,422 +1844,593 @@ 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
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:31
+msgctxt "@title"
+msgid "Update Firmware"
+msgstr "Firmware aktualisieren"
+
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:39
msgctxt "@label"
-msgid "Changelog"
-msgstr "Änderungsprotokoll"
+msgid "Firmware is the piece of software running directly on your 3D printer. This firmware controls the step motors, regulates the temperature and ultimately makes your printer work."
+msgstr "Die Firmware ist der Teil der Software, der direkt auf Ihrem 3D-Drucker läuft. Diese Firmware kontrolliert die Schrittmotoren, reguliert die Temperatur und sorgt letztlich dafür, dass Ihr Drucker funktioniert."
-#: /home/ruben/Projects/Cura/plugins/ChangeLogPlugin/ChangeLog.qml:37
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/FirmwareUpdateWindow.qml:84
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/UM3InfoComponents.qml:56
-#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.qml:464
-#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:508
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:121
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:148
-#: /home/ruben/Projects/Cura/resources/qml/EngineLog.qml:38
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:46
+msgctxt "@label"
+msgid "The firmware shipping with new printers works, but new versions tend to have more features and improvements."
+msgstr "Die mit neuen Druckern gelieferte Firmware funktioniert, allerdings enthalten neue Versionen üblicherweise mehr Funktionen und Verbesserungen."
+
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:58
msgctxt "@action:button"
-msgid "Close"
-msgstr "Schließen"
+msgid "Automatically upgrade Firmware"
+msgstr "Firmware automatisch aktualisieren"
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/FirmwareUpdateWindow.qml:22
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:69
+msgctxt "@action:button"
+msgid "Upload custom Firmware"
+msgstr "Benutzerdefinierte Firmware hochladen"
+
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:83
+msgctxt "@label"
+msgid "Firmware can not be updated because there is no connection with the printer."
+msgstr "Firmware kann nicht aktualisiert werden, da keine Verbindung zum Drucker besteht."
+
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:91
+msgctxt "@label"
+msgid "Firmware can not be updated because the connection with the printer does not support upgrading firmware."
+msgstr "Firmware kann nicht aktualisiert werden, da die Verbindung zum Drucker die Firmware-Aktualisierung nicht unterstützt."
+
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:98
+msgctxt "@title:window"
+msgid "Select custom firmware"
+msgstr "Benutzerdefinierte Firmware wählen"
+
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:119
msgctxt "@title:window"
msgid "Firmware Update"
msgstr "Firmware-Aktualisierung"
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/FirmwareUpdateWindow.qml:42
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:143
msgctxt "@label"
msgid "Updating firmware."
msgstr "Die Firmware wird aktualisiert."
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/FirmwareUpdateWindow.qml:44
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:145
msgctxt "@label"
msgid "Firmware update completed."
msgstr "Firmware-Aktualisierung abgeschlossen."
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/FirmwareUpdateWindow.qml:46
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:147
msgctxt "@label"
msgid "Firmware update failed due to an unknown error."
msgstr "Die Firmware-Aktualisierung ist aufgrund eines unbekannten Fehlers fehlgeschlagen."
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/FirmwareUpdateWindow.qml:48
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:149
msgctxt "@label"
msgid "Firmware update failed due to an communication error."
msgstr "Die Firmware-Aktualisierung ist aufgrund eines Kommunikationsfehlers fehlgeschlagen."
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/FirmwareUpdateWindow.qml:50
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:151
msgctxt "@label"
msgid "Firmware update failed due to an input/output error."
msgstr "Die Firmware-Aktualisierung ist aufgrund eines Eingabe-/Ausgabefehlers fehlgeschlagen."
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/FirmwareUpdateWindow.qml:52
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:153
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:144
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobCard.qml:181
+#: /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/DiscoverUM3Action.qml:43
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:208
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobCard.qml:249
+msgctxt "@info"
+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
+msgctxt "@info"
+msgid "The webcam is not available because you are monitoring a cloud printer."
+msgstr "Die Webcam ist nicht verfügbar, weil Sie einen Cloud-Drucker überwachen."
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:300
+msgctxt "@label:status"
+msgid "Loading..."
+msgstr "Lädt..."
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:304
+msgctxt "@label:status"
+msgid "Unavailable"
+msgstr "Nicht verfügbar"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:308
+msgctxt "@label:status"
+msgid "Unreachable"
+msgstr "Nicht erreichbar"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:312
+msgctxt "@label:status"
+msgid "Idle"
+msgstr "Leerlauf"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:353
+msgctxt "@label"
+msgid "Untitled"
+msgstr "Unbenannt"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:374
+msgctxt "@label"
+msgid "Anonymous"
+msgstr "Anonym"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:401
+msgctxt "@label:status"
+msgid "Requires configuration changes"
+msgstr "Erfordert Konfigurationsänderungen"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:439
+msgctxt "@action:button"
+msgid "Details"
+msgstr "Details"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobCard.qml:130
+msgctxt "@label"
+msgid "Unavailable printer"
+msgstr "Drucker nicht verfügbar"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobCard.qml:132
+msgctxt "@label"
+msgid "First available"
+msgstr "Zuerst verfügbar"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml:31
+msgctxt "@label"
+msgid "Queued"
+msgstr "In Warteschlange"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml:67
+msgctxt "@label link to connect manager"
+msgid "Manage in browser"
+msgstr "Im Browser verwalten"
+
+#: /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:116
+msgctxt "@label"
+msgid "Print jobs"
+msgstr "Druckaufträge"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml:132
+msgctxt "@label"
+msgid "Total print time"
+msgstr "Druckdauer insgesamt"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml:148
+msgctxt "@label"
+msgid "Waiting for"
+msgstr "Warten auf"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:50
msgctxt "@window:title"
msgid "Existing Connection"
msgstr "Vorhandene Verbindung"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:45
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:52
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:62
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:69
msgctxt "@title:window"
msgid "Connect to Networked Printer"
msgstr "Anschluss an vernetzten Drucker"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:72
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:81
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:82
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:42
-msgctxt "@action:button"
-msgid "Add"
-msgstr "Hinzufügen"
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:81
+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:92
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:101
msgctxt "@action:button"
msgid "Edit"
msgstr "Bearbeiten"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:103
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:128
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:48
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:117
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:112
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:146
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:55
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:121
msgctxt "@action:button"
msgid "Remove"
msgstr "Entfernen"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:111
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:120
msgctxt "@action:button"
msgid "Refresh"
msgstr "Aktualisieren"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:204
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:215
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:231
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:244
+#: /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:268
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:283
+#: /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:280
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:297
+#: /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:302
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:321
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:306
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:325
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:316
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:336
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:321
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/UM3InfoComponents.qml:39
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:341
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/UM3InfoComponents.qml:74
msgctxt "@action:button"
msgid "Connect"
msgstr "Verbinden"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:335
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:354
+msgctxt "@title:window"
+msgid "Invalid IP address"
+msgstr "Ungültige IP-Adresse"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:355
+#: /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:366
msgctxt "@title:window"
msgid "Printer Address"
msgstr "Druckeradresse"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:358
-msgctxt "@alabel"
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:389
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddPrinterByIpContent.qml:102
+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."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:387
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/MoreInfoWindow.qml:132
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:419
+#: /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/PrintWindow.qml:34
-msgctxt "@title:window"
-msgid "Print over network"
-msgstr "Drucken über Netzwerk"
+#: /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/PrintWindow.qml:65
-msgctxt "@label"
-msgid "Printer selection"
-msgstr "Druckerauswahl"
+#: /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/PrintWindow.qml:105
+#: /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 "Vorbereitung..."
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:88
+msgctxt "@label:status"
+msgid "Aborting..."
+msgstr "Wird abgebrochen..."
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:92
+msgctxt "@label:status"
+msgid "Pausing..."
+msgstr "Wird pausiert..."
+
+#: /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:96
+msgctxt "@label:status"
+msgid "Resuming..."
+msgstr "Wird fortgesetzt..."
+
+#: /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:100
+msgctxt "@label:status"
+msgid "Finishes %1 at %2"
+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/PrintJobInfoBlock.qml:142
-msgctxt "@label"
-msgid "Waiting for: Unavailable printer"
-msgstr "Warten auf: Drucker nicht verfügbar"
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintWindow.qml:47
+msgctxt "@title:window"
+msgid "Print over network"
+msgstr "Drucken über Netzwerk"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintJobInfoBlock.qml:144
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintWindow.qml:79
msgctxt "@label"
-msgid "Waiting for: First available"
-msgstr "Warten auf: Ersten verfügbaren"
+msgid "Printer selection"
+msgstr "Druckerauswahl"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintJobInfoBlock.qml:148
-msgctxt "@label"
-msgid "Waiting for: "
-msgstr "Warten auf: "
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintJobInfoBlock.qml:213
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:54
msgctxt "@label"
msgid "Move to top"
msgstr "Vorziehen"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintJobInfoBlock.qml:234
-msgctxt "@window:title"
-msgid "Move print job to top"
-msgstr "Druckauftrag vorziehen"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintJobInfoBlock.qml:236
-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 "Soll dieser %1 wirklich an den Anfang der Warteschlange vorgezogen werden?"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintJobInfoBlock.qml:245
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:70
msgctxt "@label"
msgid "Delete"
msgstr "Löschen"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintJobInfoBlock.qml:264
-msgctxt "@window:title"
-msgid "Delete print job"
-msgstr "Druckauftrag löschen"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintJobInfoBlock.qml:266
-msgctxt "@label %1 is the name of a print job."
-msgid "Are you sure you want to delete %1?"
-msgstr "Soll %1 wirklich gelöscht werden?"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/ClusterMonitorItem.qml:32
-msgctxt "@label link to connect manager"
-msgid "Manage queue"
-msgstr "Warteschlange verwalten"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/ClusterMonitorItem.qml:54
-msgctxt "@label"
-msgid "Queued"
-msgstr "In Warteschlange"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/ClusterControlItem.qml:44
-msgctxt "@label"
-msgid "Printing"
-msgstr "Drucken"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/ClusterControlItem.qml:54
-msgctxt "@label link to connect manager"
-msgid "Manage printers"
-msgstr "Drucker verwalten"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/ClusterControlItem.qml:212
-msgctxt "@label"
-msgid "Not available"
-msgstr "Nicht verfügbar"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/ClusterControlItem.qml:215
-msgctxt "@label"
-msgid "Unreachable"
-msgstr "Nicht erreichbar"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/ClusterControlItem.qml:221
-msgctxt "@label"
-msgid "Available"
-msgstr "Verfügbar"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/ClusterControlItem.qml:416
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:100
#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:289
msgctxt "@label"
msgid "Resume"
msgstr "Zurückkehren"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/ClusterControlItem.qml:416
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:102
+msgctxt "@label"
+msgid "Pausing..."
+msgstr "Wird pausiert..."
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:104
+msgctxt "@label"
+msgid "Resuming..."
+msgstr "Wird fortgesetzt..."
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:106
#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:284
#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:293
msgctxt "@label"
msgid "Pause"
msgstr "Pausieren"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/ClusterControlItem.qml:444
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:124
+msgctxt "@label"
+msgid "Aborting..."
+msgstr "Wird abgebrochen..."
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:124
msgctxt "@label"
msgid "Abort"
msgstr "Abbrechen"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/ClusterControlItem.qml:464
+#: /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 "Soll dieser %1 wirklich an den Anfang der Warteschlange vorgezogen werden?"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:144
+msgctxt "@window:title"
+msgid "Move print job to top"
+msgstr "Druckauftrag vorziehen"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:153
+msgctxt "@label %1 is the name of a print job."
+msgid "Are you sure you want to delete %1?"
+msgstr "Soll %1 wirklich gelöscht werden?"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:154
+msgctxt "@window:title"
+msgid "Delete print job"
+msgstr "Druckauftrag löschen"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:163
+msgctxt "@label %1 is the name of a print job."
+msgid "Are you sure you want to abort %1?"
+msgstr "Möchten Sie %1 wirklich abbrechen?"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:164
#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:335
msgctxt "@window:title"
msgid "Abort print"
msgstr "Drucken abbrechen"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/ClusterControlItem.qml:466
-msgctxt "@label %1 is the name of a print job."
-msgid "Are you sure you want to abort %1?"
-msgstr "Möchten Sie %1 wirklich abbrechen?"
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:20
+msgctxt "@title:window"
+msgid "Configuration Changes"
+msgstr "Konfigurationsänderungen"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/ClusterControlItem.qml:665
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/ClusterControlItem.qml:673
-msgctxt "@label:status"
-msgid "Aborted"
-msgstr "Abgebrochen"
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:27
+msgctxt "@action:button"
+msgid "Override"
+msgstr "Überschreiben"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/ClusterControlItem.qml:667
-msgctxt "@label:status"
-msgid "Finished"
-msgstr "Beendet"
+#: /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] "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/ClusterControlItem.qml:670
-msgctxt "@label:status"
-msgid "Preparing"
-msgstr "Vorbereitung"
+#: /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/ClusterControlItem.qml:675
-msgctxt "@label:status"
-msgid "Pausing"
-msgstr "Wird pausiert"
+#: /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/ClusterControlItem.qml:677
-msgctxt "@label:status"
-msgid "Paused"
-msgstr "Pausiert"
+#: /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/ClusterControlItem.qml:679
-msgctxt "@label:status"
-msgid "Resuming"
-msgstr "Wird fortgesetzt"
+#: /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/ClusterControlItem.qml:681
-msgctxt "@label:status"
-msgid "Action required"
-msgstr "Handlung erforderlich"
+#: /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/UM3InfoComponents.qml:38
+#: /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 "Ü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: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/UM3NetworkPrinting/resources/qml/UM3InfoComponents.qml:117
-msgctxt "@info:tooltip"
-msgid "Load the configuration of the printer into Cura"
-msgstr "Die Druckerkonfiguration in Cura laden"
+#: /home/ruben/Projects/Cura/plugins/SettingsGuide/resources/qml/SettingsGuide.qml:16
+msgctxt "@title"
+msgid "Cura Settings Guide"
+msgstr "Anleitung für Cura-Einstellungen"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/UM3InfoComponents.qml:118
-msgctxt "@action:button"
-msgid "Activate Configuration"
-msgstr "Konfiguration aktivieren"
+#: /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.\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/SimulationView/SimulationView.qml:130
+#: /home/ruben/Projects/Cura/plugins/MonitorStage/MonitorMain.qml:117
+msgctxt "@info"
+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:156
+msgctxt "@label link to technical assistance"
+msgid "View user manuals online"
+msgstr "Benutzerhandbücher online anzeigen"
+
+#: /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/SimulationView.qml:145
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:107
msgctxt "@label:listbox"
msgid "Material Color"
msgstr "Materialfarbe"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:149
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:111
msgctxt "@label:listbox"
msgid "Line Type"
msgstr "Linientyp"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:153
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:115
msgctxt "@label:listbox"
msgid "Feedrate"
msgstr "Vorschub"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:157
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:119
msgctxt "@label:listbox"
msgid "Layer thickness"
msgstr "Schichtdicke"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:198
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:156
msgctxt "@label"
msgid "Compatibility Mode"
msgstr "Kompatibilitätsmodus"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:284
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:230
msgctxt "@label"
-msgid "Show Travels"
-msgstr "Bewegungen anzeigen"
+msgid "Travels"
+msgstr "Bewegungen"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:290
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:236
msgctxt "@label"
-msgid "Show Helpers"
-msgstr "Helfer anzeigen"
+msgid "Helpers"
+msgstr "Helfer"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:296
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:242
msgctxt "@label"
-msgid "Show Shell"
-msgstr "Gehäuse anzeigen"
+msgid "Shell"
+msgstr "Gehäuse"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:302
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:248
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedInfillDensitySelector.qml:65
msgctxt "@label"
-msgid "Show Infill"
-msgstr "Füllung anzeigen"
+msgid "Infill"
+msgstr "Füllung"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:355
+#: /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/SimulationView.qml:366
+#: /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/SimulationView.qml:379
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:322
msgctxt "@label"
msgid "Top / Bottom"
msgstr "Oben/Unten"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:383
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:326
msgctxt "@label"
msgid "Inner Wall"
msgstr "Innenwand"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:448
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:384
msgctxt "@label"
msgid "min"
msgstr "min."
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:500
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:433
msgctxt "@label"
msgid "max"
msgstr "max."
@@ -2059,40 +2445,40 @@ msgctxt "@label"
msgid "Post Processing Scripts"
msgstr "Skripts Nachbearbeitung"
-#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.qml:225
+#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.qml:233
msgctxt "@action"
msgid "Add a script"
msgstr "Ein Skript hinzufügen"
-#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.qml:271
+#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.qml:279
msgctxt "@label"
msgid "Settings"
msgstr "Einstellungen"
-#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.qml:474
+#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.qml:493
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 these data"
-msgstr "Ich möchte diese Daten nicht senden"
+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 these data to Ultimaker and help us improve Cura"
-msgstr "Ich erlaube das Senden dieser Daten an Ultimaker, um Cura zu verbessern"
+msgid "Allow sending anonymous data"
+msgstr "Senden von anonymen Daten erlauben"
#: /home/ruben/Projects/Cura/plugins/ImageReader/ConfigUI.qml:19
msgctxt "@title:window"
@@ -2141,19 +2527,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."
@@ -2194,18 +2580,18 @@ 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:341
+#: /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:383
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:388
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/resources/qml/Preferences/SettingVisibilityPage.qml:98
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/SettingVisibilityPage.qml:94
msgctxt "@label:textbox"
msgid "Filter..."
msgstr "Filtern..."
@@ -2232,13 +2618,13 @@ msgid "Create new"
msgstr "Neu erstellen"
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:70
-#: /home/ruben/Projects/Cura/resources/qml/WorkspaceSummaryDialog.qml:72
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:73
msgctxt "@action:title"
msgid "Summary - Cura Project"
msgstr "Zusammenfassung – Cura-Projekt"
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:92
-#: /home/ruben/Projects/Cura/resources/qml/WorkspaceSummaryDialog.qml:96
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:97
msgctxt "@action:label"
msgid "Printer settings"
msgstr "Druckereinstellungen"
@@ -2255,18 +2641,19 @@ msgid "Update"
msgstr "Aktualisierung"
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:143
-#: /home/ruben/Projects/Cura/resources/qml/WorkspaceSummaryDialog.qml:105
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:106
msgctxt "@action:label"
msgid "Type"
msgstr "Typ"
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:159
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:121
msgctxt "@action:label"
msgid "Printer Group"
msgstr "Druckergruppe"
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:180
-#: /home/ruben/Projects/Cura/resources/qml/WorkspaceSummaryDialog.qml:196
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:226
msgctxt "@action:label"
msgid "Profile settings"
msgstr "Profileinstellungen"
@@ -2278,19 +2665,20 @@ 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/resources/qml/WorkspaceSummaryDialog.qml:220
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:121
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:250
msgctxt "@action:label"
msgid "Name"
msgstr "Name"
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:231
-#: /home/ruben/Projects/Cura/resources/qml/WorkspaceSummaryDialog.qml:204
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:234
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/WorkspaceSummaryDialog.qml:209
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:239
msgctxt "@action:label"
msgid "%1 override"
msgid_plural "%1 overrides"
@@ -2320,7 +2708,6 @@ 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/resources/qml/WorkspaceSummaryDialog.qml:237
msgctxt "@action:label"
msgid "Setting visibility"
msgstr "Sichtbarkeit einstellen"
@@ -2331,13 +2718,11 @@ msgid "Mode"
msgstr "Modus"
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:352
-#: /home/ruben/Projects/Cura/resources/qml/WorkspaceSummaryDialog.qml:246
msgctxt "@action:label"
msgid "Visible settings:"
msgstr "Sichtbare Einstellungen:"
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:357
-#: /home/ruben/Projects/Cura/resources/qml/WorkspaceSummaryDialog.qml:251
msgctxt "@action:label"
msgid "%1 out of %2"
msgstr "%1 von %2"
@@ -2352,256 +2737,191 @@ msgctxt "@action:button"
msgid "Open"
msgstr "Öffnen"
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/ProfileCreatorTabControls.qml:34
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/pages/BackupsPage.qml:28
+msgctxt "@title"
+msgid "My Backups"
+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 "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 "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 "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 "Anmelden"
+
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/main.qml:24
+msgctxt "@title:window"
+msgid "Cura Backups"
+msgstr "Cura-Backups"
+
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListItemDetails.qml:21
+msgctxt "@backuplist:label"
+msgid "Cura Version"
+msgstr "Cura-Version"
+
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListItemDetails.qml:29
+msgctxt "@backuplist:label"
+msgid "Machines"
+msgstr "Maschinen"
+
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListItemDetails.qml:37
+msgctxt "@backuplist:label"
+msgid "Materials"
+msgstr "Materialien"
+
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListItemDetails.qml:45
+msgctxt "@backuplist:label"
+msgid "Profiles"
+msgstr "Profile"
+
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListItemDetails.qml:53
+msgctxt "@backuplist:label"
+msgid "Plugins"
+msgstr "Plugins"
+
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListItem.qml:71
+msgctxt "@button"
+msgid "Restore"
+msgstr "Wiederherstellen"
+
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListItem.qml:99
+msgctxt "@dialog:title"
+msgid "Delete Backup"
+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 "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 "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 "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 "Möchten Sie mehr?"
+
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListFooter.qml:31
+msgctxt "@button"
+msgid "Backup Now"
+msgstr "Jetzt Backup durchführen"
+
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListFooter.qml:43
+msgctxt "@checkbox:description"
+msgid "Auto Backup"
+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 "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 "Nicht unterstützt"
+
+#: /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:138
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:154
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:152
+#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/ProfileCreatorTabControls.qml:60
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:174
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:159
msgctxt "@action:button"
msgid "Export"
msgstr "Export"
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/ProfileCreatorTabControls.qml:140
-msgctxt "@action:button"
-msgid "Next"
-msgstr "Weiter"
-
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/ProfileCreatorPageCategoryView.qml:163
+#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/ProfileCreatorPageCategoryView.qml:209
msgctxt "@label"
msgid "Tip"
msgstr "Tipp"
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/CuraPrintProfileCreatorView.qml:80
-#: /home/ruben/Projects/Cura/resources/qml/PrepareSidebar.qml:341
-msgctxt "@label Hours and minutes"
-msgid "00h 00min"
-msgstr "00 Stunden 00 Minuten"
+#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/ProfileCreatorMaterialMenu.qml:20
+#: /home/ruben/Projects/Cura/resources/qml/Menus/MaterialMenu.qml:66
+msgctxt "@label:category menu label"
+msgid "Generic"
+msgstr "Generisch"
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/CuraPrintProfileCreatorView.qml:142
-#: /home/ruben/Projects/Cura/resources/qml/PrepareSidebar.qml:441
-msgctxt "@label"
-msgid "Cost specification"
-msgstr "Kostenangabe"
-
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/CuraPrintProfileCreatorView.qml:147
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/CuraPrintProfileCreatorView.qml:156
-#: /home/ruben/Projects/Cura/resources/qml/PrepareSidebar.qml:446
-#: /home/ruben/Projects/Cura/resources/qml/PrepareSidebar.qml:455
-msgctxt "@label m for meter"
-msgid "%1m"
-msgstr "%1 m"
-
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/CuraPrintProfileCreatorView.qml:148
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/CuraPrintProfileCreatorView.qml:157
-#: /home/ruben/Projects/Cura/resources/qml/PrepareSidebar.qml:447
-#: /home/ruben/Projects/Cura/resources/qml/PrepareSidebar.qml:456
-msgctxt "@label g for grams"
-msgid "%1g"
-msgstr "%1 g"
-
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/CuraPrintProfileCreatorView.qml:155
-#: /home/ruben/Projects/Cura/resources/qml/PrepareSidebar.qml:454
-msgctxt "@label"
-msgid "Total:"
-msgstr "Insgesamt:"
-
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/CuraPrintProfileCreatorView.qml:205
-msgctxt "@label Print estimates: m for meters, g for grams, %4 is currency and %3 is print cost"
-msgid "%1m / ~ %2g / ~ %4 %3"
-msgstr "%1m / ~ %2g / ~ %4 %3"
-
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/CuraPrintProfileCreatorView.qml:210
-msgctxt "@label Print estimates: m for meters, g for grams"
-msgid "%1m / ~ %2g"
-msgstr "%1m / ~ %2g"
-
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/ProfileCreatorPage.qml:143
+#: /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:26
+#: /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
+#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UM2UpgradeSelectionMachineAction.qml:30
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
+#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UM2UpgradeSelectionMachineAction.qml:44
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/UpgradeFirmwareMachineAction.qml:30
-msgctxt "@title"
-msgid "Upgrade Firmware"
-msgstr "Firmware aktualisieren"
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UpgradeFirmwareMachineAction.qml:41
-msgctxt "@label"
-msgid "Firmware is the piece of software running directly on your 3D printer. This firmware controls the step motors, regulates the temperature and ultimately makes your printer work."
-msgstr "Die Firmware ist der Teil der Software, der direkt auf Ihrem 3D-Drucker läuft. Diese Firmware kontrolliert die Schrittmotoren, reguliert die Temperatur und sorgt letztlich dafür, dass Ihr Drucker funktioniert."
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UpgradeFirmwareMachineAction.qml:51
-msgctxt "@label"
-msgid "The firmware shipping with new printers works, but new versions tend to have more features and improvements."
-msgstr "Die mit neuen Druckern gelieferte Firmware funktioniert, allerdings enthalten neue Versionen üblicherweise mehr Funktionen und Verbesserungen."
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UpgradeFirmwareMachineAction.qml:65
-msgctxt "@action:button"
-msgid "Automatically upgrade Firmware"
-msgstr "Firmware automatisch aktualisieren"
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UpgradeFirmwareMachineAction.qml:75
-msgctxt "@action:button"
-msgid "Upload custom Firmware"
-msgstr "Benutzerdefinierte Firmware hochladen"
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UpgradeFirmwareMachineAction.qml:87
-msgctxt "@title:window"
-msgid "Select custom firmware"
-msgstr "Benutzerdefinierte Firmware wählen"
-
-#: /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"
@@ -2613,7 +2933,6 @@ msgid "Printer does not accept commands"
msgstr "Drucker nimmt keine Befehle an"
#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:133
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:197
msgctxt "@label:MonitorStatus"
msgid "In maintenance. Please check the printer"
msgstr "In Wartung. Den Drucker überprüfen"
@@ -2624,19 +2943,16 @@ msgid "Lost connection with the printer"
msgstr "Verbindung zum Drucker wurde unterbrochen"
#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:146
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:187
msgctxt "@label:MonitorStatus"
msgid "Printing..."
msgstr "Es wird gedruckt..."
#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:149
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:189
msgctxt "@label:MonitorStatus"
msgid "Paused"
msgstr "Pausiert"
#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:152
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:191
msgctxt "@label:MonitorStatus"
msgid "Preparing..."
msgstr "Vorbereitung läuft..."
@@ -2656,229 +2972,170 @@ 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/DiscardOrKeepProfileChangesDialog.qml:15
-msgctxt "@title:window"
-msgid "Discard or Keep changes"
-msgstr "Änderungen verwerfen oder übernehmen"
-
-#: /home/ruben/Projects/Cura/resources/qml/DiscardOrKeepProfileChangesDialog.qml:57
-msgctxt "@text:window"
-msgid ""
-"You have customized some profile settings.\n"
-"Would you like to keep or discard those settings?"
-msgstr ""
-"Sie haben einige Profileinstellungen angepasst.\n"
-"Möchten Sie diese Einstellungen übernehmen oder verwerfen?"
-
-#: /home/ruben/Projects/Cura/resources/qml/DiscardOrKeepProfileChangesDialog.qml:110
-msgctxt "@title:column"
-msgid "Profile settings"
-msgstr "Profileinstellungen"
-
-#: /home/ruben/Projects/Cura/resources/qml/DiscardOrKeepProfileChangesDialog.qml:117
-msgctxt "@title:column"
-msgid "Default"
-msgstr "Standard"
-
-#: /home/ruben/Projects/Cura/resources/qml/DiscardOrKeepProfileChangesDialog.qml:124
-msgctxt "@title:column"
-msgid "Customized"
-msgstr "Angepasst"
-
-#: /home/ruben/Projects/Cura/resources/qml/DiscardOrKeepProfileChangesDialog.qml:157
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:639
-msgctxt "@option:discardOrKeep"
-msgid "Always ask me this"
-msgstr "Stets nachfragen"
-
-#: /home/ruben/Projects/Cura/resources/qml/DiscardOrKeepProfileChangesDialog.qml:158
-msgctxt "@option:discardOrKeep"
-msgid "Discard and never ask again"
-msgstr "Verwerfen und zukünftig nicht mehr nachfragen"
-
-#: /home/ruben/Projects/Cura/resources/qml/DiscardOrKeepProfileChangesDialog.qml:159
-msgctxt "@option:discardOrKeep"
-msgid "Keep and never ask again"
-msgstr "Übernehmen und zukünftig nicht mehr nachfragen"
-
-#: /home/ruben/Projects/Cura/resources/qml/DiscardOrKeepProfileChangesDialog.qml:196
-msgctxt "@action:button"
-msgid "Discard"
-msgstr "Verwerfen"
-
-#: /home/ruben/Projects/Cura/resources/qml/DiscardOrKeepProfileChangesDialog.qml:209
-msgctxt "@action:button"
-msgid "Keep"
-msgstr "Übernehmen"
-
-#: /home/ruben/Projects/Cura/resources/qml/DiscardOrKeepProfileChangesDialog.qml:222
-msgctxt "@action:button"
-msgid "Create New Profile"
-msgstr "Neues Profil erstellen"
-
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:71
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:73
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:102
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:103
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:127
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:137
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:147
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:157
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:207
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:209
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:224
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:258
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:275
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:293
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:302
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:316
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:323
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:334
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:347
msgctxt "@label"
msgid "Adhesion Information"
msgstr "Haftungsinformationen"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:378
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:373
+#: /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:35
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:72
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:99
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:40
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:73
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:117
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:131
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:160
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:148
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:223
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:239
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:287
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:253
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:240
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:290
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:254
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:304
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:312
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:313
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:317
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:335
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:343
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:347
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:353
msgctxt "@info:status Don't translate the XML tag !"
msgid "Successfully exported material to %1"
msgstr "Material erfolgreich nach %1 exportiert"
@@ -2888,649 +3145,536 @@ msgctxt "@title:tab"
msgid "Setting Visibility"
msgstr "Sichtbarkeit einstellen"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/SettingVisibilityPage.qml:50
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/SettingVisibilityPage.qml:46
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:48
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:61
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:68
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:75
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:83
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:537
+#: /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:141
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:130
msgctxt "@label"
msgid "Interface"
msgstr "Schnittstelle"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:152
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:141
msgctxt "@label"
msgid "Language:"
msgstr "Sprache:"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:220
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:208
msgctxt "@label"
msgid "Currency:"
msgstr "Währung:"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:234
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:221
msgctxt "@label"
msgid "Theme:"
msgstr "Thema:"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:294
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:277
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:311
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:294
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:319
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:302
msgctxt "@option:check"
msgid "Slice automatically"
msgstr "Automatisch schneiden"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:333
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:316
msgctxt "@label"
msgid "Viewport behavior"
msgstr "Viewport-Verhalten"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:341
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:324
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:350
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:333
msgctxt "@option:check"
msgid "Display overhang"
msgstr "Überhang anzeigen"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:357
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:341
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:362
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:346
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:371
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:356
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:376
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:361
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:386
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:371
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:391
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:371
+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."
+
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:376
msgctxt "@action:button"
msgid "Zoom toward mouse direction"
msgstr "In Mausrichtung zoomen"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:401
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:402
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:406
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:407
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:415
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:416
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:420
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:421
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:432
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:433
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:441
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:442
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:449
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:450
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:454
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:455
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:470
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:465
+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:472
+msgctxt "@window:text"
+msgid "Camera rendering: "
+msgstr "Kamera-Rendering: "
+
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:483
+msgid "Perspective"
+msgstr "Ansicht"
+
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:484
+msgid "Orthogonal"
+msgstr "Orthogonal"
+
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:515
msgctxt "@label"
msgid "Opening and saving files"
msgstr "Dateien öffnen und speichern"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:477
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:522
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:482
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:527
msgctxt "@option:check"
msgid "Scale large models"
msgstr "Große Modelle anpassen"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:492
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:537
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:497
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:542
msgctxt "@option:check"
msgid "Scale extremely small models"
msgstr "Extrem kleine Modelle skalieren"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:507
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:552
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:512
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:557
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:522
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:567
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:527
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:572
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:537
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:582
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:541
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:586
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:551
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:596
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:559
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:604
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:573
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:618
msgctxt "@option:openProject"
msgid "Always ask me this"
msgstr "Stets nachfragen"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:574
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:619
msgctxt "@option:openProject"
msgid "Always open as a project"
msgstr "Immer als Projekt öffnen"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:575
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:620
msgctxt "@option:openProject"
msgid "Always import models"
msgstr "Modelle immer importieren"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:611
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:656
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:620
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:665
msgctxt "@label"
msgid "Profiles"
msgstr "Profile"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:625
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:670
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:640
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:684
+#: /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:685
msgctxt "@option:discardOrKeep"
msgid "Always discard changed settings"
msgstr "Geänderte Einstellungen immer verwerfen"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:641
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:686
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:675
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:720
msgctxt "@label"
msgid "Privacy"
msgstr "Privatsphäre"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:683
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:727
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:688
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:732
msgctxt "@option:check"
msgid "Check for updates on start"
msgstr "Bei Start nach Updates suchen"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:699
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:742
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:704
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:747
msgctxt "@option:check"
msgid "Send (anonymous) print information"
msgstr "(Anonyme) Druckinformationen senden"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:713
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:756
msgctxt "@action:button"
msgid "More information"
msgstr "Mehr Informationen"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:731
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:774
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/PrintSetupSelectorHeader.qml:27
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ProfileMenu.qml:23
msgctxt "@label"
msgid "Experimental"
msgstr "Experimentell"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:738
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:781
msgctxt "@info:tooltip"
msgid "Use multi build plate functionality"
msgstr "Mehrfach-Druckplattenfunktion verwenden"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:743
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:786
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:542
+#: /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:55
-#: /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:134
msgctxt "@action:button"
msgid "Rename"
msgstr "Umbenennen"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:147
-msgctxt "@label"
-msgid "Printer type:"
-msgstr "Druckertyp:"
-
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:156
-msgctxt "@label"
-msgid "Connection:"
-msgstr "Verbindung:"
-
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:162
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/OutputDeviceHeader.qml:47
-msgctxt "@info:status"
-msgid "The printer is not connected."
-msgstr "Der Drucker ist nicht verbunden."
-
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:168
-msgctxt "@label"
-msgid "State:"
-msgstr "Status:"
-
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:181
-msgctxt "@label:MonitorStatus"
-msgid "Waiting for a printjob"
-msgstr "Warten auf einen Druckauftrag"
-
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:193
-msgctxt "@label:MonitorStatus"
-msgid "Waiting for someone to clear the build plate"
-msgstr "Warten auf Räumen des Druckbeets"
-
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:199
-msgctxt "@label:MonitorStatus"
-msgid "Aborting print..."
-msgstr "Drucken wird abgebrochen..."
-
#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:36
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:546
+#: /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:89
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:105
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:181
msgctxt "@title:window"
msgid "Create Profile"
msgstr "Profil erstellen"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:225
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:183
+msgctxt "@info"
+msgid "Please provide a name for this profile."
+msgstr "Geben Sie bitte einen Namen für dieses Profil an."
+
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:239
msgctxt "@title:window"
msgid "Duplicate Profile"
msgstr "Profil duplizieren"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:256
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:270
msgctxt "@title:window"
msgid "Rename Profile"
msgstr "Profil umbenennen"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:269
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:283
msgctxt "@title:window"
msgid "Import Profile"
msgstr "Profil importieren"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:295
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:309
msgctxt "@title:window"
msgid "Export Profile"
msgstr "Profil exportieren"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:350
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:364
msgctxt "@label %1 is printer name"
msgid "Printer: %1"
msgstr "Drucker: %1"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:403
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:420
msgctxt "@label"
-msgid "Protected profiles"
-msgstr "Geschützte Profile"
+msgid "Default profiles"
+msgstr "Standardprofile"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:403
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:420
msgctxt "@label"
msgid "Custom profiles"
msgstr "Benutzerdefinierte Profile"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:480
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:500
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:487
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:507
msgctxt "@action:button"
msgid "Discard current changes"
msgstr "Aktuelle Änderungen verwerfen"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:504
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:524
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:511
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:531
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:530
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:550
msgctxt "@title:tab"
msgid "Global Settings"
msgstr "Globale Einstellungen"
-#: /home/ruben/Projects/Cura/resources/qml/AddMachineDialog.qml:18
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:946
-msgctxt "@title:window"
-msgid "Add Printer"
-msgstr "Drucker hinzufügen"
-
-#: /home/ruben/Projects/Cura/resources/qml/AddMachineDialog.qml:194
-msgctxt "@label"
-msgid "Printer Name:"
-msgstr "Druckername:"
-
-#: /home/ruben/Projects/Cura/resources/qml/AddMachineDialog.qml:217
+#: /home/ruben/Projects/Cura/resources/qml/MainWindow/MainWindowHeader.qml:89
msgctxt "@action:button"
-msgid "Add Printer"
-msgstr "Drucker hinzufügen"
+msgid "Marketplace"
+msgstr "Marktplatz"
-#: /home/ruben/Projects/Cura/resources/qml/JobSpecs.qml:84
+#: /home/ruben/Projects/Cura/resources/qml/MainWindow/ApplicationMenu.qml:27
+#: /home/ruben/Projects/Cura/resources/qml/Menus/FileMenu.qml:13
+msgctxt "@title:menu menubar:toplevel"
+msgid "&File"
+msgstr "&Datei"
+
+#: /home/ruben/Projects/Cura/resources/qml/MainWindow/ApplicationMenu.qml:31
+msgctxt "@title:menu menubar:toplevel"
+msgid "&Edit"
+msgstr "&Bearbeiten"
+
+#: /home/ruben/Projects/Cura/resources/qml/MainWindow/ApplicationMenu.qml:48
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ViewMenu.qml:12
+msgctxt "@title:menu menubar:toplevel"
+msgid "&View"
+msgstr "&Ansicht"
+
+#: /home/ruben/Projects/Cura/resources/qml/MainWindow/ApplicationMenu.qml:50
+#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:13
+msgctxt "@title:menu menubar:toplevel"
+msgid "&Settings"
+msgstr "&Einstellungen"
+
+#: /home/ruben/Projects/Cura/resources/qml/MainWindow/ApplicationMenu.qml:55
+msgctxt "@title:menu menubar:toplevel"
+msgid "E&xtensions"
+msgstr "Er&weiterungen"
+
+#: /home/ruben/Projects/Cura/resources/qml/MainWindow/ApplicationMenu.qml:89
+msgctxt "@title:menu menubar:toplevel"
+msgid "P&references"
+msgstr "E&instellungen"
+
+#: /home/ruben/Projects/Cura/resources/qml/MainWindow/ApplicationMenu.qml:97
+msgctxt "@title:menu menubar:toplevel"
+msgid "&Help"
+msgstr "&Hilfe"
+
+#: /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: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."
+
+#: /home/ruben/Projects/Cura/resources/qml/JobSpecs.qml:88
msgctxt "@text Print job name"
msgid "Untitled"
msgstr "Unbenannt"
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:15
-msgctxt "@title:window"
-msgid "About Cura"
-msgstr "Über Cura"
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:43
-msgctxt "@label"
-msgid "version: %1"
-msgstr "Version: %1"
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:56
-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/AboutDialog.qml:69
-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 ""
-"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/AboutDialog.qml:118
-msgctxt "@label"
-msgid "Graphical user interface"
-msgstr "Grafische Benutzerschnittstelle"
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:119
-msgctxt "@label"
-msgid "Application framework"
-msgstr "Anwendungsrahmenwerk"
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:120
-msgctxt "@label"
-msgid "G-code generator"
-msgstr "G-Code-Generator"
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:121
-msgctxt "@label"
-msgid "Interprocess communication library"
-msgstr "Bibliothek Interprozess-Kommunikation"
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:123
-msgctxt "@label"
-msgid "Programming language"
-msgstr "Programmiersprache"
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:124
-msgctxt "@label"
-msgid "GUI framework"
-msgstr "GUI-Rahmenwerk"
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:125
-msgctxt "@label"
-msgid "GUI framework bindings"
-msgstr "GUI-Rahmenwerk Einbindungen"
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:126
-msgctxt "@label"
-msgid "C/C++ Binding library"
-msgstr "C/C++ Einbindungsbibliothek"
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:127
-msgctxt "@label"
-msgid "Data interchange format"
-msgstr "Format Datenaustausch"
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:128
-msgctxt "@label"
-msgid "Support library for scientific computing"
-msgstr "Support-Bibliothek für wissenschaftliche Berechnung"
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:129
-msgctxt "@label"
-msgid "Support library for faster math"
-msgstr "Support-Bibliothek für schnelleres Rechnen"
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:130
-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/AboutDialog.qml:131
-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/AboutDialog.qml:132
-msgctxt "@label"
-msgid "Serial communication library"
-msgstr "Bibliothek für serielle Kommunikation"
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:133
-msgctxt "@label"
-msgid "ZeroConf discovery library"
-msgstr "Bibliothek für ZeroConf-Erkennung"
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:134
-msgctxt "@label"
-msgid "Polygon clipping library"
-msgstr "Bibliothek für Polygon-Beschneidung"
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:135
-msgctxt "@Label"
-msgid "Python HTTP library"
-msgstr "Bibliothek für Python HTTP"
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:137
-msgctxt "@label"
-msgid "Font"
-msgstr "Schriftart"
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:138
-msgctxt "@label"
-msgid "SVG icons"
-msgstr "SVG-Symbole"
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:139
-msgctxt "@label"
-msgid "Linux cross-distribution application deployment"
-msgstr "Distributionsunabhängiges Format für Linux-Anwendungen"
-
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:42
-msgctxt "@label"
-msgid "Profile:"
-msgstr "Profil:"
-
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:103
-msgctxt "@tooltip"
-msgid ""
-"Some setting/override values are different from the values stored in the profile.\n"
-"\n"
-"Click to open the profile manager."
-msgstr ""
-"Einige Einstellungs-/Überschreibungswerte unterscheiden sich von den im Profil gespeicherten Werten.\n"
-"\n"
-"Klicken Sie, um den Profilmanager zu öffnen."
-
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:199
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:68
msgctxt "@label:textbox"
-msgid "Search..."
-msgstr "Suchen..."
+msgid "search settings"
+msgstr "Einstellungen durchsuchen"
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:544
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:466
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:553
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:475
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:590
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:512
msgctxt "@action:menu"
msgid "Hide this setting"
msgstr "Diese Einstellung ausblenden"
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:608
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:525
msgctxt "@action:menu"
msgid "Don't show this setting"
msgstr "Diese Einstellung ausblenden"
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:612
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:529
msgctxt "@action:menu"
msgid "Keep this setting visible"
msgstr "Diese Einstellung weiterhin anzeigen"
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:636
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:416
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:548
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:434
msgctxt "@action:menu"
msgid "Configure setting visibility..."
msgstr "Sichtbarkeit einstellen wird konfiguriert..."
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:643
-msgctxt "@action:inmenu"
-msgid "Collapse All"
-msgstr "Alle verkleinern"
-
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:648
-msgctxt "@action:inmenu"
-msgid "Expand All"
-msgstr "Alle vergrößern"
-
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingCategory.qml:249
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingCategory.qml:237
msgctxt "@label"
msgid ""
"Some hidden settings use values different from their normal calculated value.\n"
@@ -3541,27 +3685,32 @@ msgstr ""
"\n"
"Klicken Sie, um diese Einstellungen sichtbar zu machen."
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:61
+#: /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:66
+#: /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:154
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:186
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:157
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:190
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:188
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:228
msgctxt "@label"
msgid ""
"This setting has a value that is different from the profile.\n"
@@ -3572,7 +3721,7 @@ msgstr ""
"\n"
"Klicken Sie, um den Wert des Profils wiederherzustellen."
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:286
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:322
msgctxt "@label"
msgid ""
"This setting is normally calculated, but it currently has an absolute value set.\n"
@@ -3583,116 +3732,210 @@ msgstr ""
"\n"
"Klicken Sie, um den berechneten Wert wiederherzustellen."
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ManualPrinterControl.qml:129
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/PrintSetupSelectorContents.qml:144
+msgctxt "@button"
+msgid "Recommended"
+msgstr "Empfohlen"
+
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/PrintSetupSelectorContents.qml:158
+msgctxt "@button"
+msgid "Custom"
+msgstr "Benutzerdefiniert"
+
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedInfillDensitySelector.qml:193
+msgctxt "@label"
+msgid "Gradual infill"
+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:30
+msgctxt "@label"
+msgid "Support"
+msgstr "Stützstruktur"
+
+#: /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/RecommendedAdhesionSelector.qml:29
+msgctxt "@label"
+msgid "Adhesion"
+msgstr "Haftung"
+
+#: /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
+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 "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."
+
+#: /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 "Ein"
+
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/PrintSetupSelectorHeader.qml:14
+msgctxt "@label:Should be short"
+msgid "Off"
+msgstr "Aus"
+
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Custom/GlobalProfileSelector.qml:27
+msgctxt "@label"
+msgid "Profile"
+msgstr "Profil"
+
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Custom/GlobalProfileSelector.qml:94
+msgctxt "@tooltip"
+msgid ""
+"Some setting/override values are different from the values stored in the profile.\n"
+"\n"
+"Click to open the profile manager."
+msgstr ""
+"Einige Einstellungs-/Überschreibungswerte unterscheiden sich von den im Profil gespeicherten Werten.\n"
+"\n"
+"Klicken Sie, um den Profilmanager zu öffnen."
+
+#: /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 "Druckeinrichtung ist deaktiviert. G-Code-Datei kann nicht geändert werden."
+
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ManualPrinterControl.qml:52
msgctxt "@label"
msgid "Printer control"
msgstr "Druckersteuerung"
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ManualPrinterControl.qml:144
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ManualPrinterControl.qml:67
msgctxt "@label"
msgid "Jog Position"
msgstr "Tippposition"
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ManualPrinterControl.qml:162
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ManualPrinterControl.qml:85
msgctxt "@label"
msgid "X/Y"
msgstr "X/Y"
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ManualPrinterControl.qml:269
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ManualPrinterControl.qml:192
msgctxt "@label"
msgid "Z"
msgstr "Z"
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ManualPrinterControl.qml:334
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ManualPrinterControl.qml:257
msgctxt "@label"
msgid "Jog Distance"
msgstr "Tippdistanz"
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ManualPrinterControl.qml:443
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ManualPrinterControl.qml:301
msgctxt "@label"
msgid "Send G-code"
msgstr "G-Code senden"
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ManualPrinterControl.qml:506
+#: /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:36
-#: /home/ruben/Projects/Cura/resources/qml/SidebarHeader.qml:272
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:38
msgctxt "@label"
msgid "Extruder"
msgstr "Extruder"
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:66
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:68
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:98
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:100
msgctxt "@tooltip"
msgid "The current temperature of this hotend."
msgstr "Die aktuelle Temperatur dieses Hotends."
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:172
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:174
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:336
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/HeatedBedBox.qml:331
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:338
+#: /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:339
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/HeatedBedBox.qml:334
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:341
+#: /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:365
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:367
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:401
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:403
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:433
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:435
msgctxt "@tooltip"
msgid "The material in this extruder."
msgstr "Das Material in diesem Extruder."
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:465
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:467
msgctxt "@tooltip"
msgid "The nozzle inserted in this extruder."
msgstr "Die in diesem Extruder eingesetzte Düse."
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/HeatedBedBox.qml:25
-#: /home/ruben/Projects/Cura/resources/qml/SidebarHeader.qml:493
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/OutputDeviceHeader.qml:55
+msgctxt "@info:status"
+msgid "The printer is not connected."
+msgstr "Der Drucker ist nicht verbunden."
+
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/HeatedBedBox.qml:26
msgctxt "@label"
msgid "Build plate"
msgstr "Druckbett"
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/HeatedBedBox.qml:55
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/HeatedBedBox.qml:56
msgctxt "@tooltip"
msgid "The target temperature of the heated bed. The bed will heat up or cool down towards this temperature. If this is 0, the bed heating is turned off."
msgstr "Die Zieltemperatur des heizbaren Betts. Das Bett wird auf diese Temperatur aufgeheizt oder abgekühlt. Wenn der Wert 0 beträgt, wird die Bettheizung ausgeschaltet."
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/HeatedBedBox.qml:87
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/HeatedBedBox.qml:88
msgctxt "@tooltip"
msgid "The current temperature of the heated bed."
msgstr "Die aktuelle Temperatur des beheizten Betts."
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/HeatedBedBox.qml:160
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/HeatedBedBox.qml:161
msgctxt "@tooltip of temperature input"
msgid "The temperature to pre-heat the bed to."
msgstr "Die Temperatur, auf die das Bett vorgeheizt wird."
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/HeatedBedBox.qml:360
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/HeatedBedBox.qml:361
msgctxt "@tooltip of pre-heat"
msgid "Heat the bed in advance before printing. You can continue adjusting your print while it is heating, and you won't have to wait for the bed to heat up when you're ready to print."
msgstr "Heizen Sie das Bett vor Druckbeginn auf. Sie können Ihren Druck während des Aufheizens weiter anpassen und müssen nicht warten, bis das Bett aufgeheizt ist, wenn Sie druckbereit sind."
@@ -3702,16 +3945,11 @@ msgctxt "@label:category menu label"
msgid "Material"
msgstr "Material"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/MaterialMenu.qml:37
+#: /home/ruben/Projects/Cura/resources/qml/Menus/MaterialMenu.qml:42
msgctxt "@label:category menu label"
msgid "Favorites"
msgstr "Favoriten"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/MaterialMenu.qml:61
-msgctxt "@label:category menu label"
-msgid "Generic"
-msgstr "Generisch"
-
#: /home/ruben/Projects/Cura/resources/qml/Menus/PrinterMenu.qml:25
msgctxt "@label:category menu label"
msgid "Network enabled printers"
@@ -3722,17 +3960,62 @@ msgctxt "@label:category menu label"
msgid "Local printers"
msgstr "Lokale Drucker"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/ViewMenu.qml:12
-msgctxt "@title:menu menubar:toplevel"
-msgid "&View"
-msgstr "&Ansicht"
+#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:15
+msgctxt "@title:menu menubar:settings"
+msgid "&Printer"
+msgstr "Dr&ucker"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/ViewMenu.qml:39
+#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:32
+msgctxt "@title:menu"
+msgid "&Material"
+msgstr "&Material"
+
+#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:41
+msgctxt "@action:inmenu"
+msgid "Set as Active Extruder"
+msgstr "Als aktiven Extruder festlegen"
+
+#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:47
+msgctxt "@action:inmenu"
+msgid "Enable Extruder"
+msgstr "Extruder aktivieren"
+
+#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:54
+msgctxt "@action:inmenu"
+msgid "Disable Extruder"
+msgstr "Extruder deaktivieren"
+
+#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:68
+msgctxt "@title:menu"
+msgid "&Build plate"
+msgstr "&Druckplatte"
+
+#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:71
+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:54
+#: /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"
@@ -3742,16 +4025,31 @@ msgctxt "@action:inmenu"
msgid "Visible Settings"
msgstr "Sichtbare Einstellungen"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingVisibilityPresetsMenu.qml:43
+#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingVisibilityPresetsMenu.qml:42
msgctxt "@action:inmenu"
msgid "Show All Settings"
msgstr "Alle Einstellungen anzeigen"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingVisibilityPresetsMenu.qml:54
+#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingVisibilityPresetsMenu.qml:53
msgctxt "@action:inmenu"
msgid "Manage Setting Visibility..."
msgstr "Sichtbarkeit einstellen verwalten..."
+#: /home/ruben/Projects/Cura/resources/qml/Menus/FileMenu.qml:32
+msgctxt "@title:menu menubar:file"
+msgid "&Save..."
+msgstr "&Speichern..."
+
+#: /home/ruben/Projects/Cura/resources/qml/Menus/FileMenu.qml:53
+msgctxt "@title:menu menubar:file"
+msgid "&Export..."
+msgstr "&Exportieren..."
+
+#: /home/ruben/Projects/Cura/resources/qml/Menus/FileMenu.qml:64
+msgctxt "@action:inmenu menubar:file"
+msgid "Export Selection..."
+msgstr "Auswahl exportieren..."
+
#: /home/ruben/Projects/Cura/resources/qml/Menus/ContextMenu.qml:27
msgctxt "@label"
msgid "Print Selected Model With:"
@@ -3771,634 +4069,509 @@ msgctxt "@label"
msgid "Number of Copies"
msgstr "Anzahl Kopien"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/ConfigurationListView.qml:33
-msgctxt "@label:header configurations"
-msgid "Available configurations"
-msgstr "Verfügbare Konfigurationen"
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/AutoConfiguration.qml:18
+msgctxt "@header"
+msgid "Configurations"
+msgstr "Konfigurationen"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/PrintCoreConfiguration.qml:28
-msgctxt "@label:extruder label"
-msgid "Extruder"
-msgstr "Extruder"
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/ConfigurationMenu.qml:110
+msgctxt "@label"
+msgid "Select configuration"
+msgstr "Konfiguration wählen"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/SyncButton.qml:16
-msgctxt "@label:extruder label"
-msgid "Yes"
-msgstr "Ja"
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/ConfigurationMenu.qml:221
+msgctxt "@label"
+msgid "Configurations"
+msgstr "Konfigurationen"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/SyncButton.qml:16
-msgctxt "@label:extruder label"
-msgid "No"
-msgstr "Nein"
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/ConfigurationListView.qml:57
+msgctxt "@label"
+msgid "Loading available configurations from the printer..."
+msgstr "Verfügbare Konfigurationen werden von diesem Drucker geladen..."
-#: /home/ruben/Projects/Cura/resources/qml/Menus/RecentFilesMenu.qml:13
+#: /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 "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 "Benutzerdefiniert"
+
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/CustomConfiguration.qml:61
+msgctxt "@label"
+msgid "Printer"
+msgstr "Drucker"
+
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/CustomConfiguration.qml:213
+msgctxt "@label"
+msgid "Enabled"
+msgstr "Aktiviert"
+
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/CustomConfiguration.qml:250
+msgctxt "@label"
+msgid "Material"
+msgstr "Material"
+
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/CustomConfiguration.qml:375
+msgctxt "@label"
+msgid "Use glue for better adhesion with this material combination."
+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 "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 "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/PrepareSidebar.qml:150
-msgctxt "@label:listbox"
-msgid "Print Setup"
-msgstr "Druckeinrichtung"
-
-#: /home/ruben/Projects/Cura/resources/qml/PrepareSidebar.qml:150
-msgctxt "@label:listbox"
-msgid ""
-"Print Setup disabled\n"
-"G-code files cannot be modified"
-msgstr ""
-"Druckeinrichtung deaktiviert\n"
-"G-Code-Dateien können nicht geändert werden"
-
-#: /home/ruben/Projects/Cura/resources/qml/PrepareSidebar.qml:359
-msgctxt "@tooltip"
-msgid "Time specification"
-msgstr "Zeitangabe"
-
-#: /home/ruben/Projects/Cura/resources/qml/PrepareSidebar.qml:577
-msgctxt "@tooltip"
-msgid "Recommended Print Setup
Print with the recommended settings for the selected printer, material and quality."
-msgstr "Empfohlene Druckeinrichtung
Drucken mit den empfohlenen Einstellungen für den gewählten Drucker, das gewählte Material und die gewählte Qualität."
-
-#: /home/ruben/Projects/Cura/resources/qml/PrepareSidebar.qml:582
-msgctxt "@tooltip"
-msgid "Custom Print Setup
Print with finegrained control over every last bit of the slicing process."
-msgstr "Benutzerdefinierte Druckeinrichtung
Druck mit Feineinstellung über jedem einzelnen Bereich des Schneidvorgangs."
-
-#: /home/ruben/Projects/Cura/resources/qml/PrintMonitor.qml:106
+#: /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:114
+#: /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:122
+#: /home/ruben/Projects/Cura/resources/qml/PrintMonitor.qml:156
msgctxt "@label"
msgid "Printing Time"
msgstr "Druckzeit"
-#: /home/ruben/Projects/Cura/resources/qml/PrintMonitor.qml:130
+#: /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/Actions.qml:78
+#: /home/ruben/Projects/Cura/resources/qml/ViewsSelector.qml:50
+msgctxt "@label"
+msgid "View type"
+msgstr "Typ anzeigen"
+
+#: /home/ruben/Projects/Cura/resources/qml/ObjectSelector.qml:59
+msgctxt "@label"
+msgid "Object list"
+msgstr "Objektliste"
+
+#: /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 "Ultimaker‑Konto"
+
+#: /home/ruben/Projects/Cura/resources/qml/Account/UserOperations.qml:42
+msgctxt "@button"
+msgid "Sign out"
+msgstr "Abmelden"
+
+#: /home/ruben/Projects/Cura/resources/qml/Account/AccountWidget.qml:24
+msgctxt "@action:button"
+msgid "Sign in"
+msgstr "Anmelden"
+
+#: /home/ruben/Projects/Cura/resources/qml/Account/GeneralOperations.qml:40
+msgctxt "@label"
+msgid "The next generation 3D printing workflow"
+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 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 "Konto erstellen"
+
+#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/OutputProcessWidget.qml:59
+msgctxt "@label"
+msgid "No time estimation available"
+msgstr "Keine Zeitschätzung verfügbar"
+
+#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/OutputProcessWidget.qml:77
+msgctxt "@label"
+msgid "No cost estimation available"
+msgstr "Keine Kostenschätzung verfügbar"
+
+#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/OutputProcessWidget.qml:127
+msgctxt "@button"
+msgid "Preview"
+msgstr "Vorschau"
+
+#: /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:67
+msgctxt "@label:PrintjobStatus"
+msgid "Unable to slice"
+msgstr "Slicing nicht möglich"
+
+#: /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 "Slice"
+
+#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/SliceProcessWidget.qml:104
+msgctxt "@label"
+msgid "Start the slicing process"
+msgstr "Slicing-Vorgang starten"
+
+#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/SliceProcessWidget.qml:118
+msgctxt "@button"
+msgid "Cancel"
+msgstr "Abbrechen"
+
+#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/PrintJobInformation.qml:31
+msgctxt "@label"
+msgid "Time estimation"
+msgstr "Zeitschätzung"
+
+#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/PrintJobInformation.qml:114
+msgctxt "@label"
+msgid "Material estimation"
+msgstr "Materialschätzung"
+
+#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/PrintJobInformation.qml:164
+msgctxt "@label m for meter"
+msgid "%1m"
+msgstr "%1 m"
+
+#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/PrintJobInformation.qml:165
+msgctxt "@label g for grams"
+msgid "%1g"
+msgstr "%1 g"
+
+#: /home/ruben/Projects/Cura/resources/qml/PrinterSelector/MachineSelectorList.qml:19
+msgctxt "@label"
+msgid "Connected printers"
+msgstr "Verbundene Drucker"
+
+#: /home/ruben/Projects/Cura/resources/qml/PrinterSelector/MachineSelectorList.qml:19
+msgctxt "@label"
+msgid "Preset printers"
+msgstr "Voreingestellte Drucker"
+
+#: /home/ruben/Projects/Cura/resources/qml/PrinterSelector/MachineSelector.qml:166
+msgctxt "@button"
+msgid "Add printer"
+msgstr "Drucker hinzufügen"
+
+#: /home/ruben/Projects/Cura/resources/qml/PrinterSelector/MachineSelector.qml:182
+msgctxt "@button"
+msgid "Manage printers"
+msgstr "Drucker verwalten"
+
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:81
+msgctxt "@action:inmenu"
+msgid "Show Online Troubleshooting Guide"
+msgstr "Online-Fehlerbehebung anzeigen"
+
+#: /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:85
+#: /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:95
+#: /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:105
+#: /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:113
+#: /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:120
+#: /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:127
+#: /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:134
+#: /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:141
+#: /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:148
+#: /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:155
+#: /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:161
+#: /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:168
+#: /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:176
+#: /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:184
+#: /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:196
+#: /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:202
+#: /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:209
+#: /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:217
+#: /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:225
+#: /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:232
+#: /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:242
+#: /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:251
+#: /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:260
+#: /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:268
+#: /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:274
+#: /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:294
+#: /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:304
+#: /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:314
+#: /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:321
+#: /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:331
+#: /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:341
+#: /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:350
+#: /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:357
+#: /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:365
+#: /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:372
+#: /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:379
+#: /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:386
+#: /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:394
+#: /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:401
-msgctxt "@action:inmenu menubar:help"
-msgid "Show Engine &Log..."
-msgstr "Engine-&Protokoll anzeigen..."
-
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:409
+#: /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:423
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:441
msgctxt "@action:menu"
-msgid "Browse packages..."
-msgstr "Pakete durchsuchen..."
+msgid "&Marketplace"
+msgstr "&Marktplatz"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:430
-msgctxt "@action:inmenu menubar:view"
-msgid "Expand/Collapse Sidebar"
-msgstr "Seitenleiste vergrößern/verkleinern"
-
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:27
-msgctxt "@label:PrintjobStatus"
-msgid "Please load a 3D model"
-msgstr "Bitte laden Sie ein 3D-Modell"
-
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:37
-msgctxt "@label:PrintjobStatus"
-msgid "Ready to slice"
-msgstr "Bereit zum Slicen (Schneiden)"
-
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:39
-msgctxt "@label:PrintjobStatus"
-msgid "Slicing..."
-msgstr "Das Slicing läuft..."
-
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:41
-msgctxt "@label:PrintjobStatus %1 is target operation"
-msgid "Ready to %1"
-msgstr "Bereit zum %1"
-
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:43
-msgctxt "@label:PrintjobStatus"
-msgid "Unable to Slice"
-msgstr "Slicing nicht möglich"
-
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:45
-msgctxt "@label:PrintjobStatus"
-msgid "Slicing unavailable"
-msgstr "Slicing ist nicht verfügbar"
-
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:172
-msgctxt "@info:tooltip"
-msgid "Slice current printjob"
-msgstr "Aktuellen Druckauftrag slicen"
-
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:172
-msgctxt "@info:tooltip"
-msgid "Cancel slicing process"
-msgstr "Slicing-Vorgang abbrechen"
-
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:184
-msgctxt "@label:Printjob"
-msgid "Prepare"
-msgstr "Vorbereiten"
-
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:184
-msgctxt "@label:Printjob"
-msgid "Cancel"
-msgstr "Abbrechen"
-
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:320
-msgctxt "@info:tooltip"
-msgid "Select the active output device"
-msgstr "Wählen Sie das aktive Ausgabegerät"
-
-#: /home/ruben/Projects/Cura/resources/qml/OpenFilesIncludingProjectsDialog.qml:19
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:760
-msgctxt "@title:window"
-msgid "Open file(s)"
-msgstr "Datei(en) öffnen"
-
-#: /home/ruben/Projects/Cura/resources/qml/OpenFilesIncludingProjectsDialog.qml:64
-msgctxt "@text:window"
-msgid "We have found one or more project file(s) within the files you have selected. You can open only one project file at a time. We suggest to only import models from those files. Would you like to proceed?"
-msgstr "Es wurden eine oder mehrere Projektdatei(en) innerhalb der von Ihnen gewählten Dateien gefunden. Sie können nur eine Projektdatei auf einmal öffnen. Es wird empfohlen, nur Modelle aus diesen Dateien zu importieren. Möchten Sie fortfahren?"
-
-#: /home/ruben/Projects/Cura/resources/qml/OpenFilesIncludingProjectsDialog.qml:99
-msgctxt "@action:button"
-msgid "Import all as models"
-msgstr "Alle als Modelle importieren"
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:19
+#: /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:104
-msgctxt "@title:menu menubar:toplevel"
-msgid "&File"
-msgstr "&Datei"
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:120
-msgctxt "@title:menu menubar:file"
-msgid "&Save..."
-msgstr "&Speichern..."
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:141
-msgctxt "@title:menu menubar:file"
-msgid "&Export..."
-msgstr "&Exportieren..."
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:151
-msgctxt "@action:inmenu menubar:file"
-msgid "Export Selection..."
-msgstr "Auswahl exportieren..."
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:168
-msgctxt "@title:menu menubar:toplevel"
-msgid "&Edit"
-msgstr "&Bearbeiten"
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:185
-msgctxt "@title:menu"
-msgid "&View"
-msgstr "&Ansicht"
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:190
-msgctxt "@title:menu"
-msgid "&Settings"
-msgstr "&Konfiguration"
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:192
-msgctxt "@title:menu menubar:settings"
-msgid "&Printer"
-msgstr "Dr&ucker"
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:201
-msgctxt "@title:menu"
-msgid "&Material"
-msgstr "&Material"
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:210
-msgctxt "@action:inmenu"
-msgid "Set as Active Extruder"
-msgstr "Als aktiven Extruder festlegen"
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:216
-#: /home/ruben/Projects/Cura/resources/qml/SidebarHeader.qml:188
-msgctxt "@action:inmenu"
-msgid "Enable Extruder"
-msgstr "Extruder aktivieren"
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:223
-#: /home/ruben/Projects/Cura/resources/qml/SidebarHeader.qml:194
-msgctxt "@action:inmenu"
-msgid "Disable Extruder"
-msgstr "Extruder deaktivieren"
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:235
-msgctxt "@title:menu"
-msgid "&Build plate"
-msgstr "&Druckplatte"
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:236
-msgctxt "@title:settings"
-msgid "&Profile"
-msgstr "&Profil"
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:246
-msgctxt "@title:menu menubar:toplevel"
-msgid "E&xtensions"
-msgstr "Er&weiterungen"
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:280
-msgctxt "@title:menu menubar:toplevel"
-msgid "&Toolbox"
-msgstr "&Toolbox"
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:287
-msgctxt "@title:menu menubar:toplevel"
-msgid "P&references"
-msgstr "E&instellungen"
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:295
-msgctxt "@title:menu menubar:toplevel"
-msgid "&Help"
-msgstr "&Hilfe"
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:341
+#: /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:370
-msgctxt "@action:button"
-msgid "Open File"
-msgstr "Datei öffnen"
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:540
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:413
msgctxt "@title:tab"
msgid "Settings"
msgstr "Einstellungen"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:586
-msgctxt "@title:window"
-msgid "New project"
-msgstr "Neues Projekt"
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:587
-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."
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:715
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:539
msgctxt "@title:window"
msgid "Closing Cura"
msgstr "Cura wird geschlossen"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:716
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:728
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:540
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:552
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:861
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:590
+#: /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:691
msgctxt "@window:title"
msgid "Install Package"
msgstr "Paket installieren"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:868
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:699
msgctxt "@title:window"
msgid "Open File(s)"
msgstr "Datei(en) öffnen"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:871
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:702
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/WorkspaceSummaryDialog.qml:14
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:805
msgctxt "@title:window"
-msgid "Save Project"
-msgstr "Projekt speichern"
+msgid "Add Printer"
+msgstr "Drucker hinzufügen"
-#: /home/ruben/Projects/Cura/resources/qml/WorkspaceSummaryDialog.qml:120
-msgctxt "@action:label"
-msgid ""
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/WorkspaceSummaryDialog.qml:137
-msgctxt "@action:label"
-msgid "Build plate"
-msgstr "Druckplatte"
-
-#: /home/ruben/Projects/Cura/resources/qml/WorkspaceSummaryDialog.qml:169
-msgctxt "@action:label"
-msgid "Extruder %1"
-msgstr "Extruder %1"
-
-#: /home/ruben/Projects/Cura/resources/qml/WorkspaceSummaryDialog.qml:179
-msgctxt "@action:label"
-msgid "%1 & material"
-msgstr "%1 & Material"
-
-#: /home/ruben/Projects/Cura/resources/qml/WorkspaceSummaryDialog.qml:268
-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/WorkspaceSummaryDialog.qml:287
-msgctxt "@action:button"
-msgid "Save"
-msgstr "Speichern"
-
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:192
-msgctxt "@label"
-msgid "Layer Height"
-msgstr "Schichtdicke"
-
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:277
-msgctxt "@tooltip"
-msgid "This quality profile is not available for you 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 dieses Qualitätsprofil zu aktivieren"
-
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:450
-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/SidebarSimple.qml:467
-msgctxt "@label"
-msgid "Print Speed"
-msgstr "Druckgeschwindigkeit"
-
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:479
-msgctxt "@label"
-msgid "Slower"
-msgstr "Langsamer"
-
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:490
-msgctxt "@label"
-msgid "Faster"
-msgstr "Schneller"
-
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:518
-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/SidebarSimple.qml:541
-msgctxt "@label"
-msgid "Infill"
-msgstr "Füllung"
-
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:777
-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/SidebarSimple.qml:789
-msgctxt "@label"
-msgid "Enable gradual"
-msgstr "Graduell aktivieren"
-
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:856
-msgctxt "@label"
-msgid "Generate Support"
-msgstr "Stützstruktur generieren"
-
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:890
-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/SidebarSimple.qml:962
-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/SidebarSimple.qml:985
-msgctxt "@label"
-msgid "Build Plate Adhesion"
-msgstr "Druckplattenhaftung"
-
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:1040
-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/SidebarSimple.qml:1080
-msgctxt "@label"
-msgid "Need help improving your prints? Read the Ultimaker Troubleshooting Guides"
-msgstr "Sie benötigen Hilfe für Ihre Drucke? Lesen Sie die Ultimaker Anleitungen für Fehlerbehebung>"
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:813
+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"
@@ -4407,75 +4580,483 @@ msgid_plural "Print Selected Models with %1"
msgstr[0] "Ausgewähltes Modell drucken mit %1"
msgstr[1] "Ausgewählte Modelle drucken mit %1"
-#: /home/ruben/Projects/Cura/resources/qml/AskOpenAsProjectOrModelsDialog.qml:20
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/DiscardOrKeepProfileChangesDialog.qml:15
+msgctxt "@title:window"
+msgid "Discard or Keep changes"
+msgstr "Änderungen verwerfen oder übernehmen"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/DiscardOrKeepProfileChangesDialog.qml:57
+msgctxt "@text:window"
+msgid ""
+"You have customized some profile settings.\n"
+"Would you like to keep or discard those settings?"
+msgstr ""
+"Sie haben einige Profileinstellungen angepasst.\n"
+"Möchten Sie diese Einstellungen übernehmen oder verwerfen?"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/DiscardOrKeepProfileChangesDialog.qml:110
+msgctxt "@title:column"
+msgid "Profile settings"
+msgstr "Profileinstellungen"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/DiscardOrKeepProfileChangesDialog.qml:117
+msgctxt "@title:column"
+msgid "Default"
+msgstr "Standard"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/DiscardOrKeepProfileChangesDialog.qml:124
+msgctxt "@title:column"
+msgid "Customized"
+msgstr "Angepasst"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/DiscardOrKeepProfileChangesDialog.qml:158
+msgctxt "@option:discardOrKeep"
+msgid "Discard and never ask again"
+msgstr "Verwerfen und zukünftig nicht mehr nachfragen"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/DiscardOrKeepProfileChangesDialog.qml:159
+msgctxt "@option:discardOrKeep"
+msgid "Keep and never ask again"
+msgstr "Übernehmen und zukünftig nicht mehr nachfragen"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/DiscardOrKeepProfileChangesDialog.qml:196
+msgctxt "@action:button"
+msgid "Discard"
+msgstr "Verwerfen"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/DiscardOrKeepProfileChangesDialog.qml:209
+msgctxt "@action:button"
+msgid "Keep"
+msgstr "Übernehmen"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/DiscardOrKeepProfileChangesDialog.qml:222
+msgctxt "@action:button"
+msgid "Create New Profile"
+msgstr "Neues Profil erstellen"
+
+#: /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
+msgctxt "@label"
+msgid "version: %1"
+msgstr "Version: %1"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:71
+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
+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 ""
+"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
+msgctxt "@label"
+msgid "Graphical user interface"
+msgstr "Grafische Benutzerschnittstelle"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:135
+msgctxt "@label"
+msgid "Application framework"
+msgstr "Anwendungsrahmenwerk"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:136
+msgctxt "@label"
+msgid "G-code generator"
+msgstr "G-Code-Generator"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:137
+msgctxt "@label"
+msgid "Interprocess communication library"
+msgstr "Bibliothek Interprozess-Kommunikation"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:139
+msgctxt "@label"
+msgid "Programming language"
+msgstr "Programmiersprache"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:140
+msgctxt "@label"
+msgid "GUI framework"
+msgstr "GUI-Rahmenwerk"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:141
+msgctxt "@label"
+msgid "GUI framework bindings"
+msgstr "GUI-Rahmenwerk Einbindungen"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:142
+msgctxt "@label"
+msgid "C/C++ Binding library"
+msgstr "C/C++ Einbindungsbibliothek"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:143
+msgctxt "@label"
+msgid "Data interchange format"
+msgstr "Format Datenaustausch"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:144
+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
+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
+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
+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
+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
+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
+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
+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
+msgctxt "@label"
+msgid "Serial communication library"
+msgstr "Bibliothek für serielle Kommunikation"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:153
+msgctxt "@label"
+msgid "ZeroConf discovery library"
+msgstr "Bibliothek für ZeroConf-Erkennung"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:154
+msgctxt "@label"
+msgid "Polygon clipping library"
+msgstr "Bibliothek für Polygon-Beschneidung"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:155
+msgctxt "@Label"
+msgid "Python HTTP library"
+msgstr "Bibliothek für Python HTTP"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:157
+msgctxt "@label"
+msgid "Font"
+msgstr "Schriftart"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:158
+msgctxt "@label"
+msgid "SVG icons"
+msgstr "SVG-Symbole"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:159
+msgctxt "@label"
+msgid "Linux cross-distribution application deployment"
+msgstr "Distributionsunabhängiges Format für Linux-Anwendungen"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/OpenFilesIncludingProjectsDialog.qml:64
+msgctxt "@text:window"
+msgid "We have found one or more project file(s) within the files you have selected. You can open only one project file at a time. We suggest to only import models from those files. Would you like to proceed?"
+msgstr "Es wurden eine oder mehrere Projektdatei(en) innerhalb der von Ihnen gewählten Dateien gefunden. Sie können nur eine Projektdatei auf einmal öffnen. Es wird empfohlen, nur Modelle aus diesen Dateien zu importieren. Möchten Sie fortfahren?"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/OpenFilesIncludingProjectsDialog.qml:99
+msgctxt "@action:button"
+msgid "Import all as models"
+msgstr "Alle als Modelle importieren"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:15
+msgctxt "@title:window"
+msgid "Save Project"
+msgstr "Projekt speichern"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:149
+msgctxt "@action:label"
+msgid "Build plate"
+msgstr "Druckplatte"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:183
+msgctxt "@action:label"
+msgid "Extruder %1"
+msgstr "Extruder %1"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:198
+msgctxt "@action:label"
+msgid "%1 & material"
+msgstr "%1 & Material"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:200
+msgctxt "@action:label"
+msgid "Material"
+msgstr "Material"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:272
+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:291
+msgctxt "@action:button"
+msgid "Save"
+msgstr "Speichern"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AskOpenAsProjectOrModelsDialog.qml:20
msgctxt "@title:window"
msgid "Open project file"
msgstr "Projektdatei öffnen"
-#: /home/ruben/Projects/Cura/resources/qml/AskOpenAsProjectOrModelsDialog.qml:93
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AskOpenAsProjectOrModelsDialog.qml:93
msgctxt "@text:window"
msgid "This is a Cura project file. Would you like to open it as a project or import the models from it?"
msgstr "Dies ist eine Cura-Projektdatei. Möchten Sie diese als Projekt öffnen oder die Modelle hieraus importieren?"
-#: /home/ruben/Projects/Cura/resources/qml/AskOpenAsProjectOrModelsDialog.qml:103
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AskOpenAsProjectOrModelsDialog.qml:103
msgctxt "@text:window"
msgid "Remember my choice"
msgstr "Meine Auswahl merken"
-#: /home/ruben/Projects/Cura/resources/qml/AskOpenAsProjectOrModelsDialog.qml:122
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AskOpenAsProjectOrModelsDialog.qml:122
msgctxt "@action:button"
msgid "Open as project"
msgstr "Als Projekt öffnen"
-#: /home/ruben/Projects/Cura/resources/qml/AskOpenAsProjectOrModelsDialog.qml:131
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AskOpenAsProjectOrModelsDialog.qml:131
msgctxt "@action:button"
msgid "Import models"
msgstr "Modelle importieren"
-#: /home/ruben/Projects/Cura/resources/qml/EngineLog.qml:15
-msgctxt "@title:window"
-msgid "Engine Log"
-msgstr "Engine-Protokoll"
-
-#: /home/ruben/Projects/Cura/resources/qml/SidebarHeader.qml:70
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/DropDownWidget.qml:93
msgctxt "@label"
-msgid "Printer type"
-msgstr "Druckertyp"
+msgid "Empty"
+msgstr "Leer"
-#: /home/ruben/Projects/Cura/resources/qml/SidebarHeader.qml:376
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddNetworkOrLocalPrinterContent.qml:24
msgctxt "@label"
-msgid "Material"
-msgstr "Material"
+msgid "Add a printer"
+msgstr "Einen Drucker hinzufügen"
-#: /home/ruben/Projects/Cura/resources/qml/SidebarHeader.qml:543
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddNetworkOrLocalPrinterContent.qml:39
msgctxt "@label"
-msgid "Use glue with this material combination"
-msgstr "Für diese Materialkombination Kleber verwenden"
+msgid "Add a networked printer"
+msgstr "Einen vernetzten Drucker hinzufügen"
-#: /home/ruben/Projects/Cura/resources/qml/SidebarHeader.qml:575
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddNetworkOrLocalPrinterContent.qml:81
msgctxt "@label"
-msgid "Check compatibility"
-msgstr "Kompatibilität prüfen"
+msgid "Add a non-networked printer"
+msgstr "Einen unvernetzten Drucker hinzufügen"
-#: /home/ruben/Projects/Cura/resources/qml/SidebarHeader.qml:593
-msgctxt "@tooltip"
-msgid "Click to check the material compatibility on Ultimaker.com."
-msgstr "Klicken Sie, um die Materialkompatibilität auf Ultimaker.com zu prüfen."
+#: /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/ObjectsList.qml:211
-msgctxt "@option:check"
-msgid "See only current build plate"
-msgstr "Nur aktuelle Druckplatte anzeigen"
+#: /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/ObjectsList.qml:227
-msgctxt "@action:button"
-msgid "Arrange to all build plates"
-msgstr "An allen Druckplatten ausrichten"
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddPrinterByIpContent.qml:158
+msgctxt "@button"
+msgid "Add"
+msgstr "Hinzufügen"
-#: /home/ruben/Projects/Cura/resources/qml/ObjectsList.qml:247
-msgctxt "@action:button"
-msgid "Arrange current build plate"
-msgstr "An aktueller Druckplatte ausrichten"
+#: /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:207
+msgctxt "@label"
+msgid "Printer name"
+msgstr "Druckername"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddLocalPrinterScrollView.qml:220
+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"
#: MachineSettingsAction/plugin.json
msgctxt "description"
@@ -4547,26 +5128,36 @@ msgctxt "name"
msgid "God Mode"
msgstr "Gott-Modus"
-#: ChangeLogPlugin/plugin.json
+#: FirmwareUpdater/plugin.json
msgctxt "description"
-msgid "Shows changes since latest checked version."
-msgstr "Zeigt die Änderungen seit der letzten geprüften Version an."
+msgid "Provides a machine actions for updating firmware."
+msgstr "Ermöglicht Gerätemaßnahmen für die Aktualisierung der Firmware."
-#: ChangeLogPlugin/plugin.json
+#: FirmwareUpdater/plugin.json
msgctxt "name"
-msgid "Changelog"
-msgstr "Änderungsprotokoll"
+msgid "Firmware Updater"
+msgstr "Firmware-Aktualisierungsfunktion"
#: ProfileFlattener/plugin.json
msgctxt "description"
-msgid "Create a flattend quality changes profile."
+msgid "Create a flattened quality changes profile."
msgstr "Erstellt eine geglättete Qualität, verändert das Profil."
#: ProfileFlattener/plugin.json
msgctxt "name"
-msgid "Profile flatener"
+msgid "Profile Flattener"
msgstr "Profilglättfunktion"
+#: 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."
@@ -4577,26 +5168,6 @@ msgctxt "name"
msgid "USB printing"
msgstr "USB-Drucken"
-#: UserAgreement/plugin.json
-msgctxt "description"
-msgid "Ask the user once if he/she agrees with our license."
-msgstr "Den Benutzer einmalig fragen, ob er unsere Lizenz akzeptiert."
-
-#: UserAgreement/plugin.json
-msgctxt "name"
-msgid "UserAgreement"
-msgstr "UserAgreement"
-
-#: X3GWriter/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)."
-
-#: X3GWriter/plugin.json
-msgctxt "name"
-msgid "X3GWriter"
-msgstr "X3G-Writer"
-
#: GCodeGzWriter/plugin.json
msgctxt "description"
msgid "Writes g-code to a compressed archive."
@@ -4647,6 +5218,16 @@ msgctxt "name"
msgid "UM3 Network Connection"
msgstr "UM3-Netzwerkverbindung"
+#: SettingsGuide/plugin.json
+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."
+
+#: SettingsGuide/plugin.json
+msgctxt "name"
+msgid "Settings Guide"
+msgstr "Anleitung für Einstellungen"
+
#: MonitorStage/plugin.json
msgctxt "description"
msgid "Provides a monitor stage in Cura."
@@ -4707,6 +5288,16 @@ 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."
@@ -4787,6 +5378,16 @@ 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."
@@ -4797,6 +5398,16 @@ 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."
@@ -4807,6 +5418,16 @@ 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."
@@ -4897,6 +5518,16 @@ 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."
@@ -4927,6 +5558,16 @@ 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.)."
@@ -4947,6 +5588,733 @@ msgctxt "name"
msgid "Cura Profile Reader"
msgstr "Cura-Profil-Reader"
+#~ 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"
+
+#~ msgctxt "@info:status"
+#~ msgid "Nothing to slice because none of the models fit the build volume. Please scale or rotate models to fit."
+#~ msgstr "Es ist kein Objekt zum Schneiden vorhanden, da keines der Modelle der Druckabmessung entspricht. Bitte die Modelle passend skalieren oder drehen."
+
+#~ msgctxt "@info:status"
+#~ msgid "The selected material is incompatible with the selected machine or configuration."
+#~ msgstr "Das gewählte Material ist mit der gewählten Maschine oder Konfiguration nicht kompatibel."
+
+#~ msgctxt "@info:title"
+#~ msgid "Incompatible Material"
+#~ msgstr "Material nicht kompatibel"
+
+#~ msgctxt "@info:status Don't translate the XML tags or !"
+#~ msgid "Failed to import profile from {0}: {1}"
+#~ msgstr "Import des Profils aus Datei {0} fehlgeschlagen: {1}"
+
+#~ msgctxt "@title"
+#~ msgid "Toolbox"
+#~ msgstr "Toolbox"
+
+#~ msgctxt "@label"
+#~ msgid "Not available"
+#~ msgstr "Nicht verfügbar"
+
+#~ msgctxt "@label"
+#~ msgid "Unreachable"
+#~ msgstr "Nicht erreichbar"
+
+#~ msgctxt "@label"
+#~ msgid "Available"
+#~ msgstr "Verfügbar"
+
+#~ msgctxt "@label:status"
+#~ msgid "Preparing"
+#~ msgstr "Vorbereitung"
+
+#~ msgctxt "@label:status"
+#~ msgid "Pausing"
+#~ msgstr "Wird pausiert"
+
+#~ msgctxt "@label:status"
+#~ msgid "Resuming"
+#~ msgstr "Wird fortgesetzt"
+
+#~ msgctxt "@label"
+#~ msgid "Waiting for: Unavailable printer"
+#~ msgstr "Warten auf: Drucker nicht verfügbar"
+
+#~ msgctxt "@label"
+#~ msgid "Waiting for: First available"
+#~ msgstr "Warten auf: Ersten verfügbaren"
+
+#~ msgctxt "@label"
+#~ msgid "Waiting for: "
+#~ msgstr "Warten auf: "
+
+#~ msgctxt "@label"
+#~ msgid "Configuration change"
+#~ msgstr "Konfigurationsänderung"
+
+#~ msgctxt "@label"
+#~ msgid "The assigned printer, %1, requires the following configuration change(s):"
+#~ msgstr "Der zugewiesene Drucker %1 erfordert die folgende(n) Konfigurationsänderung(en):"
+
+#~ msgctxt "@label"
+#~ msgid "Override"
+#~ msgstr "Überschreiben"
+
+#~ msgctxt "@label"
+#~ msgid "Starting a print job with an incompatible configuration could damage your 3D printer. Are you sure you want to override the configuration and print %1?"
+#~ msgstr "Das Starten eines Druckauftrags mit einer inkompatiblen Konfiguration kann Ihren 3D-Drucker beschädigen. Möchten Sie die Konfiguration wirklich überschreiben und %1 drucken?"
+
+#~ msgctxt "@window:title"
+#~ msgid "Override configuration configuration and start print"
+#~ msgstr "Konfiguration überschreiben und Druck starten"
+
+#~ msgctxt "@label link to connect manager"
+#~ msgid "Manage queue"
+#~ msgstr "Warteschlange verwalten"
+
+#~ msgctxt "@label"
+#~ msgid "Printing"
+#~ msgstr "Drucken"
+
+#~ msgctxt "@label link to connect manager"
+#~ msgid "Manage printers"
+#~ msgstr "Drucker verwalten"
+
+#~ msgctxt "@action:button"
+#~ msgid "Activate Configuration"
+#~ msgstr "Konfiguration aktivieren"
+
+#~ msgctxt "@info:tooltip"
+#~ msgid "Load the configuration of the printer into Cura"
+#~ msgstr "Die Druckerkonfiguration in Cura laden"
+
+#~ msgctxt "@label"
+#~ msgid "Show Travels"
+#~ msgstr "Bewegungen anzeigen"
+
+#~ msgctxt "@label"
+#~ msgid "Show Helpers"
+#~ msgstr "Helfer anzeigen"
+
+#~ msgctxt "@label"
+#~ msgid "Show Shell"
+#~ msgstr "Gehäuse anzeigen"
+
+#~ msgctxt "@label"
+#~ msgid "Show Infill"
+#~ msgstr "Füllung anzeigen"
+
+#~ msgctxt "@text:window"
+#~ msgid "I don't want to send these data"
+#~ msgstr "Ich möchte diese Daten nicht senden"
+
+#~ msgctxt "@text:window"
+#~ msgid "Allow sending these data to Ultimaker and help us improve Cura"
+#~ msgstr "Ich erlaube das Senden dieser Daten an Ultimaker, um Cura zu verbessern"
+
+#~ msgctxt "@label"
+#~ msgid "Printer type:"
+#~ msgstr "Druckertyp:"
+
+#~ msgctxt "@label"
+#~ msgid "Connection:"
+#~ msgstr "Verbindung:"
+
+#~ msgctxt "@label"
+#~ msgid "State:"
+#~ msgstr "Status:"
+
+#~ msgctxt "@label:MonitorStatus"
+#~ msgid "Waiting for a printjob"
+#~ msgstr "Warten auf einen Druckauftrag"
+
+#~ msgctxt "@label:MonitorStatus"
+#~ msgid "Waiting for someone to clear the build plate"
+#~ msgstr "Warten auf Räumen des Druckbeets"
+
+#~ msgctxt "@label:MonitorStatus"
+#~ msgid "Aborting print..."
+#~ msgstr "Drucken wird abgebrochen..."
+
+#~ msgctxt "@label"
+#~ msgid "Protected profiles"
+#~ msgstr "Geschützte Profile"
+
+#~ msgctxt "@label"
+#~ msgid "Printer Name:"
+#~ msgstr "Druckername:"
+
+#~ msgctxt "@label"
+#~ msgid "Profile:"
+#~ msgstr "Profil:"
+
+#~ msgctxt "@label:textbox"
+#~ msgid "Search..."
+#~ msgstr "Suchen..."
+
+#~ msgctxt "@action:inmenu"
+#~ msgid "Collapse All"
+#~ msgstr "Alle verkleinern"
+
+#~ msgctxt "@action:inmenu"
+#~ msgid "Expand All"
+#~ msgstr "Alle vergrößern"
+
+#~ msgctxt "@label:header configurations"
+#~ msgid "Available configurations"
+#~ msgstr "Verfügbare Konfigurationen"
+
+#~ msgctxt "@label:extruder label"
+#~ msgid "Extruder"
+#~ msgstr "Extruder"
+
+#~ msgctxt "@label:extruder label"
+#~ msgid "Yes"
+#~ msgstr "Ja"
+
+#~ msgctxt "@label:extruder label"
+#~ msgid "No"
+#~ msgstr "Nein"
+
+#~ msgctxt "@label:listbox"
+#~ msgid "Print Setup"
+#~ msgstr "Druckeinrichtung"
+
+#~ msgctxt "@label:listbox"
+#~ msgid ""
+#~ "Print Setup disabled\n"
+#~ "G-code files cannot be modified"
+#~ msgstr ""
+#~ "Druckeinrichtung deaktiviert\n"
+#~ "G-Code-Dateien können nicht geändert werden"
+
+#~ msgctxt "@label Hours and minutes"
+#~ msgid "00h 00min"
+#~ msgstr "00 Stunden 00 Minuten"
+
+#~ msgctxt "@tooltip"
+#~ msgid "Time specification"
+#~ msgstr "Zeitangabe"
+
+#~ msgctxt "@label"
+#~ msgid "Cost specification"
+#~ msgstr "Kostenangabe"
+
+#~ msgctxt "@label"
+#~ msgid "Total:"
+#~ msgstr "Insgesamt:"
+
+#~ msgctxt "@tooltip"
+#~ msgid "Recommended Print Setup
Print with the recommended settings for the selected printer, material and quality."
+#~ msgstr "Empfohlene Druckeinrichtung
Drucken mit den empfohlenen Einstellungen für den gewählten Drucker, das gewählte Material und die gewählte Qualität."
+
+#~ msgctxt "@tooltip"
+#~ msgid "Custom Print Setup
Print with finegrained control over every last bit of the slicing process."
+#~ msgstr "Benutzerdefinierte Druckeinrichtung
Druck mit Feineinstellung über jedem einzelnen Bereich des Schneidvorgangs."
+
+#~ msgctxt "@action:inmenu menubar:help"
+#~ msgid "Show Engine &Log..."
+#~ msgstr "Engine-&Protokoll anzeigen..."
+
+#~ msgctxt "@action:menu"
+#~ msgid "Browse packages..."
+#~ msgstr "Pakete durchsuchen..."
+
+#~ msgctxt "@action:inmenu menubar:view"
+#~ msgid "Expand/Collapse Sidebar"
+#~ msgstr "Seitenleiste vergrößern/verkleinern"
+
+#~ msgctxt "@label:PrintjobStatus"
+#~ msgid "Please load a 3D model"
+#~ msgstr "Bitte laden Sie ein 3D-Modell"
+
+#~ msgctxt "@label:PrintjobStatus"
+#~ msgid "Ready to slice"
+#~ msgstr "Bereit zum Slicen (Schneiden)"
+
+#~ msgctxt "@label:PrintjobStatus %1 is target operation"
+#~ msgid "Ready to %1"
+#~ msgstr "Bereit zum %1"
+
+#~ msgctxt "@label:PrintjobStatus"
+#~ msgid "Slicing unavailable"
+#~ msgstr "Slicing ist nicht verfügbar"
+
+#~ msgctxt "@info:tooltip"
+#~ msgid "Slice current printjob"
+#~ msgstr "Aktuellen Druckauftrag slicen"
+
+#~ msgctxt "@info:tooltip"
+#~ msgid "Cancel slicing process"
+#~ msgstr "Slicing-Vorgang abbrechen"
+
+#~ msgctxt "@label:Printjob"
+#~ msgid "Prepare"
+#~ msgstr "Vorbereiten"
+
+#~ msgctxt "@label:Printjob"
+#~ msgid "Cancel"
+#~ msgstr "Abbrechen"
+
+#~ msgctxt "@info:tooltip"
+#~ msgid "Select the active output device"
+#~ msgstr "Wählen Sie das aktive Ausgabegerät"
+
+#~ msgctxt "@title:menu"
+#~ msgid "&View"
+#~ msgstr "&Ansicht"
+
+#~ msgctxt "@title:menu"
+#~ msgid "&Settings"
+#~ msgstr "&Konfiguration"
+
+#~ msgctxt "@title:menu menubar:toplevel"
+#~ msgid "&Toolbox"
+#~ msgstr "&Toolbox"
+
+#~ msgctxt "@action:button"
+#~ msgid "Open File"
+#~ msgstr "Datei öffnen"
+
+#~ msgctxt "@tooltip"
+#~ msgid "This quality profile is not available for you 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 dieses Qualitätsprofil zu aktivieren"
+
+#~ msgctxt "@label"
+#~ msgid "Print Speed"
+#~ msgstr "Druckgeschwindigkeit"
+
+#~ msgctxt "@label"
+#~ msgid "Slower"
+#~ msgstr "Langsamer"
+
+#~ msgctxt "@label"
+#~ msgid "Faster"
+#~ msgstr "Schneller"
+
+#~ msgctxt "@label"
+#~ msgid "Enable gradual"
+#~ msgstr "Graduell aktivieren"
+
+#~ msgctxt "@label"
+#~ msgid "Generate Support"
+#~ msgstr "Stützstruktur generieren"
+
+#~ msgctxt "@label"
+#~ msgid "Build Plate Adhesion"
+#~ msgstr "Druckplattenhaftung"
+
+#~ msgctxt "@label"
+#~ msgid "Need help improving your prints? Read the Ultimaker Troubleshooting Guides"
+#~ msgstr "Sie benötigen Hilfe für Ihre Drucke? Lesen Sie die Ultimaker Anleitungen für Fehlerbehebung>"
+
+#~ msgctxt "@title:window"
+#~ msgid "Engine Log"
+#~ msgstr "Engine-Protokoll"
+
+#~ msgctxt "@label"
+#~ msgid "Printer type"
+#~ msgstr "Druckertyp"
+
+#~ msgctxt "@label"
+#~ msgid "Use glue with this material combination"
+#~ msgstr "Für diese Materialkombination Kleber verwenden"
+
+#~ msgctxt "@label"
+#~ msgid "Check compatibility"
+#~ msgstr "Kompatibilität prüfen"
+
+#~ msgctxt "@tooltip"
+#~ 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 "Shows changes since latest checked version."
+#~ msgstr "Zeigt die Änderungen seit der letzten geprüften Version an."
+
+#~ msgctxt "name"
+#~ msgid "Changelog"
+#~ msgstr "Änderungsprotokoll"
+
+#~ msgctxt "description"
+#~ msgid "Create a flattend quality changes profile."
+#~ msgstr "Erstellt eine geglättete Qualität, verändert das Profil."
+
+#~ msgctxt "name"
+#~ msgid "Profile flatener"
+#~ msgstr "Profilglättfunktion"
+
+#~ msgctxt "description"
+#~ msgid "Ask the user once if he/she agrees with our license."
+#~ msgstr "Den Benutzer einmalig fragen, ob er unsere Lizenz akzeptiert."
+
+#~ msgctxt "name"
+#~ msgid "UserAgreement"
+#~ msgstr "UserAgreement"
+
+#~ msgctxt "@warning:status"
+#~ msgid "Please generate G-code before saving."
+#~ msgstr "Generieren Sie vor dem Speichern bitte einen G-Code."
+
+#~ msgctxt "@action"
+#~ msgid "Upgrade Firmware"
+#~ msgstr "Firmware aktualisieren"
+
+#~ msgctxt "@label unknown material"
+#~ msgid "Unknown"
+#~ msgstr "Unbekannt"
+
+#~ msgctxt "@info:status Don't translate the XML tags or !"
+#~ msgid "No custom profile to import in file {0}"
+#~ msgstr "Kein benutzerdefiniertes Profil für das Importieren in Datei {0}"
+
+#~ msgctxt "@info:status Don't translate the XML tags or !"
+#~ msgid "This profile {0} contains incorrect data, could not import it."
+#~ msgstr "Dieses Profil {0} enthält falsche Daten, Importieren nicht möglich."
+
+#~ msgctxt "@info:status Don't translate the XML tags or !"
+#~ 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 "@title:window"
+#~ msgid "Confirm uninstall "
+#~ msgstr "Deinstallieren bestätigen "
+
+#~ msgctxt "@label Print estimates: m for meters, g for grams, %4 is currency and %3 is print cost"
+#~ msgid "%1m / ~ %2g / ~ %4 %3"
+#~ msgstr "%1m / ~ %2g / ~ %4 %3"
+
+#~ msgctxt "@label Print estimates: m for meters, g for grams"
+#~ msgid "%1m / ~ %2g"
+#~ msgstr "%1m / ~ %2g"
+
+#~ msgctxt "@title"
+#~ msgid "Upgrade Firmware"
+#~ msgstr "Firmware aktualisieren"
+
#~ msgctxt "@action:button"
#~ msgid "Print with Doodle3D WiFi-Box"
#~ msgstr "Mit Doodle3D WLAN-Box drucken"
@@ -5039,10 +6407,6 @@ msgstr "Cura-Profil-Reader"
#~ msgid "Lost connection with the printer"
#~ msgstr "Verbindung zum Drucker wurde unterbrochen"
-#~ msgctxt "@label:status"
-#~ msgid "Unavailable"
-#~ msgstr "Nicht verfügbar"
-
#~ msgctxt "@label:status"
#~ msgid "Unknown"
#~ msgstr "Unbekannt"
diff --git a/resources/i18n/de_DE/fdmextruder.def.json.po b/resources/i18n/de_DE/fdmextruder.def.json.po
index 56b6c35c93..3df5bac5ef 100644
--- a/resources/i18n/de_DE/fdmextruder.def.json.po
+++ b/resources/i18n/de_DE/fdmextruder.def.json.po
@@ -1,14 +1,14 @@
# Cura
-# Copyright (C) 2018 Ultimaker
+# Copyright (C) 2019 Ultimaker B.V.
# This file is distributed under the same license as the Cura package.
-# Ruben Dulek , 2018.
+# Ruben Dulek , 2019.
#
msgid ""
msgstr ""
-"Project-Id-Version: Cura 3.5\n"
+"Project-Id-Version: Cura 4.2\n"
"Report-Msgid-Bugs-To: r.dulek@ultimaker.com\n"
-"POT-Creation-Date: 2018-09-19 17:07+0000\n"
-"PO-Revision-Date: 2018-09-28 14:25+0100\n"
+"POT-Creation-Date: 2019-07-16 14:38+0000\n"
+"PO-Revision-Date: 2019-03-13 14:00+0200\n"
"Last-Translator: Bothof \n"
"Language-Team: German\n"
"Language: de_DE\n"
@@ -83,8 +83,8 @@ msgstr "G-Code Extruder-Start"
#: fdmextruder.def.json
msgctxt "machine_extruder_start_code description"
-msgid "Start g-code to execute whenever turning the extruder on."
-msgstr "Starten Sie den G-Code jedes Mal, wenn Sie den Extruder einschalten."
+msgid "Start g-code to execute when switching to this extruder."
+msgstr "Auszuführenden G-Code beim Umschalten auf diesen Extruder starten."
#: fdmextruder.def.json
msgctxt "machine_extruder_start_pos_abs label"
@@ -123,8 +123,8 @@ msgstr "G-Code Extruder-Ende"
#: fdmextruder.def.json
msgctxt "machine_extruder_end_code description"
-msgid "End g-code to execute whenever turning the extruder off."
-msgstr "Beenden Sie den G-Code jedes Mal, wenn Sie den Extruder ausschalten."
+msgid "End g-code to execute when switching away from this extruder."
+msgstr "Auszuführenden G-Code beim Umschalten von diesem Extruder beenden."
#: fdmextruder.def.json
msgctxt "machine_extruder_end_pos_abs label"
@@ -166,6 +166,16 @@ msgctxt "extruder_prime_pos_z description"
msgid "The Z coordinate of the position where the nozzle primes at the start of printing."
msgstr "Die Z-Koordinate der Position, an der die Düse am Druckbeginn einzieht."
+#: fdmextruder.def.json
+msgctxt "machine_extruder_cooling_fan_number label"
+msgid "Extruder Print Cooling Fan"
+msgstr "Drucklüfter Extruder"
+
+#: fdmextruder.def.json
+msgctxt "machine_extruder_cooling_fan_number description"
+msgid "The number of the print cooling fan associated with this extruder. Only change this from the default value of 0 when you have a different print cooling fan for each extruder."
+msgstr "Die Anzahl der Drucklüfter für diesen Extruder. Nur vom Standardwert 0 ändern, wenn Sie für jeden Extruder einen anderen Drucklüfter verwenden."
+
#: fdmextruder.def.json
msgctxt "platform_adhesion label"
msgid "Build Plate Adhesion"
@@ -215,3 +225,11 @@ msgstr "Durchmesser"
msgctxt "material_diameter description"
msgid "Adjusts the diameter of the filament used. Match this value with the diameter of the used filament."
msgstr "Der Durchmesser des verwendeten Filaments wird angepasst. Stellen Sie hier den Durchmesser des verwendeten Filaments ein."
+
+#~ msgctxt "machine_extruder_start_code description"
+#~ msgid "Start g-code to execute whenever turning the extruder on."
+#~ msgstr "Starten Sie den G-Code jedes Mal, wenn Sie den Extruder einschalten."
+
+#~ msgctxt "machine_extruder_end_code description"
+#~ msgid "End g-code to execute whenever turning the extruder off."
+#~ msgstr "Beenden Sie den G-Code jedes Mal, wenn Sie den Extruder ausschalten."
diff --git a/resources/i18n/de_DE/fdmprinter.def.json.po b/resources/i18n/de_DE/fdmprinter.def.json.po
index 3b3e8b9115..cde935ac95 100644
--- a/resources/i18n/de_DE/fdmprinter.def.json.po
+++ b/resources/i18n/de_DE/fdmprinter.def.json.po
@@ -1,16 +1,16 @@
# Cura
-# Copyright (C) 2018 Ultimaker
+# Copyright (C) 2019 Ultimaker B.V.
# This file is distributed under the same license as the Cura package.
-# Ruben Dulek , 2018.
+# Ruben Dulek , 2019.
#
msgid ""
msgstr ""
-"Project-Id-Version: Cura 3.5\n"
+"Project-Id-Version: Cura 4.2\n"
"Report-Msgid-Bugs-To: r.dulek@ultimaker.com\n"
-"POT-Creation-Date: 2018-09-19 17:07+0000\n"
-"PO-Revision-Date: 2018-09-28 14:57+0200\n"
-"Last-Translator: Bothof \n"
-"Language-Team: German\n"
+"POT-Creation-Date: 2019-07-16 14:38+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"
@@ -237,7 +237,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 +247,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 +257,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 +267,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 +277,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 +307,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 +317,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 +337,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 +402,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 +422,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 +432,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 +442,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 +472,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
@@ -1077,7 +1077,7 @@ msgstr "Polygone oben/unten verbinden"
#: fdmprinter.def.json
msgctxt "connect_skin_polygons description"
-msgid "Connect top/bottom skin paths where they run next to each other. For the concentric pattern enabling this setting greatly reduces the travel time, but because the connections can happend midway over infill this feature can reduce the top surface quality."
+msgid "Connect top/bottom skin paths where they run next to each other. For the concentric pattern enabling this setting greatly reduces the travel time, but because the connections can happen midway over infill this feature can reduce the top surface quality."
msgstr "Außenhaut-Pfade oben/unten verbinden, wenn sie nebeneinander laufen. Bei konzentrischen Mustern reduziert die Aktivierung dieser Einstellung die Durchlaufzeit erheblich. Da die Verbindungen jedoch auf halbem Weg über der Füllung erfolgen können, kann diese Funktion die Oberflächenqualität reduzieren."
#: fdmprinter.def.json
@@ -1297,8 +1297,12 @@ 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 +1324,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 +1341,15 @@ 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"
@@ -1497,8 +1508,8 @@ msgstr "Füllmuster"
#: fdmprinter.def.json
msgctxt "infill_pattern description"
-msgid "The pattern of the infill material of the print. The line and zig zag infill swap direction on alternate layers, reducing material cost. The grid, triangle, tri-hexagon, cubic, octet, quarter cubic, cross and concentric patterns are fully printed every layer. Cubic, quarter cubic and octet infill change with every layer to provide a more equal distribution of strength over each direction."
-msgstr "Das Muster des Füllmaterials des Drucks. Die Linien- und Zickzackfüllmethode wechseln nach jeder Schicht die Richtung, um Materialkosten zu reduzieren. Die Gitter-, Dreieck- Tri-Hexagon-, Würfel-, Octahedral-, Viertelwürfel-, Quer- und konzentrischen Muster werden in jeder Schicht vollständig gedruckt. Würfel-, Viertelwürfel- und Octahedral-Füllungen wechseln mit jeder Schicht, um eine gleichmäßigere Verteilung der Stärke in allen Richtungen zu erzielen."
+msgid "The pattern of the infill material of the print. The line and zig zag infill swap direction on alternate layers, reducing material cost. The grid, triangle, tri-hexagon, cubic, octet, quarter cubic, cross and concentric patterns are fully printed every layer. Gyroid, cubic, quarter cubic and octet infill change with every layer to provide a more equal distribution of strength over each direction."
+msgstr "Das Muster des Füllmaterials des Drucks. Die Linien- und Zickzackfüllmethode wechseln nach jeder Schicht die Richtung, um Materialkosten zu reduzieren. Die Gitter-, Dreieck- Tri-Hexagon-, Würfel-, Octahedral-, Viertelwürfel-, Quer- und konzentrischen Muster werden in jeder Schicht vollständig gedruckt. Gyroid-, Würfel-, Viertelwürfel- und Octahedral-Füllungen wechseln mit jeder Schicht, um eine gleichmäßigere Verteilung der Stärke in allen Richtungen zu erzielen."
#: fdmprinter.def.json
msgctxt "infill_pattern option grid"
@@ -1560,6 +1571,11 @@ msgctxt "infill_pattern option cross_3d"
msgid "Cross 3D"
msgstr "3D-Quer"
+#: fdmprinter.def.json
+msgctxt "infill_pattern option gyroid"
+msgid "Gyroid"
+msgstr "Gyroid"
+
#: fdmprinter.def.json
msgctxt "zig_zaggify_infill label"
msgid "Connect Infill Lines"
@@ -1671,8 +1687,8 @@ msgstr "Prozentsatz Außenhaut überlappen"
#: fdmprinter.def.json
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."
+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"
@@ -1681,8 +1697,8 @@ msgstr "Außenhaut überlappen"
#: fdmprinter.def.json
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 "Das Ausmaß des Überlappens zwischen der Außenhaut und den Wänden. Ein leichtes Überlappen ermöglicht es den Wänden, eine solide Verbindung mit der Außenhaut herzustellen."
+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_wipe_dist label"
@@ -1864,6 +1880,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"
@@ -1974,6 +2000,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"
@@ -1984,6 +2090,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"
@@ -2101,8 +2327,9 @@ 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."
-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."
+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
msgctxt "material_standby_temperature label"
@@ -2121,8 +2348,8 @@ msgstr "Düsenschalter Einzugsabstand"
#: fdmprinter.def.json
msgctxt "switch_extruder_retraction_amount description"
-msgid "The amount of retraction: Set at 0 for no retraction at all. This should generally be the same as the length of the heat zone."
-msgstr "Der Wert für den Einzug: 0 einstellen, um keinen Einzug zu erhalten. Dies sollte generell mit der Länge der Heizzone übereinstimmen."
+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 "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"
@@ -2154,6 +2381,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"
@@ -2345,14 +2582,15 @@ 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"
@@ -2781,8 +3019,8 @@ 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 and also to only comb within the infill. Note that the 'Within Infill' option behaves exactly like the 'Not in Skin' option in earlier Cura releases."
-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, indem nur die Füllung berücksichtigt wird. Die Option „Innerhalb der Füllung“ verhält sich genauso wie die Option „Nicht in Außenhaut“ in früheren Cura Versionen."
+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 "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"
@@ -2924,6 +3162,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"
@@ -3194,6 +3442,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"
@@ -3264,6 +3517,36 @@ 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."
+#: fdmprinter.def.json
+msgctxt "support_brim_enable label"
+msgid "Enable Support Brim"
+msgstr "Stütz-Brim aktivieren"
+
+#: fdmprinter.def.json
+msgctxt "support_brim_enable description"
+msgid "Generate a brim within the support infill regions of the first layer. This brim is printed underneath the support, not around it. Enabling this setting increases the adhesion of support to the build plate."
+msgstr "Erstellen Sie ein Brim in den Stützstruktur-Füllungsbereichen der ersten Schicht. Das Brim wird unterhalb der Stützstruktur und nicht drumherum gedruckt. Die Aktivierung dieser Einstellung erhöht die Haftung der Stützstruktur am Druckbett."
+
+#: fdmprinter.def.json
+msgctxt "support_brim_width label"
+msgid "Support Brim Width"
+msgstr "Breite der Brim-Stützstruktur"
+
+#: fdmprinter.def.json
+msgctxt "support_brim_width description"
+msgid "The width of the brim to print underneath the support. A larger brim enhances adhesion to the build plate, at the cost of some extra material."
+msgstr "Die Breite des unter der Stützstruktur zu druckenden Brims. Ein größeres Brim erhöht die Haftung am Druckbett, jedoch erhöht sich hierdurch der Materialverbrauch."
+
+#: fdmprinter.def.json
+msgctxt "support_brim_line_count label"
+msgid "Support Brim Line Count"
+msgstr "Anzahl der Brim-Stützstrukturlinien"
+
+#: fdmprinter.def.json
+msgctxt "support_brim_line_count description"
+msgid "The number of lines used for the support brim. More brim lines enhance adhesion to the build plate, at the cost of some extra material."
+msgstr "Die Anzahl der Linien für die Brim-Stützstruktur. Eine größere Anzahl von Brim-Linien verbessert die Haftung am Druckbett, jedoch erhöht sich hierdurch der Materialverbrauch."
+
#: fdmprinter.def.json
msgctxt "support_z_distance label"
msgid "Support Z Distance"
@@ -3361,8 +3644,9 @@ 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"
@@ -3404,6 +3688,16 @@ msgctxt "gradual_support_infill_step_height description"
msgid "The height of support infill of a given density before switching to half the density."
msgstr "Die Höhe der Stützstruktur-Füllung einer bestimmten Dichte vor dem Umschalten auf die halbe Dichte."
+#: fdmprinter.def.json
+msgctxt "minimum_support_area label"
+msgid "Minimum Support Area"
+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 "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"
msgid "Enable Support Interface"
@@ -3629,6 +3923,66 @@ msgctxt "support_bottom_pattern option zigzag"
msgid "Zig Zag"
msgstr "Zickzack"
+#: fdmprinter.def.json
+msgctxt "minimum_interface_area label"
+msgid "Minimum Support Interface Area"
+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 "Mindestflächenbreite für Stützstruktur-Schnittstellen-Polygone. Polygone, die eine kleinere Fläche als diesen Wert aufweisen, werden nicht generiert."
+
+#: fdmprinter.def.json
+msgctxt "minimum_roof_area label"
+msgid "Minimum Support Roof Area"
+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 "Mindestflächenbreite für die Dächer der Stützstruktur. Polygone, die eine kleinere Fläche als diesen Wert aufweisen, werden nicht generiert."
+
+#: fdmprinter.def.json
+msgctxt "minimum_bottom_area label"
+msgid "Minimum Support Floor Area"
+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 "Mindestflächenbreite für die Böden der Stützstruktur. Polygone, die eine kleinere Fläche als diesen Wert aufweisen, werden nicht generiert."
+
+#: fdmprinter.def.json
+msgctxt "support_interface_offset label"
+msgid "Support Interface Horizontal Expansion"
+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 "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 "Horizontale Erweiterung Stützstrukturdach"
+
+#: fdmprinter.def.json
+msgctxt "support_roof_offset description"
+msgid "Amount of offset applied to the roofs of the support."
+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 "Horizontale Erweiterung Stützstrukturboden"
+
+#: fdmprinter.def.json
+msgctxt "support_bottom_offset description"
+msgid "Amount of offset applied to the floors of the support."
+msgstr "Umfang des angewandten Versatzes für die Böden der Stützstruktur."
+
#: fdmprinter.def.json
msgctxt "support_fan_enable label"
msgid "Fan Speed Override"
@@ -3670,13 +4024,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
@@ -3833,6 +4187,16 @@ msgctxt "brim_line_count description"
msgid "The number of lines used for a brim. More brim lines enhance adhesion to the build plate, but also reduces the effective print area."
msgstr "Die Anzahl der Linien für das Brim-Element. Eine größere Anzahl von Brim-Linien verbessert die Haftung am Druckbett, es wird dadurch aber auch der verwendbare Druckbereich verkleinert."
+#: fdmprinter.def.json
+msgctxt "brim_replaces_support label"
+msgid "Brim Replaces Support"
+msgstr "Brim ersetzt die Stützstruktur"
+
+#: fdmprinter.def.json
+msgctxt "brim_replaces_support description"
+msgid "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."
+msgstr "Erzwingen Sie den Druck des Brims um das Modell herum, auch wenn dieser Raum sonst durch die Stützstruktur belegt würde. Dies ersetzt einige der ersten Schichten der Stützstruktur durch Brim-Bereiche."
+
#: fdmprinter.def.json
msgctxt "brim_outside_only label"
msgid "Brim Only on Outside"
@@ -4163,16 +4527,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"
@@ -4213,16 +4567,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"
@@ -4233,6 +4577,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"
@@ -4515,8 +4869,9 @@ 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"
@@ -4748,6 +5103,16 @@ 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."
+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."
+
#: fdmprinter.def.json
msgctxt "support_skip_some_zags label"
msgid "Break Up Support In Chunks"
@@ -5005,8 +5370,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"
@@ -5349,7 +5714,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
@@ -5359,7 +5724,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
@@ -5369,7 +5734,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
@@ -5379,7 +5744,7 @@ 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"
+msgid "Adaptive Layers Threshold"
msgstr "Schwellenwert Anpassschichten"
#: fdmprinter.def.json
@@ -5597,6 +5962,156 @@ 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 "command_line_settings label"
msgid "Command Line Settings"
@@ -5657,6 +6172,162 @@ 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 "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."
+
+#~ 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 "Das Ausmaß des Überlappens zwischen der Außenhaut und den Wänden. Ein leichtes Überlappen ermöglicht es den Wänden, eine solide Verbindung mit der Außenhaut herzustellen."
+
+#~ msgctxt "switch_extruder_retraction_amount description"
+#~ msgid "The amount of retraction: Set at 0 for no retraction at all. This should generally be the same as the length of the heat zone."
+#~ msgstr "Der Wert für den Einzug: 0 einstellen, um keinen Einzug zu erhalten. Dies sollte generell mit der Länge der Heizzone übereinstimmen."
+
+#~ 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 and also to only comb within the infill. Note that the 'Within Infill' option behaves exactly like the 'Not in Skin' option in earlier Cura releases."
+#~ 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, indem nur die Füllung berücksichtigt wird. Die Option „Innerhalb der Füllung“ verhält sich genauso wie die Option „Nicht in Außenhaut“ in früheren Cura Versionen."
+
+#~ msgctxt "connect_skin_polygons description"
+#~ msgid "Connect top/bottom skin paths where they run next to each other. For the concentric pattern enabling this setting greatly reduces the travel time, but because the connections can happend midway over infill this feature can reduce the top surface quality."
+#~ msgstr "Außenhaut-Pfade oben/unten verbinden, wenn sie nebeneinander laufen. Bei konzentrischen Mustern reduziert die Aktivierung dieser Einstellung die Durchlaufzeit erheblich. Da die Verbindungen jedoch auf halbem Weg über der Füllung erfolgen können, kann diese Funktion die Oberflächenqualität reduzieren."
+
+#~ msgctxt "infill_pattern description"
+#~ msgid "The pattern of the infill material of the print. The line and zig zag infill swap direction on alternate layers, reducing material cost. The grid, triangle, tri-hexagon, cubic, octet, quarter cubic, cross and concentric patterns are fully printed every layer. Cubic, quarter cubic and octet infill change with every layer to provide a more equal distribution of strength over each direction."
+#~ msgstr "Das Muster des Füllmaterials des Drucks. Die Linien- und Zickzackfüllmethode wechseln nach jeder Schicht die Richtung, um Materialkosten zu reduzieren. Die Gitter-, Dreieck- Tri-Hexagon-, Würfel-, Octahedral-, Viertelwürfel-, Quer- und konzentrischen Muster werden in jeder Schicht vollständig gedruckt. Würfel-, Viertelwürfel- und Octahedral-Füllungen wechseln mit jeder Schicht, um eine gleichmäßigere Verteilung der Stärke in allen Richtungen zu erzielen."
+
#~ msgctxt "infill_pattern option concentric_3d"
#~ msgid "Concentric 3D"
#~ msgstr "Konzentrisch 3D"
diff --git a/resources/i18n/es_ES/cura.po b/resources/i18n/es_ES/cura.po
index 1c4d985f97..834396b94c 100644
--- a/resources/i18n/es_ES/cura.po
+++ b/resources/i18n/es_ES/cura.po
@@ -1,24 +1,24 @@
# Cura
-# Copyright (C) 2018 Ultimaker
+# Copyright (C) 2019 Ultimaker B.V.
# This file is distributed under the same license as the Cura package.
-# Ruben Dulek , 2018.
+# Ruben Dulek , 2019.
#
msgid ""
msgstr ""
-"Project-Id-Version: Cura 3.5\n"
+"Project-Id-Version: Cura 4.2\n"
"Report-Msgid-Bugs-To: r.dulek@ultimaker.com\n"
-"POT-Creation-Date: 2018-09-19 17:07+0200\n"
-"PO-Revision-Date: 2018-09-28 14:55+0200\n"
-"Last-Translator: Bothof \n"
-"Language-Team: Spanish\n"
+"POT-Creation-Date: 2019-07-16 14:38+0200\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:27
msgctxt "@action"
msgid "Machine Settings"
msgstr "Ajustes de la máquina"
@@ -48,15 +48,15 @@ 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
msgctxt "@warning:status"
-msgid "Please generate G-code before saving."
-msgstr "Genere un G-code antes de guardar."
+msgid "Please prepare G-code before exporting."
+msgstr "Prepare el Gcode antes de la exportación."
-#: /home/ruben/Projects/Cura/plugins/ModelChecker/ModelChecker.py:30
+#: /home/ruben/Projects/Cura/plugins/ModelChecker/ModelChecker.py:31
msgctxt "@info:title"
msgid "3D Model Assistant"
msgstr "Asistente del modelo 3D"
-#: /home/ruben/Projects/Cura/plugins/ModelChecker/ModelChecker.py:80
+#: /home/ruben/Projects/Cura/plugins/ModelChecker/ModelChecker.py:90
#, python-brace-format
msgctxt "@info:status"
msgid ""
@@ -70,10 +70,10 @@ 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 "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"
@@ -85,37 +85,36 @@ 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:40
+#: /home/ruben/Projects/Cura/plugins/AMFReader/__init__.py:15
+msgctxt "@item:inlistbox"
+msgid "AMF File"
+msgstr "Archivo AMF"
+
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:37
msgctxt "@item:inmenu"
msgid "USB printing"
msgstr "Impresión USB"
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:41
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:38
msgctxt "@action:button Preceded by 'Ready to'."
msgid "Print via USB"
msgstr "Imprimir mediante USB"
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:42
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:39
msgctxt "@info:tooltip"
msgid "Print via USB"
msgstr "Imprimir mediante USB"
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:83
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:75
msgctxt "@info:status"
msgid "Connected via USB"
msgstr "Conectado mediante USB"
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:103
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:100
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/X3GWriter/build/GPX-prefix/src/GPX/slicerplugins/cura15.06/X3gWriter/__init__.py:16
msgctxt "X3g Writer Plugin Description"
msgid "Writes X3g to files"
@@ -126,6 +125,11 @@ msgctxt "X3g Writer File Description"
msgid "X3g File"
msgstr "Archivo X3g"
+#: /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/GCodeGzWriter/__init__.py:17
#: /home/ruben/Projects/Cura/plugins/GCodeGzReader/__init__.py:17
msgctxt "@item:inlistbox"
@@ -137,7 +141,8 @@ msgctxt "@error:not supported"
msgid "GCodeGzWriter does not support text mode."
msgstr "GCodeGzWriter no es compatible con el modo texto."
-#: /home/ruben/Projects/Cura/plugins/UFPWriter/__init__.py:38
+#: /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"
@@ -159,7 +164,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/ClusterUM3OutputDevice.py:131
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/MeshFormatHandler.py:106
msgctxt "@info:status"
msgid "There are no file formats available to write with!"
msgstr "¡No hay formatos de archivo disponibles con los que escribir!"
@@ -196,9 +201,10 @@ 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/cura/Settings/CuraContainerRegistry.py:133
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:140
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1567
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py:188
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:134
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:141
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1622
msgctxt "@info:title"
msgid "Error"
msgstr "Error"
@@ -227,8 +233,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/CuraApplication.py:1557
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1651
+#: /home/ruben/Projects/Cura/cura/OAuth2/AuthorizationService.py:197
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1612
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1712
msgctxt "@info:title"
msgid "Warning"
msgstr "Advertencia"
@@ -255,274 +262,385 @@ 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:86
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:75
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:93
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:87
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:76
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:94
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
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:95
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
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:98
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
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:100
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
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:105
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
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:108
msgctxt "@info:title"
msgid "Authentication status"
msgstr "Estado de la autenticación"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:103
-msgctxt "@info:status"
-msgid ""
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:104
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:110
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:114
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:116
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:120
msgctxt "@info:title"
msgid "Authentication Status"
msgstr "Estado de la autenticación"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:105
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:111
+#: /home/ruben/Projects/Cura/cura/OAuth2/AuthorizationService.py:198
msgctxt "@action:button"
msgid "Retry"
msgstr "Volver a intentar"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:106
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:112
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:109
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:115
msgctxt "@info:status"
msgid "Access to the printer accepted"
msgstr "Acceso a la impresora aceptado"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:113
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:119
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:115
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/UM3InfoComponents.qml:29
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/UM3InfoComponents.qml:73
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:121
+#: /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:117
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/UM3InfoComponents.qml:28
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/UM3InfoComponents.qml:72
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:123
+#: /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:202
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:208
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:204
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:210
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:210
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:232
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:216
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:238
msgctxt "@window:title"
msgid "Mismatched configuration"
msgstr "Configuración desajustada"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:224
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:230
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:226
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:232
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:253
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:197
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:259
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:176
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:181
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:260
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:216
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:232
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:266
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:194
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:211
msgctxt "@info:status"
msgid "Sending data to printer"
msgstr "Enviando datos a la impresora"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:261
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:217
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:233
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:267
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:196
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:213
msgctxt "@info:title"
msgid "Sending Data"
msgstr "Enviando datos"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:262
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:234
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxProgressButton.qml:18
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxConfirmUninstallResetDialog.qml:80
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:378
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintWindow.qml:92
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/MoreInfoWindow.qml:143
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:268
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:214
+#: /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:410
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintWindow.qml:20
+#: /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:391
-#: /home/ruben/Projects/Cura/resources/qml/OpenFilesIncludingProjectsDialog.qml:87
-#: /home/ruben/Projects/Cura/resources/qml/WorkspaceSummaryDialog.qml:279
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/OpenFilesIncludingProjectsDialog.qml:87
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:283
msgctxt "@action:button"
msgid "Cancel"
msgstr "Cancelar"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:325
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:331
#, 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:331
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:337
#, 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:354
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:360
#, 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:363
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:369
#, 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:549
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:555
msgctxt "@window:title"
msgid "Sync with your printer"
msgstr "Sincronizar con la impresora"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:551
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:557
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:553
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:559
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:89
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:96
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:310
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:289
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:370
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:312
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:291
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:371
msgctxt "@info:title"
msgid "Data Sent"
msgstr "Fecha de envío"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:313
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:292
msgctxt "@action:button"
msgid "View in Monitor"
msgstr "Ver en pantalla"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:420
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:411
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:318
#, python-brace-format
msgctxt "@info:status"
msgid "Printer '{printer_name}' has finished printing '{job_name}'."
msgstr "{printer_name} ha terminado de imprimir «{job_name}»."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:422
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:413
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:322
#, 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:423
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:414
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:316
msgctxt "@info:status"
msgid "Print finished"
msgstr "Impresión terminada"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/DiscoverUM3Action.py:26
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:595
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:629
+msgctxt "@label:material"
+msgid "Empty"
+msgstr "Vacío"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:596
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:630
+msgctxt "@label:material"
+msgid "Unknown"
+msgstr "Desconocido"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:169
+msgctxt "@action:button"
+msgid "Print via Cloud"
+msgstr "Imprimir mediante Cloud"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:170
+msgctxt "@properties:tooltip"
+msgid "Print via Cloud"
+msgstr "Imprimir mediante Cloud"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:171
+msgctxt "@info:status"
+msgid "Connected via Cloud"
+msgstr "Conectado mediante Cloud"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:182
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:359
+msgctxt "@info:title"
+msgid "Cloud error"
+msgstr "Error de Cloud"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:199
+msgctxt "@info:status"
+msgid "Could not export print job."
+msgstr "No se ha podido exportar el trabajo de impresión."
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:358
+msgctxt "@info:text"
+msgid "Could not upload the data to the printer."
+msgstr "No se han podido cargar los datos en la impresora."
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/Utils.py:51
+msgctxt "@info:status"
+msgid "tomorrow"
+msgstr "mañana"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/Utils.py:54
+msgctxt "@info:status"
+msgid "today"
+msgstr "hoy"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py:187
+msgctxt "@info:description"
+msgid "There was an error connecting to the cloud."
+msgstr "Se ha producido un error al conectarse a la nube."
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudProgressMessage.py:14
+msgctxt "@info:status"
+msgid "Sending Print Job"
+msgstr "Enviando trabajo de impresión"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudProgressMessage.py:15
+msgctxt "@info:status"
+msgid "Uploading via Ultimaker Cloud"
+msgstr "Cargando a través de Ultimaker Cloud"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py:621
+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/UM3OutputDevicePlugin.py:627
+msgctxt "@info:status Ultimaker Cloud is a brand name and shouldn't be translated."
+msgid "Connect to Ultimaker Cloud"
+msgstr "Conectar a Ultimaker Cloud"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py:628
+msgctxt "@action"
+msgid "Don't ask me again for this printer."
+msgstr "No volver a preguntarme para esta impresora."
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py:631
+msgctxt "@action"
+msgid "Get started"
+msgstr "Empezar"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py:637
+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."
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py:643
+msgctxt "@info:status"
+msgid "Connected!"
+msgstr "¡Conectado!"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py:645
+msgctxt "@action"
+msgid "Review your connection"
+msgstr "Revise su conexión"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/DiscoverUM3Action.py:30
msgctxt "@action"
msgid "Connect via Network"
msgstr "Conectar a través de la red"
-#: /home/ruben/Projects/Cura/plugins/MonitorStage/__init__.py:12
+#: /home/ruben/Projects/Cura/plugins/MonitorStage/__init__.py:14
msgctxt "@item:inmenu"
msgid "Monitor"
msgstr "Supervisar"
-#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py:68
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py:118
+msgctxt "@info"
+msgid "Could not access update information."
+msgstr "No se pudo acceder a la información actualizada."
+
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerMessage.py:17
#, python-brace-format
msgctxt "@info Don't translate {machine_name}, since it gets replaced by a printer name!"
msgid "New features are available for your {machine_name}! It is recommended to update the firmware on your printer."
msgstr "Hay nuevas funciones disponibles para {machine_name}. Se recomienda actualizar el firmware de la impresora."
-#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py:72
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerMessage.py:21
#, python-format
msgctxt "@info:title The %s gets replaced with the printer name."
msgid "New %s firmware available"
msgstr "Nuevo firmware de %s disponible"
-#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py:75
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerMessage.py:27
msgctxt "@action:button"
msgid "How to update"
msgstr "Cómo actualizar"
-#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py:91
-msgctxt "@info"
-msgid "Could not access update information."
-msgstr "No se pudo acceder a la información actualizada."
-
-#: /home/ruben/Projects/Cura/plugins/SimulationView/__init__.py:14
+#: /home/ruben/Projects/Cura/plugins/SimulationView/__init__.py:15
msgctxt "@item:inlistbox"
msgid "Layer view"
msgstr "Vista de capas"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.py:102
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.py:114
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:103
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.py:115
msgctxt "@info:title"
msgid "Simulation View"
msgstr "Vista de simulación"
-#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.py:28
+#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.py:35
+msgctxt "@item:inmenu"
+msgid "Post Processing"
+msgstr "Posprocesamiento"
+
+#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.py:36
+msgctxt "@item:inmenu"
msgid "Modify G-Code"
msgstr "Modificar GCode"
@@ -536,36 +654,6 @@ 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:43
-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:46
-msgctxt "@info:title"
-msgid "Collecting Data"
-msgstr "Recopilando datos"
-
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/SliceInfo.py:48
-msgctxt "@action:button"
-msgid "More info"
-msgstr "Más información"
-
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/SliceInfo.py:49
-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:51
-msgctxt "@action:button"
-msgid "Allow"
-msgstr "Permitir"
-
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/SliceInfo.py:52
-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"
@@ -596,56 +684,56 @@ msgctxt "@item:inlistbox"
msgid "GIF Image"
msgstr "Imagen GIF"
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:333
+#: /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:333
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:364
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:388
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:397
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:406
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:415
+#: /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:363
+#: /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:387
+#: /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:396
+#: /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:405
+#: /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:414
+#: /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. Please scale or rotate models to fit."
-msgstr "No hay nada que segmentar porque ninguno de los modelos se adapta al volumen de impresión. Escale o rote los modelos para que se adapten."
+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 "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:49
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py:242
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py:50
+#: /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:242
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py:256
msgctxt "@info:title"
msgid "Information"
msgstr "Información"
@@ -661,13 +749,11 @@ msgid "Configure Per Model Settings"
msgstr "Configurar ajustes por modelo"
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.py:175
-#: /home/ruben/Projects/Cura/resources/qml/PrepareSidebar.qml:576
msgctxt "@title:tab"
msgid "Recommended"
msgstr "Recomendado"
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.py:177
-#: /home/ruben/Projects/Cura/resources/qml/PrepareSidebar.qml:581
msgctxt "@title:tab"
msgid "Custom"
msgstr "Personalizado"
@@ -678,19 +764,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:711
+#: /home/ruben/Projects/Cura/plugins/3MFReader/ThreeMFWorkspaceReader.py:191
+#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:775
msgctxt "@label"
msgid "Nozzle"
msgstr "Tobera"
-#: /home/ruben/Projects/Cura/plugins/3MFReader/ThreeMFWorkspaceReader.py:468
+#: /home/ruben/Projects/Cura/plugins/3MFReader/ThreeMFWorkspaceReader.py:474
#, 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:471
+#: /home/ruben/Projects/Cura/plugins/3MFReader/ThreeMFWorkspaceReader.py:477
msgctxt "@info:title"
msgid "Open Project File"
msgstr "Abrir archivo de proyecto"
@@ -705,22 +791,65 @@ msgctxt "@item:inlistbox"
msgid "G File"
msgstr "Archivo G"
-#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:317
+#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:328
msgctxt "@info:status"
msgid "Parsing G-code"
msgstr "Analizar GCode"
-#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:319
-#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:466
+#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:330
+#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:483
msgctxt "@info:title"
msgid "G-code Details"
msgstr "Datos de GCode"
-#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:464
+#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:481
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."
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/DrivePluginExtension.py:64
+msgctxt "@item:inmenu"
+msgid "Manage backups"
+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
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/DriveApiService.py:55
+#: /home/ruben/Projects/Cura/cura/Backups/Backup.py:104
+msgctxt "@info:title"
+msgid "Backup"
+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 "Se ha producido un error al obtener sus copias de seguridad."
+
+#: /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 "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 "Copias de seguridad"
+
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/UploadBackupJob.py:27
+msgctxt "@info:backup_status"
+msgid "Uploading your backup..."
+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 "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 "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
msgctxt "@item:inlistbox"
@@ -732,7 +861,7 @@ msgctxt "@item:inmenu"
msgid "Profile Assistant"
msgstr "Asistente del perfil"
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/__init__.py:17
+#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/__init__.py:18
msgctxt "@item:inlistbox"
msgid "Profile Assistant"
msgstr "Asistente del perfil"
@@ -752,231 +881,266 @@ msgctxt "@error:zip"
msgid "Error writing 3mf file."
msgstr "Error al escribir el archivo 3MF."
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UM2UpgradeSelection.py:17
+#: /home/ruben/Projects/Cura/plugins/PreviewStage/__init__.py:13
+msgctxt "@item:inmenu"
+msgid "Preview"
+msgstr "Vista previa"
+
+#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UM2UpgradeSelection.py:19
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOUpgradeSelection.py:18
msgctxt "@action"
msgid "Select upgrades"
msgstr "Seleccionar actualizaciones"
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UpgradeFirmwareMachineAction.py:12
-msgctxt "@action"
-msgid "Upgrade Firmware"
-msgstr "Actualizar firmware"
-
-#: /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:98
-msgctxt "@tooltip"
-msgid "Outer Wall"
-msgstr "Pared exterior"
+#: /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/PrintInformation.py:99
-msgctxt "@tooltip"
-msgid "Inner Walls"
-msgstr "Paredes interiores"
+#: /home/ruben/Projects/Cura/cura/Settings/cura_empty_instance_containers.py:33
+msgctxt "@info:not supported profile"
+msgid "Not supported"
+msgstr "No compatible"
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:100
-msgctxt "@tooltip"
-msgid "Skin"
-msgstr "Forro"
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:101
-msgctxt "@tooltip"
-msgid "Infill"
-msgstr "Relleno"
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:102
-msgctxt "@tooltip"
-msgid "Support Infill"
-msgstr "Relleno de soporte"
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:103
-msgctxt "@tooltip"
-msgid "Support Interface"
-msgstr "Interfaz de soporte"
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:104
-msgctxt "@tooltip"
-msgid "Support"
-msgstr "Soporte"
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:105
-msgctxt "@tooltip"
-msgid "Skirt"
-msgstr "Falda"
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:106
-msgctxt "@tooltip"
-msgid "Travel"
-msgstr "Desplazamiento"
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:107
-msgctxt "@tooltip"
-msgid "Retractions"
-msgstr "Retracciones"
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:108
-msgctxt "@tooltip"
-msgid "Other"
-msgstr "Otro"
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:229
-msgctxt "@label unknown material"
-msgid "Unknown"
-msgstr "Desconocido"
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:314
-#, python-brace-format
-msgctxt "@label"
-msgid "Pre-sliced file {0}"
-msgstr "Archivo {0} presegmentado"
-
-#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:186
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:121
+#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:203
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:122
msgctxt "@title:window"
msgid "File Already Exists"
msgstr "El archivo ya existe"
-#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:187
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:122
+#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:204
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:123
#, 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/ExtrudersModel.py:212
-msgctxt "@menuitem"
-msgid "Not overridden"
-msgstr "No reemplazado"
-
-#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:120
+#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:427
+#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:430
msgctxt "@info:status"
-msgid "The selected material is incompatible with the selected machine or configuration."
-msgstr "El material seleccionado no es compatible con la máquina o la configuración seleccionada."
+msgid "Invalid file URL:"
+msgstr "URL del archivo no válida:"
-#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:121
-msgctxt "@info:title"
-msgid "Incompatible Material"
-msgstr "Material incompatible"
+#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:925
+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:863
-#, 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:865
+#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:927
msgctxt "@info:title"
msgid "Settings updated"
msgstr "Ajustes actualizados"
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:131
+#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:1481
+msgctxt "@info:title"
+msgid "Extruder(s) Disabled"
+msgstr "Extrusores deshabilitados"
+
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:132
#, 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:139
#, 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:144
#, 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:145
msgctxt "@info:title"
msgid "Export succeeded"
msgstr "Exportación correcta"
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:170
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:194
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:313
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:172
#, python-brace-format
-msgctxt "@info:status Don't translate the XML tags or !"
-msgid "Failed to import profile from {0}: {1}"
-msgstr "Error al importar el perfil de {0}: {1}"
+msgctxt "@info:status Don't translate the XML tags !"
+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:176
#, python-brace-format
-msgctxt "@info:status Don't translate the XML tags or !"
+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:192
+#, 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 que 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:218
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:228
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:196
#, python-brace-format
-msgctxt "@info:status Don't translate the XML tags or !"
+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:220
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:230
+#, 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:243
#, python-brace-format
-msgctxt "@info:status Don't translate the XML tags or !"
+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:316
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:315
+#, python-brace-format
+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}:"
+
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:318
#, 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:321
#, 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:324
#, 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:359
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:375
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:389
#, 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:59
+#: /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:306
+#, python-brace-format
+msgctxt "@label"
+msgid "Pre-sliced file {0}"
+msgstr "Archivo {0} presegmentado"
+
+#: /home/ruben/Projects/Cura/cura/UI/WelcomePagesModel.py:56
+#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/ProfileCreatorTabControls.qml:62
+msgctxt "@action:button"
+msgid "Next"
+msgstr "Siguiente"
+
+#: /home/ruben/Projects/Cura/cura/UI/ObjectsModel.py:61
#, 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/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:124
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:168
+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:91
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:48
+msgctxt "@action:button"
+msgid "Add"
+msgstr "Agregar"
+
+#: /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:109
#, python-brace-format
@@ -989,45 +1153,79 @@ msgctxt "@item:inlistbox"
msgid "All Files (*)"
msgstr "Todos los archivos (*)"
-#: /home/ruben/Projects/Cura/cura/Machines/MaterialManager.py:609
+#: /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
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:269
+msgctxt "@label"
+msgid "Unknown"
+msgstr "Desconocido"
+
+#: /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/Machines/MaterialManager.py:689
msgctxt "@label"
msgid "Custom Material"
msgstr "Material personalizado"
-#: /home/ruben/Projects/Cura/cura/Machines/MaterialManager.py:610
+#: /home/ruben/Projects/Cura/cura/Machines/MaterialManager.py:690
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/ConfigurationMenu.qml:203
msgctxt "@label"
msgid "Custom"
msgstr "Personalizado"
-#: /home/ruben/Projects/Cura/cura/BuildVolume.py:81
+#: /home/ruben/Projects/Cura/cura/BuildVolume.py:89
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:91
msgctxt "@info:title"
msgid "Build Volume"
msgstr "Volumen de impresión"
-#: /home/ruben/Projects/Cura/cura/Backups/Backup.py:97
+#: /home/ruben/Projects/Cura/cura/Backups/Backup.py:99
msgctxt "@info:backup_failed"
msgid "Could not create archive from user data directory: {}"
msgstr "No se ha podido crear el archivo desde el directorio de datos de usuario: {}"
-#: /home/ruben/Projects/Cura/cura/Backups/Backup.py:102
-msgctxt "@info:title"
-msgid "Backup"
-msgstr "Copia de seguridad"
-
-#: /home/ruben/Projects/Cura/cura/Backups/Backup.py:112
+#: /home/ruben/Projects/Cura/cura/Backups/Backup.py:114
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:122
+#: /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/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:197
+msgctxt "@info"
+msgid "Unable to reach the Ultimaker account server."
+msgstr "No se puede acceder al servidor de cuentas de Ultimaker."
+
+#: /home/ruben/Projects/Cura/cura/OAuth2/AuthorizationRequestHandler.py:66
+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:73
+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:27
msgctxt "@info:status"
@@ -1035,42 +1233,46 @@ msgid "Multiplying and placing objects"
msgstr "Multiplicar y colocar objetos"
#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:28
+msgctxt "@info:title"
+msgid "Placing Objects"
+msgstr "Colocando objetos"
+
+#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:100
+#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsJob.py:103
+#: /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
msgctxt "@info:title"
msgid "Placing Object"
msgstr "Colocando objeto"
-#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:100
-#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsJob.py:96
-#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsAllBuildPlatesJob.py:150
-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/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:97
-#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsAllBuildPlatesJob.py:151
+#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsJob.py:104
+#: /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"
-#: /home/ruben/Projects/Cura/cura/CrashHandler.py:87
+#: /home/ruben/Projects/Cura/cura/CrashHandler.py:83
msgctxt "@title:window"
msgid "Cura can't start"
msgstr "Cura no puede iniciarse"
-#: /home/ruben/Projects/Cura/cura/CrashHandler.py:93
+#: /home/ruben/Projects/Cura/cura/CrashHandler.py:89
msgctxt "@label crash message"
msgid ""
"
Oops, Ultimaker Cura has encountered something that doesn't seem right.
\n"
@@ -1085,32 +1287,32 @@ msgstr ""
"
Envíenos el informe de errores para que podamos solucionar el problema.
"
-#: /home/ruben/Projects/Cura/cura/CrashHandler.py:222
+#: /home/ruben/Projects/Cura/cura/CrashHandler.py:218
msgctxt "@title:groupbox"
msgid "Error traceback"
msgstr "Rastreabilidad de errores"
-#: /home/ruben/Projects/Cura/cura/CrashHandler.py:303
+#: /home/ruben/Projects/Cura/cura/CrashHandler.py:299
msgctxt "@title:groupbox"
msgid "Logs"
msgstr "Registros"
-#: /home/ruben/Projects/Cura/cura/CrashHandler.py:326
+#: /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:345
+#: /home/ruben/Projects/Cura/cura/CrashHandler.py:342
msgctxt "@action:button"
msgid "Send report"
msgstr "Enviar informe"
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:454
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:504
msgctxt "@info:progress"
msgid "Loading machines..."
msgstr "Cargando máquinas..."
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:748
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:819
msgctxt "@info:progress"
msgid "Setting up scene..."
msgstr "Configurando escena..."
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:784
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:854
msgctxt "@info:progress"
msgid "Loading interface..."
msgstr "Cargando interfaz..."
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:997
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1133
#, 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:1556
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1611
#, 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:1566
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1621
#, 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:1650
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1711
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:61
-msgctxt "@title"
-msgid "Machine Settings"
-msgstr "Ajustes de la máquina"
-
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:80
-msgctxt "@title:tab"
-msgid "Printer"
-msgstr "Impresora"
-
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:99
-msgctxt "@label"
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:58
+msgctxt "@title:label"
msgid "Printer Settings"
msgstr "Ajustes de la impresora"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:110
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:72
msgctxt "@label"
msgid "X (Width)"
msgstr "X (anchura)"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:111
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:121
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:131
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:237
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:386
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:402
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:420
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:432
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:857
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:76
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:90
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:104
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:194
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:213
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:232
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:253
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:272
+#: /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:120
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:86
msgctxt "@label"
msgid "Y (Depth)"
msgstr "Y (profundidad)"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:130
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:100
msgctxt "@label"
msgid "Z (Height)"
msgstr "Z (altura)"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:142
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:114
msgctxt "@label"
msgid "Build plate shape"
msgstr "Forma de la placa de impresión"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:151
-msgctxt "@option:check"
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:127
+msgctxt "@label"
msgid "Origin at center"
msgstr "Origen en el centro"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:159
-msgctxt "@option:check"
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:139
+msgctxt "@label"
msgid "Heated bed"
-msgstr "Plataforma caliente"
+msgstr "Plataforma calentada"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:170
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:151
msgctxt "@label"
msgid "G-code flavor"
msgstr "Tipo de GCode"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:183
-msgctxt "@label"
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:176
+msgctxt "@title:label"
msgid "Printhead Settings"
msgstr "Ajustes del cabezal de impresión"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:193
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:190
msgctxt "@label"
msgid "X min"
msgstr "X mín."
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:194
-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:203
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:209
msgctxt "@label"
msgid "Y min"
msgstr "Y mín."
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:204
-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:213
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:228
msgctxt "@label"
msgid "X max"
msgstr "X máx."
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:214
-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:223
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:249
msgctxt "@label"
msgid "Y max"
msgstr "Y máx."
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:224
-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:236
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:268
msgctxt "@label"
-msgid "Gantry height"
-msgstr "Altura del caballete"
+msgid "Gantry Height"
+msgstr "Altura del puente"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:238
-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:257
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:282
msgctxt "@label"
msgid "Number of Extruders"
msgstr "Número de extrusores"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:313
-msgctxt "@label"
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:341
+msgctxt "@title:label"
msgid "Start G-code"
msgstr "Iniciar GCode"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:323
-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:332
-msgctxt "@label"
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:355
+msgctxt "@title:label"
msgid "End G-code"
msgstr "Finalizar GCode"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:342
-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:373
-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:385
+#: /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:401
+#: /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:403
-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:419
+#: /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:431
+#: /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/MachineSettingsExtruderTab.qml:162
+msgctxt "@title:label"
msgid "Extruder Start G-code"
msgstr "GCode inicial del extrusor"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:470
-msgctxt "@label"
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsExtruderTab.qml:176
+msgctxt "@title:label"
msgid "Extruder End G-code"
msgstr "GCode final del extrusor"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxProgressButton.qml:17
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxProgressButton.qml:18
msgctxt "@action:button"
msgid "Install"
msgstr "Instalar"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxProgressButton.qml:19
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxProgressButton.qml:20
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailTileActions.qml:46
msgctxt "@action:button"
msgid "Installed"
msgstr "Instalado"
@@ -1435,68 +1601,82 @@ msgctxt "@info"
msgid "Could not connect to the Cura Package database. Please check your connection."
msgstr "No se ha podido conectar con la base de datos del Paquete Cura. Compruebe la conexión."
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/SmallRatingWidget.qml:27
+msgctxt "@label"
+msgid "ratings"
+msgstr "calificaciones"
+
#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledPage.qml:38
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxHeader.qml:26
+#: /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:75
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:66
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:544
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledPage.qml:70
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxHeader.qml:44
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:80
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:417
msgctxt "@title:tab"
msgid "Materials"
msgstr "Materiales"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml:80
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml:91
+msgctxt "@label"
+msgid "Your rating"
+msgstr "Su calificación"
+
+#: /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:86
+#: /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:92
+#: /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:98
+#: /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:117
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml:159
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:255
-msgctxt "@label"
-msgid "Unknown"
-msgstr "Desconocido"
+#: /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 "Inicie sesión para realizar la instalación o la actualización"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailTileActions.qml:44
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml:30
+#: /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:45
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml:31
+#: /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:46
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml:32
+#: /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"
msgstr "Actualizado"
#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/Toolbox.qml:13
msgctxt "@title"
-msgid "Toolbox"
-msgstr "Cuadro de herramientas"
+msgid "Marketplace"
+msgstr "Marketplace"
#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxBackColumn.qml:25
msgctxt "@action:button"
@@ -1505,8 +1685,8 @@ msgstr "Atrás"
#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxConfirmUninstallResetDialog.qml:20
msgctxt "@title:window"
-msgid "Confirm uninstall "
-msgstr "Confirmar desinstalación "
+msgid "Confirm uninstall"
+msgstr "Confirmar desinstalación"
#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxConfirmUninstallResetDialog.qml:50
msgctxt "@text:window"
@@ -1523,17 +1703,27 @@ msgctxt "@text:window"
msgid "Profiles"
msgstr "Perfiles"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxConfirmUninstallResetDialog.qml:89
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxConfirmUninstallResetDialog.qml:90
msgctxt "@action:button"
msgid "Confirm"
msgstr "Confirmar"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxFooter.qml:17
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/RatingWidget.qml:54
+msgctxt "@label"
+msgid "You need to login first before you can rate"
+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 "Debe instalar el paquete antes de enviar sus calificaciones"
+
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxFooter.qml:19
msgctxt "@info"
msgid "You will need to restart Cura before changes in packages have effect."
msgstr "Tendrá que reiniciar Cura para que los cambios de los paquetes surtan efecto."
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxFooter.qml:34
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxFooter.qml:45
msgctxt "@info:button"
msgid "Quit Cura"
msgstr "Salir de Cura"
@@ -1553,22 +1743,27 @@ msgctxt "@label"
msgid "Generic Materials"
msgstr "Materiales genéricos"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxHeader.qml:54
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxHeader.qml:59
msgctxt "@title:tab"
msgid "Installed"
msgstr "Instalado"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml:19
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml:22
msgctxt "@label"
msgid "Will install upon restarting"
msgstr "Se instalará después de reiniciar"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml:51
+#: /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 "Inicie sesión para realizar la actualización"
+
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml:71
msgctxt "@action:button"
msgid "Downgrade"
msgstr "Degradar"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml:51
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml:71
msgctxt "@action:button"
msgid "Uninstall"
msgstr "Desinstalar"
@@ -1589,12 +1784,12 @@ msgstr ""
"Debe aceptar dicha licencia para instalar el complemento.\n"
"¿Acepta las condiciones que aparecen a continuación?"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxLicenseDialog.qml:54
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxLicenseDialog.qml:55
msgctxt "@action:button"
msgid "Accept"
msgstr "Aceptar"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxLicenseDialog.qml:65
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxLicenseDialog.qml:66
msgctxt "@action:button"
msgid "Decline"
msgstr "Rechazar"
@@ -1604,22 +1799,42 @@ msgctxt "@label"
msgid "Featured"
msgstr "Destacado"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:31
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:66
msgctxt "@label"
msgid "Compatibility"
msgstr "Compatibilidad"
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:203
+msgctxt "@action:label"
+msgid "Technical Data Sheet"
+msgstr "Especificaciones técnicas"
+
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:212
+msgctxt "@action:label"
+msgid "Safety Data Sheet"
+msgstr "Especificaciones de seguridad"
+
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:221
+msgctxt "@action:label"
+msgid "Printing Guidelines"
+msgstr "Directrices de impresión"
+
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:230
+msgctxt "@action:label"
+msgid "Website"
+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:88
+#: /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:94
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxAuthorPage.qml:98
msgctxt "@label"
msgid "Email"
msgstr "Correo electrónico"
@@ -1627,424 +1842,595 @@ 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."
+msgstr "Algunos elementos pueden causar problemas durante la impresión. Haga clic para ver consejos sobre cómo ajustarlos."
-#: /home/ruben/Projects/Cura/plugins/ChangeLogPlugin/ChangeLog.qml:18
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:31
+msgctxt "@title"
+msgid "Update Firmware"
+msgstr "Actualizar firmware"
+
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:39
msgctxt "@label"
-msgid "Changelog"
-msgstr "Registro de cambios"
+msgid "Firmware is the piece of software running directly on your 3D printer. This firmware controls the step motors, regulates the temperature and ultimately makes your printer work."
+msgstr "El firmware es la parte del software que se ejecuta directamente en la impresora 3D. Este firmware controla los motores de pasos, regula la temperatura y, finalmente, hace que funcione la impresora."
-#: /home/ruben/Projects/Cura/plugins/ChangeLogPlugin/ChangeLog.qml:37
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/FirmwareUpdateWindow.qml:84
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/UM3InfoComponents.qml:56
-#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.qml:464
-#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:508
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:121
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:148
-#: /home/ruben/Projects/Cura/resources/qml/EngineLog.qml:38
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:46
+msgctxt "@label"
+msgid "The firmware shipping with new printers works, but new versions tend to have more features and improvements."
+msgstr "El firmware que se envía con las nuevas impresoras funciona, pero las nuevas versiones suelen tener más funciones y mejoras."
+
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:58
msgctxt "@action:button"
-msgid "Close"
-msgstr "Cerrar"
+msgid "Automatically upgrade Firmware"
+msgstr "Actualización de firmware automática"
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/FirmwareUpdateWindow.qml:22
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:69
+msgctxt "@action:button"
+msgid "Upload custom Firmware"
+msgstr "Cargar firmware personalizado"
+
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:83
+msgctxt "@label"
+msgid "Firmware can not be updated because there is no connection with the printer."
+msgstr "No se puede actualizar el firmware porque no hay conexión con la impresora."
+
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:91
+msgctxt "@label"
+msgid "Firmware can not be updated because the connection with the printer does not support upgrading firmware."
+msgstr "No se puede actualizar el firmware porque la conexión con la impresora no permite actualizaciones de firmware."
+
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:98
+msgctxt "@title:window"
+msgid "Select custom firmware"
+msgstr "Seleccionar firmware personalizado"
+
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:119
msgctxt "@title:window"
msgid "Firmware Update"
msgstr "Actualización del firmware"
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/FirmwareUpdateWindow.qml:42
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:143
msgctxt "@label"
msgid "Updating firmware."
msgstr "Actualización del firmware."
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/FirmwareUpdateWindow.qml:44
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:145
msgctxt "@label"
msgid "Firmware update completed."
msgstr "Actualización del firmware completada."
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/FirmwareUpdateWindow.qml:46
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:147
msgctxt "@label"
msgid "Firmware update failed due to an unknown error."
msgstr "Se ha producido un error al actualizar el firmware debido a un error desconocido."
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/FirmwareUpdateWindow.qml:48
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:149
msgctxt "@label"
msgid "Firmware update failed due to an communication error."
msgstr "Se ha producido un error al actualizar el firmware debido a un error de comunicación."
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/FirmwareUpdateWindow.qml:50
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:151
msgctxt "@label"
msgid "Firmware update failed due to an input/output error."
msgstr "Se ha producido un error al actualizar el firmware debido a un error de entrada/salida."
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/FirmwareUpdateWindow.qml:52
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:153
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:144
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobCard.qml:181
+#: /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/DiscoverUM3Action.qml:43
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:208
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobCard.qml:249
+msgctxt "@info"
+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
+msgctxt "@info"
+msgid "The webcam is not available because you are monitoring a cloud printer."
+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:300
+msgctxt "@label:status"
+msgid "Loading..."
+msgstr "Cargando..."
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:304
+msgctxt "@label:status"
+msgid "Unavailable"
+msgstr "No disponible"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:308
+msgctxt "@label:status"
+msgid "Unreachable"
+msgstr "No se puede conectar"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:312
+msgctxt "@label:status"
+msgid "Idle"
+msgstr "Sin actividad"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:353
+msgctxt "@label"
+msgid "Untitled"
+msgstr "Sin título"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:374
+msgctxt "@label"
+msgid "Anonymous"
+msgstr "Anónimo"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:401
+msgctxt "@label:status"
+msgid "Requires configuration changes"
+msgstr "Debe cambiar la configuración"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:439
+msgctxt "@action:button"
+msgid "Details"
+msgstr "Detalles"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobCard.qml:130
+msgctxt "@label"
+msgid "Unavailable printer"
+msgstr "Impresora no disponible"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobCard.qml:132
+msgctxt "@label"
+msgid "First available"
+msgstr "Primera disponible"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml:31
+msgctxt "@label"
+msgid "Queued"
+msgstr "En cola"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml:67
+msgctxt "@label link to connect manager"
+msgid "Manage in browser"
+msgstr "Gestionar en el navegador"
+
+#: /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:116
+msgctxt "@label"
+msgid "Print jobs"
+msgstr "Trabajos de impresión"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml:132
+msgctxt "@label"
+msgid "Total print time"
+msgstr "Tiempo de impresión total"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml:148
+msgctxt "@label"
+msgid "Waiting for"
+msgstr "Esperando"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:50
msgctxt "@window:title"
msgid "Existing Connection"
msgstr "Conexión existente"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:45
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:52
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:62
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:69
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:72
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:81
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:82
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:42
-msgctxt "@action:button"
-msgid "Add"
-msgstr "Agregar"
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:81
+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:92
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:101
msgctxt "@action:button"
msgid "Edit"
msgstr "Editar"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:103
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:128
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:48
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:117
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:112
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:146
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:55
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:121
msgctxt "@action:button"
msgid "Remove"
msgstr "Eliminar"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:111
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:120
msgctxt "@action:button"
msgid "Refresh"
msgstr "Actualizar"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:204
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:215
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:231
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:244
+#: /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:268
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:283
+#: /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:280
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:297
+#: /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:302
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:321
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:306
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:325
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:316
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:336
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:321
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/UM3InfoComponents.qml:39
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:341
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/UM3InfoComponents.qml:74
msgctxt "@action:button"
msgid "Connect"
msgstr "Conectar"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:335
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:354
+msgctxt "@title:window"
+msgid "Invalid IP address"
+msgstr "Dirección IP no válida"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:355
+#: /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:366
msgctxt "@title:window"
msgid "Printer Address"
msgstr "Dirección de la impresora"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:358
-msgctxt "@alabel"
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:389
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddPrinterByIpContent.qml:102
+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 red."
+msgstr "Introduzca la dirección IP o el nombre de host de la impresora en la red."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:387
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/MoreInfoWindow.qml:132
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:419
+#: /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/PrintWindow.qml:34
-msgctxt "@title:window"
-msgid "Print over network"
-msgstr "Imprimir a través de la red"
+#: /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/PrintWindow.qml:65
-msgctxt "@label"
-msgid "Printer selection"
-msgstr "Selección de la impresora"
+#: /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/PrintWindow.qml:105
+#: /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 "Preparando..."
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:88
+msgctxt "@label:status"
+msgid "Aborting..."
+msgstr "Cancelando..."
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:92
+msgctxt "@label:status"
+msgid "Pausing..."
+msgstr "Pausando..."
+
+#: /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:96
+msgctxt "@label:status"
+msgid "Resuming..."
+msgstr "Reanudando..."
+
+#: /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:100
+msgctxt "@label:status"
+msgid "Finishes %1 at %2"
+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/PrintJobInfoBlock.qml:142
-msgctxt "@label"
-msgid "Waiting for: Unavailable printer"
-msgstr "Esperando: impresora no disponible"
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintWindow.qml:47
+msgctxt "@title:window"
+msgid "Print over network"
+msgstr "Imprimir a través de la red"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintJobInfoBlock.qml:144
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintWindow.qml:79
msgctxt "@label"
-msgid "Waiting for: First available"
-msgstr "Esperando: primera disponible"
+msgid "Printer selection"
+msgstr "Selección de la impresora"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintJobInfoBlock.qml:148
-msgctxt "@label"
-msgid "Waiting for: "
-msgstr "Esperando: "
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintJobInfoBlock.qml:213
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:54
msgctxt "@label"
msgid "Move to top"
msgstr "Mover al principio"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintJobInfoBlock.qml:234
-msgctxt "@window:title"
-msgid "Move print job to top"
-msgstr "Mover trabajo de impresión al principio"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintJobInfoBlock.qml:236
-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 "¿Seguro que desea mover %1 al principio de la cola?"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintJobInfoBlock.qml:245
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:70
msgctxt "@label"
msgid "Delete"
msgstr "Borrar"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintJobInfoBlock.qml:264
-msgctxt "@window:title"
-msgid "Delete print job"
-msgstr "Borrar trabajo de impresión"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintJobInfoBlock.qml:266
-msgctxt "@label %1 is the name of a print job."
-msgid "Are you sure you want to delete %1?"
-msgstr "¿Seguro que desea borrar %1?"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/ClusterMonitorItem.qml:32
-msgctxt "@label link to connect manager"
-msgid "Manage queue"
-msgstr "Administrar cola"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/ClusterMonitorItem.qml:54
-msgctxt "@label"
-msgid "Queued"
-msgstr "En cola"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/ClusterControlItem.qml:44
-msgctxt "@label"
-msgid "Printing"
-msgstr "Imprimiendo"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/ClusterControlItem.qml:54
-msgctxt "@label link to connect manager"
-msgid "Manage printers"
-msgstr "Administrar impresoras"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/ClusterControlItem.qml:212
-msgctxt "@label"
-msgid "Not available"
-msgstr "No disponible"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/ClusterControlItem.qml:215
-msgctxt "@label"
-msgid "Unreachable"
-msgstr "No se puede conectar"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/ClusterControlItem.qml:221
-msgctxt "@label"
-msgid "Available"
-msgstr "Disponible"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/ClusterControlItem.qml:416
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:100
#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:289
msgctxt "@label"
msgid "Resume"
msgstr "Reanudar"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/ClusterControlItem.qml:416
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:102
+msgctxt "@label"
+msgid "Pausing..."
+msgstr "Pausando..."
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:104
+msgctxt "@label"
+msgid "Resuming..."
+msgstr "Reanudando..."
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:106
#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:284
#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:293
msgctxt "@label"
msgid "Pause"
msgstr "Pausar"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/ClusterControlItem.qml:444
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:124
+msgctxt "@label"
+msgid "Aborting..."
+msgstr "Cancelando..."
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:124
msgctxt "@label"
msgid "Abort"
msgstr "Cancelar"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/ClusterControlItem.qml:464
+#: /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 "¿Seguro que desea mover %1 al principio de la cola?"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:144
+msgctxt "@window:title"
+msgid "Move print job to top"
+msgstr "Mover trabajo de impresión al principio"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:153
+msgctxt "@label %1 is the name of a print job."
+msgid "Are you sure you want to delete %1?"
+msgstr "¿Seguro que desea borrar %1?"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:154
+msgctxt "@window:title"
+msgid "Delete print job"
+msgstr "Borrar trabajo de impresión"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:163
+msgctxt "@label %1 is the name of a print job."
+msgid "Are you sure you want to abort %1?"
+msgstr "¿Seguro que desea cancelar %1?"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:164
#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:335
msgctxt "@window:title"
msgid "Abort print"
msgstr "Cancela la impresión"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/ClusterControlItem.qml:466
-msgctxt "@label %1 is the name of a print job."
-msgid "Are you sure you want to abort %1?"
-msgstr "¿Seguro que desea cancelar %1?"
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:20
+msgctxt "@title:window"
+msgid "Configuration Changes"
+msgstr "Cambios de configuración"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/ClusterControlItem.qml:665
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/ClusterControlItem.qml:673
-msgctxt "@label:status"
-msgid "Aborted"
-msgstr "Cancelado"
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:27
+msgctxt "@action:button"
+msgid "Override"
+msgstr "Anular"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/ClusterControlItem.qml:667
-msgctxt "@label:status"
-msgid "Finished"
-msgstr "Terminado"
+#: /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] "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/ClusterControlItem.qml:670
-msgctxt "@label:status"
-msgid "Preparing"
-msgstr "Preparando"
+#: /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."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/ClusterControlItem.qml:675
-msgctxt "@label:status"
-msgid "Pausing"
-msgstr "Pausando"
+#: /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/ClusterControlItem.qml:677
-msgctxt "@label:status"
-msgid "Paused"
-msgstr "En pausa"
+#: /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/ClusterControlItem.qml:679
-msgctxt "@label:status"
-msgid "Resuming"
-msgstr "Reanudando"
+#: /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/ClusterControlItem.qml:681
-msgctxt "@label:status"
-msgid "Action required"
-msgstr "Acción requerida"
+#: /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/UM3InfoComponents.qml:38
+#: /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 "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: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/UM3NetworkPrinting/resources/qml/UM3InfoComponents.qml:117
-msgctxt "@info:tooltip"
-msgid "Load the configuration of the printer into Cura"
-msgstr "Carga la configuración de la impresora en Cura"
+#: /home/ruben/Projects/Cura/plugins/SettingsGuide/resources/qml/SettingsGuide.qml:16
+msgctxt "@title"
+msgid "Cura Settings Guide"
+msgstr "Guía de ajustes de Cura"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/UM3InfoComponents.qml:118
-msgctxt "@action:button"
-msgid "Activate Configuration"
-msgstr "Activar configuración"
+#: /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.\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/SimulationView/SimulationView.qml:130
+#: /home/ruben/Projects/Cura/plugins/MonitorStage/MonitorMain.qml:117
+msgctxt "@info"
+msgid "Please connect your printer to the network."
+msgstr "Conecte su impresora a la red."
+
+#: /home/ruben/Projects/Cura/plugins/MonitorStage/MonitorMain.qml:156
+msgctxt "@label link to technical assistance"
+msgid "View user manuals online"
+msgstr "Ver manuales de usuario en línea"
+
+#: /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/SimulationView.qml:145
+#: /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/SimulationView.qml:149
+#: /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/SimulationView.qml:153
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:115
msgctxt "@label:listbox"
msgid "Feedrate"
msgstr "Velocidad"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:157
+#: /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/SimulationView.qml:198
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:156
msgctxt "@label"
msgid "Compatibility Mode"
msgstr "Modo de compatibilidad"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:284
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:230
msgctxt "@label"
-msgid "Show Travels"
-msgstr "Mostrar desplazamientos"
+msgid "Travels"
+msgstr "Desplazamientos"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:290
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:236
msgctxt "@label"
-msgid "Show Helpers"
-msgstr "Mostrar asistentes"
+msgid "Helpers"
+msgstr "Asistentes"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:296
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:242
msgctxt "@label"
-msgid "Show Shell"
-msgstr "Mostrar perímetro"
+msgid "Shell"
+msgstr "Perímetro"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:302
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:248
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedInfillDensitySelector.qml:65
msgctxt "@label"
-msgid "Show Infill"
-msgstr "Mostrar relleno"
+msgid "Infill"
+msgstr "Relleno"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:355
+#: /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/SimulationView.qml:366
+#: /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/SimulationView.qml:379
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:322
msgctxt "@label"
msgid "Top / Bottom"
msgstr "Superior o inferior"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:383
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:326
msgctxt "@label"
msgid "Inner Wall"
msgstr "Pared interior"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:448
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:384
msgctxt "@label"
msgid "min"
msgstr "mín."
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:500
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:433
msgctxt "@label"
msgid "max"
msgstr "máx."
@@ -2059,40 +2445,40 @@ msgctxt "@label"
msgid "Post Processing Scripts"
msgstr "Secuencias de comandos de posprocesamiento"
-#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.qml:225
+#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.qml:233
msgctxt "@action"
msgid "Add a script"
msgstr "Añadir secuencia de comando"
-#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.qml:271
+#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.qml:279
msgctxt "@label"
msgid "Settings"
msgstr "Ajustes"
-#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.qml:474
+#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.qml:493
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 these data"
-msgstr "No quiero enviar estos datos"
+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 these data to Ultimaker and help us improve Cura"
-msgstr "Permita enviar estos datos a Ultimaker y ayúdenos a mejorar Cura"
+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"
@@ -2141,19 +2527,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."
@@ -2194,18 +2580,18 @@ 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:341
+#: /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:383
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:388
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/resources/qml/Preferences/SettingVisibilityPage.qml:98
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/SettingVisibilityPage.qml:94
msgctxt "@label:textbox"
msgid "Filter..."
msgstr "Filtrar..."
@@ -2232,13 +2618,13 @@ msgid "Create new"
msgstr "Crear nuevo"
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:70
-#: /home/ruben/Projects/Cura/resources/qml/WorkspaceSummaryDialog.qml:72
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:73
msgctxt "@action:title"
msgid "Summary - Cura Project"
msgstr "Resumen: proyecto de Cura"
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:92
-#: /home/ruben/Projects/Cura/resources/qml/WorkspaceSummaryDialog.qml:96
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:97
msgctxt "@action:label"
msgid "Printer settings"
msgstr "Ajustes de la impresora"
@@ -2255,18 +2641,19 @@ msgid "Update"
msgstr "Actualizar"
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:143
-#: /home/ruben/Projects/Cura/resources/qml/WorkspaceSummaryDialog.qml:105
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:106
msgctxt "@action:label"
msgid "Type"
msgstr "Tipo"
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:159
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:121
msgctxt "@action:label"
msgid "Printer Group"
msgstr "Grupo de impresoras"
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:180
-#: /home/ruben/Projects/Cura/resources/qml/WorkspaceSummaryDialog.qml:196
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:226
msgctxt "@action:label"
msgid "Profile settings"
msgstr "Ajustes del perfil"
@@ -2278,19 +2665,20 @@ 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/resources/qml/WorkspaceSummaryDialog.qml:220
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:121
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:250
msgctxt "@action:label"
msgid "Name"
msgstr "Nombre"
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:231
-#: /home/ruben/Projects/Cura/resources/qml/WorkspaceSummaryDialog.qml:204
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:234
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/WorkspaceSummaryDialog.qml:209
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:239
msgctxt "@action:label"
msgid "%1 override"
msgid_plural "%1 overrides"
@@ -2320,7 +2708,6 @@ 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/resources/qml/WorkspaceSummaryDialog.qml:237
msgctxt "@action:label"
msgid "Setting visibility"
msgstr "Visibilidad de los ajustes"
@@ -2331,13 +2718,11 @@ msgid "Mode"
msgstr "Modo"
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:352
-#: /home/ruben/Projects/Cura/resources/qml/WorkspaceSummaryDialog.qml:246
msgctxt "@action:label"
msgid "Visible settings:"
msgstr "Ajustes visibles:"
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:357
-#: /home/ruben/Projects/Cura/resources/qml/WorkspaceSummaryDialog.qml:251
msgctxt "@action:label"
msgid "%1 out of %2"
msgstr "%1 de un total de %2"
@@ -2352,256 +2737,191 @@ msgctxt "@action:button"
msgid "Open"
msgstr "Abrir"
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/ProfileCreatorTabControls.qml:34
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/pages/BackupsPage.qml:28
+msgctxt "@title"
+msgid "My Backups"
+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 "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 "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 "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 "Iniciar sesión"
+
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/main.qml:24
+msgctxt "@title:window"
+msgid "Cura Backups"
+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 "Versión de Cura"
+
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListItemDetails.qml:29
+msgctxt "@backuplist:label"
+msgid "Machines"
+msgstr "Máquinas"
+
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListItemDetails.qml:37
+msgctxt "@backuplist:label"
+msgid "Materials"
+msgstr "Materiales"
+
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListItemDetails.qml:45
+msgctxt "@backuplist:label"
+msgid "Profiles"
+msgstr "Perfiles"
+
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListItemDetails.qml:53
+msgctxt "@backuplist:label"
+msgid "Plugins"
+msgstr "Complementos"
+
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListItem.qml:71
+msgctxt "@button"
+msgid "Restore"
+msgstr "Restaurar"
+
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListItem.qml:99
+msgctxt "@dialog:title"
+msgid "Delete Backup"
+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 "¿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 "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 "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 "¿Desea obtener más información?"
+
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListFooter.qml:31
+msgctxt "@button"
+msgid "Backup Now"
+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 "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 "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 "No compatible"
+
+#: /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:138
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:154
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:152
+#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/ProfileCreatorTabControls.qml:60
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:174
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:159
msgctxt "@action:button"
msgid "Export"
msgstr "Exportar"
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/ProfileCreatorTabControls.qml:140
-msgctxt "@action:button"
-msgid "Next"
-msgstr "Siguiente"
-
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/ProfileCreatorPageCategoryView.qml:163
+#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/ProfileCreatorPageCategoryView.qml:209
msgctxt "@label"
msgid "Tip"
msgstr "Consejo"
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/CuraPrintProfileCreatorView.qml:80
-#: /home/ruben/Projects/Cura/resources/qml/PrepareSidebar.qml:341
-msgctxt "@label Hours and minutes"
-msgid "00h 00min"
-msgstr "00 h 00 min"
+#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/ProfileCreatorMaterialMenu.qml:20
+#: /home/ruben/Projects/Cura/resources/qml/Menus/MaterialMenu.qml:66
+msgctxt "@label:category menu label"
+msgid "Generic"
+msgstr "Genérico"
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/CuraPrintProfileCreatorView.qml:142
-#: /home/ruben/Projects/Cura/resources/qml/PrepareSidebar.qml:441
-msgctxt "@label"
-msgid "Cost specification"
-msgstr "Especificación de costes"
-
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/CuraPrintProfileCreatorView.qml:147
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/CuraPrintProfileCreatorView.qml:156
-#: /home/ruben/Projects/Cura/resources/qml/PrepareSidebar.qml:446
-#: /home/ruben/Projects/Cura/resources/qml/PrepareSidebar.qml:455
-msgctxt "@label m for meter"
-msgid "%1m"
-msgstr "%1 m"
-
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/CuraPrintProfileCreatorView.qml:148
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/CuraPrintProfileCreatorView.qml:157
-#: /home/ruben/Projects/Cura/resources/qml/PrepareSidebar.qml:447
-#: /home/ruben/Projects/Cura/resources/qml/PrepareSidebar.qml:456
-msgctxt "@label g for grams"
-msgid "%1g"
-msgstr "%1 g"
-
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/CuraPrintProfileCreatorView.qml:155
-#: /home/ruben/Projects/Cura/resources/qml/PrepareSidebar.qml:454
-msgctxt "@label"
-msgid "Total:"
-msgstr "Total:"
-
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/CuraPrintProfileCreatorView.qml:205
-msgctxt "@label Print estimates: m for meters, g for grams, %4 is currency and %3 is print cost"
-msgid "%1m / ~ %2g / ~ %4 %3"
-msgstr "%1 m/~ %2 g/~ %4 %3"
-
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/CuraPrintProfileCreatorView.qml:210
-msgctxt "@label Print estimates: m for meters, g for grams"
-msgid "%1m / ~ %2g"
-msgstr "%1 m/~ %2 g"
-
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/ProfileCreatorPage.qml:143
+#: /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:26
+#: /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
+#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UM2UpgradeSelectionMachineAction.qml:30
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
+#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UM2UpgradeSelectionMachineAction.qml:44
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/UpgradeFirmwareMachineAction.qml:30
-msgctxt "@title"
-msgid "Upgrade Firmware"
-msgstr "Actualización de firmware"
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UpgradeFirmwareMachineAction.qml:41
-msgctxt "@label"
-msgid "Firmware is the piece of software running directly on your 3D printer. This firmware controls the step motors, regulates the temperature and ultimately makes your printer work."
-msgstr "El firmware es la parte del software que se ejecuta directamente en la impresora 3D. Este firmware controla los motores de pasos, regula la temperatura y, finalmente, hace que funcione la impresora."
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UpgradeFirmwareMachineAction.qml:51
-msgctxt "@label"
-msgid "The firmware shipping with new printers works, but new versions tend to have more features and improvements."
-msgstr "El firmware que se envía con las nuevas impresoras funciona, pero las nuevas versiones suelen tener más funciones y mejoras."
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UpgradeFirmwareMachineAction.qml:65
-msgctxt "@action:button"
-msgid "Automatically upgrade Firmware"
-msgstr "Actualización de firmware automática"
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UpgradeFirmwareMachineAction.qml:75
-msgctxt "@action:button"
-msgid "Upload custom Firmware"
-msgstr "Cargar firmware personalizado"
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UpgradeFirmwareMachineAction.qml:87
-msgctxt "@title:window"
-msgid "Select custom firmware"
-msgstr "Seleccionar firmware personalizado"
-
-#: /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"
@@ -2613,7 +2933,6 @@ msgid "Printer does not accept commands"
msgstr "La impresora no acepta comandos"
#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:133
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:197
msgctxt "@label:MonitorStatus"
msgid "In maintenance. Please check the printer"
msgstr "En mantenimiento. Compruebe la impresora"
@@ -2624,19 +2943,16 @@ msgid "Lost connection with the printer"
msgstr "Se ha perdido la conexión con la impresora"
#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:146
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:187
msgctxt "@label:MonitorStatus"
msgid "Printing..."
msgstr "Imprimiendo..."
#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:149
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:189
msgctxt "@label:MonitorStatus"
msgid "Paused"
msgstr "En pausa"
#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:152
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:191
msgctxt "@label:MonitorStatus"
msgid "Preparing..."
msgstr "Preparando..."
@@ -2656,229 +2972,170 @@ 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/DiscardOrKeepProfileChangesDialog.qml:15
-msgctxt "@title:window"
-msgid "Discard or Keep changes"
-msgstr "Descartar o guardar cambios"
-
-#: /home/ruben/Projects/Cura/resources/qml/DiscardOrKeepProfileChangesDialog.qml:57
-msgctxt "@text:window"
-msgid ""
-"You have customized some profile settings.\n"
-"Would you like to keep or discard those settings?"
-msgstr ""
-"Ha personalizado parte de los ajustes del perfil.\n"
-"¿Desea descartar los cambios o guardarlos?"
-
-#: /home/ruben/Projects/Cura/resources/qml/DiscardOrKeepProfileChangesDialog.qml:110
-msgctxt "@title:column"
-msgid "Profile settings"
-msgstr "Ajustes del perfil"
-
-#: /home/ruben/Projects/Cura/resources/qml/DiscardOrKeepProfileChangesDialog.qml:117
-msgctxt "@title:column"
-msgid "Default"
-msgstr "Valor predeterminado"
-
-#: /home/ruben/Projects/Cura/resources/qml/DiscardOrKeepProfileChangesDialog.qml:124
-msgctxt "@title:column"
-msgid "Customized"
-msgstr "Valor personalizado"
-
-#: /home/ruben/Projects/Cura/resources/qml/DiscardOrKeepProfileChangesDialog.qml:157
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:639
-msgctxt "@option:discardOrKeep"
-msgid "Always ask me this"
-msgstr "Preguntar siempre"
-
-#: /home/ruben/Projects/Cura/resources/qml/DiscardOrKeepProfileChangesDialog.qml:158
-msgctxt "@option:discardOrKeep"
-msgid "Discard and never ask again"
-msgstr "Descartar y no volver a preguntar"
-
-#: /home/ruben/Projects/Cura/resources/qml/DiscardOrKeepProfileChangesDialog.qml:159
-msgctxt "@option:discardOrKeep"
-msgid "Keep and never ask again"
-msgstr "Guardar y no volver a preguntar"
-
-#: /home/ruben/Projects/Cura/resources/qml/DiscardOrKeepProfileChangesDialog.qml:196
-msgctxt "@action:button"
-msgid "Discard"
-msgstr "Descartar"
-
-#: /home/ruben/Projects/Cura/resources/qml/DiscardOrKeepProfileChangesDialog.qml:209
-msgctxt "@action:button"
-msgid "Keep"
-msgstr "Guardar"
-
-#: /home/ruben/Projects/Cura/resources/qml/DiscardOrKeepProfileChangesDialog.qml:222
-msgctxt "@action:button"
-msgid "Create New Profile"
-msgstr "Crear nuevo perfil"
-
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:71
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:73
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:102
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:103
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:127
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:137
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:147
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:157
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:207
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:209
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:224
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:258
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:275
msgctxt "@label"
msgid "Filament weight"
msgstr "Anchura del filamento"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:298
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:293
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:302
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:316
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:323
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:334
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:347
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/Preferences/Materials/MaterialsView.qml:373
+#: /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:35
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:72
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:99
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:40
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:73
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:117
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:131
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:160
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:148
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:223
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:239
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:287
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:253
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:240
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:290
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:254
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:304
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:312
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:313
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:317
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:335
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:343
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:347
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:353
msgctxt "@info:status Don't translate the XML tag !"
msgid "Successfully exported material to %1"
msgstr "El material se ha exportado correctamente a %1"
@@ -2888,649 +3145,536 @@ msgctxt "@title:tab"
msgid "Setting Visibility"
msgstr "Visibilidad de los ajustes"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/SettingVisibilityPage.qml:50
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/SettingVisibilityPage.qml:46
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:48
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:61
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:68
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:75
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:83
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:537
+#: /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:141
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:130
msgctxt "@label"
msgid "Interface"
msgstr "Interfaz"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:152
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:141
msgctxt "@label"
msgid "Language:"
msgstr "Idioma:"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:220
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:208
msgctxt "@label"
msgid "Currency:"
msgstr "Moneda:"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:234
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:221
msgctxt "@label"
msgid "Theme:"
msgstr "Tema:"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:294
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:277
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:311
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:294
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:319
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:302
msgctxt "@option:check"
msgid "Slice automatically"
msgstr "Segmentar automáticamente"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:333
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:316
msgctxt "@label"
msgid "Viewport behavior"
msgstr "Comportamiento de la ventanilla"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:341
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:324
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:350
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:333
msgctxt "@option:check"
msgid "Display overhang"
msgstr "Mostrar voladizos"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:357
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:341
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:362
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:346
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:371
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:356
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:376
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:361
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:386
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:371
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:391
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:371
+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."
+
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:376
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:401
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:402
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:406
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:407
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:415
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:416
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:420
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:421
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:432
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:433
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:441
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:442
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:449
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:450
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:454
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:455
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:470
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:465
+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:472
+msgctxt "@window:text"
+msgid "Camera rendering: "
+msgstr "Renderizado de cámara: "
+
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:483
+msgid "Perspective"
+msgstr "Perspectiva"
+
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:484
+msgid "Orthogonal"
+msgstr "Ortográfica"
+
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:515
msgctxt "@label"
msgid "Opening and saving files"
msgstr "Abrir y guardar archivos"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:477
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:522
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:482
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:527
msgctxt "@option:check"
msgid "Scale large models"
msgstr "Escalar modelos de gran tamaño"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:492
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:537
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:497
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:542
msgctxt "@option:check"
msgid "Scale extremely small models"
msgstr "Escalar modelos demasiado pequeños"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:507
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:552
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:512
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:557
msgctxt "@option:check"
msgid "Select models when loaded"
msgstr "Seleccionar modelos al abrirlos"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:522
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:567
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:527
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:572
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:537
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:582
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:541
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:586
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:551
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:596
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:559
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:604
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:573
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:618
msgctxt "@option:openProject"
msgid "Always ask me this"
msgstr "Preguntar siempre"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:574
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:619
msgctxt "@option:openProject"
msgid "Always open as a project"
msgstr "Abrir siempre como un proyecto"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:575
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:620
msgctxt "@option:openProject"
msgid "Always import models"
msgstr "Importar modelos siempre"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:611
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:656
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:620
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:665
msgctxt "@label"
msgid "Profiles"
msgstr "Perfiles"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:625
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:670
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:640
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:684
+#: /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:685
msgctxt "@option:discardOrKeep"
msgid "Always discard changed settings"
msgstr "Descartar siempre los ajustes modificados"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:641
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:686
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:675
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:720
msgctxt "@label"
msgid "Privacy"
msgstr "Privacidad"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:683
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:727
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:688
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:732
msgctxt "@option:check"
msgid "Check for updates on start"
msgstr "Buscar actualizaciones al iniciar"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:699
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:742
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:704
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:747
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:713
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:756
msgctxt "@action:button"
msgid "More information"
msgstr "Más información"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:731
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:774
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/PrintSetupSelectorHeader.qml:27
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ProfileMenu.qml:23
msgctxt "@label"
msgid "Experimental"
msgstr "Experimental"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:738
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:781
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:743
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:786
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:542
+#: /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:55
-#: /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:134
msgctxt "@action:button"
msgid "Rename"
msgstr "Cambiar nombre"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:147
-msgctxt "@label"
-msgid "Printer type:"
-msgstr "Tipo de impresora:"
-
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:156
-msgctxt "@label"
-msgid "Connection:"
-msgstr "Conexión:"
-
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:162
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/OutputDeviceHeader.qml:47
-msgctxt "@info:status"
-msgid "The printer is not connected."
-msgstr "La impresora no está conectada."
-
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:168
-msgctxt "@label"
-msgid "State:"
-msgstr "Estado:"
-
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:181
-msgctxt "@label:MonitorStatus"
-msgid "Waiting for a printjob"
-msgstr "Esperando un trabajo de impresión"
-
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:193
-msgctxt "@label:MonitorStatus"
-msgid "Waiting for someone to clear the build plate"
-msgstr "Esperando a que alguien limpie la placa de impresión"
-
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:199
-msgctxt "@label:MonitorStatus"
-msgid "Aborting print..."
-msgstr "Cancelando impresión..."
-
#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:36
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:546
+#: /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:89
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:105
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:181
msgctxt "@title:window"
msgid "Create Profile"
msgstr "Crear perfil"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:225
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:183
+msgctxt "@info"
+msgid "Please provide a name for this profile."
+msgstr "Introduzca un nombre para este perfil."
+
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:239
msgctxt "@title:window"
msgid "Duplicate Profile"
msgstr "Duplicar perfil"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:256
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:270
msgctxt "@title:window"
msgid "Rename Profile"
msgstr "Cambiar nombre de perfil"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:269
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:283
msgctxt "@title:window"
msgid "Import Profile"
msgstr "Importar perfil"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:295
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:309
msgctxt "@title:window"
msgid "Export Profile"
msgstr "Exportar perfil"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:350
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:364
msgctxt "@label %1 is printer name"
msgid "Printer: %1"
msgstr "Impresora: %1"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:403
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:420
msgctxt "@label"
-msgid "Protected profiles"
-msgstr "Perfiles protegidos"
+msgid "Default profiles"
+msgstr "Perfiles predeterminados"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:403
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:420
msgctxt "@label"
msgid "Custom profiles"
msgstr "Perfiles personalizados"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:480
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:500
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:487
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:507
msgctxt "@action:button"
msgid "Discard current changes"
msgstr "Descartar cambios actuales"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:504
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:524
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:511
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:531
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:530
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:550
msgctxt "@title:tab"
msgid "Global Settings"
msgstr "Ajustes globales"
-#: /home/ruben/Projects/Cura/resources/qml/AddMachineDialog.qml:18
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:946
-msgctxt "@title:window"
-msgid "Add Printer"
-msgstr "Agregar impresora"
-
-#: /home/ruben/Projects/Cura/resources/qml/AddMachineDialog.qml:194
-msgctxt "@label"
-msgid "Printer Name:"
-msgstr "Nombre de la impresora:"
-
-#: /home/ruben/Projects/Cura/resources/qml/AddMachineDialog.qml:217
+#: /home/ruben/Projects/Cura/resources/qml/MainWindow/MainWindowHeader.qml:89
msgctxt "@action:button"
-msgid "Add Printer"
-msgstr "Agregar impresora"
+msgid "Marketplace"
+msgstr "Marketplace"
-#: /home/ruben/Projects/Cura/resources/qml/JobSpecs.qml:84
+#: /home/ruben/Projects/Cura/resources/qml/MainWindow/ApplicationMenu.qml:27
+#: /home/ruben/Projects/Cura/resources/qml/Menus/FileMenu.qml:13
+msgctxt "@title:menu menubar:toplevel"
+msgid "&File"
+msgstr "&Archivo"
+
+#: /home/ruben/Projects/Cura/resources/qml/MainWindow/ApplicationMenu.qml:31
+msgctxt "@title:menu menubar:toplevel"
+msgid "&Edit"
+msgstr "&Edición"
+
+#: /home/ruben/Projects/Cura/resources/qml/MainWindow/ApplicationMenu.qml:48
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ViewMenu.qml:12
+msgctxt "@title:menu menubar:toplevel"
+msgid "&View"
+msgstr "&Ver"
+
+#: /home/ruben/Projects/Cura/resources/qml/MainWindow/ApplicationMenu.qml:50
+#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:13
+msgctxt "@title:menu menubar:toplevel"
+msgid "&Settings"
+msgstr "A&justes"
+
+#: /home/ruben/Projects/Cura/resources/qml/MainWindow/ApplicationMenu.qml:55
+msgctxt "@title:menu menubar:toplevel"
+msgid "E&xtensions"
+msgstr "E&xtensiones"
+
+#: /home/ruben/Projects/Cura/resources/qml/MainWindow/ApplicationMenu.qml:89
+msgctxt "@title:menu menubar:toplevel"
+msgid "P&references"
+msgstr "Pre&ferencias"
+
+#: /home/ruben/Projects/Cura/resources/qml/MainWindow/ApplicationMenu.qml:97
+msgctxt "@title:menu menubar:toplevel"
+msgid "&Help"
+msgstr "A&yuda"
+
+#: /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: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."
+
+#: /home/ruben/Projects/Cura/resources/qml/JobSpecs.qml:88
msgctxt "@text Print job name"
msgid "Untitled"
msgstr "Sin título"
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:15
-msgctxt "@title:window"
-msgid "About Cura"
-msgstr "Acerca de Cura"
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:43
-msgctxt "@label"
-msgid "version: %1"
-msgstr "versión: %1"
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:56
-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/AboutDialog.qml:69
-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 ""
-"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/AboutDialog.qml:118
-msgctxt "@label"
-msgid "Graphical user interface"
-msgstr "Interfaz gráfica de usuario (GUI)"
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:119
-msgctxt "@label"
-msgid "Application framework"
-msgstr "Entorno de la aplicación"
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:120
-msgctxt "@label"
-msgid "G-code generator"
-msgstr "Generador de GCode"
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:121
-msgctxt "@label"
-msgid "Interprocess communication library"
-msgstr "Biblioteca de comunicación entre procesos"
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:123
-msgctxt "@label"
-msgid "Programming language"
-msgstr "Lenguaje de programación"
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:124
-msgctxt "@label"
-msgid "GUI framework"
-msgstr "Entorno de la GUI"
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:125
-msgctxt "@label"
-msgid "GUI framework bindings"
-msgstr "Enlaces del entorno de la GUI"
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:126
-msgctxt "@label"
-msgid "C/C++ Binding library"
-msgstr "Biblioteca de enlaces C/C++"
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:127
-msgctxt "@label"
-msgid "Data interchange format"
-msgstr "Formato de intercambio de datos"
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:128
-msgctxt "@label"
-msgid "Support library for scientific computing"
-msgstr "Biblioteca de apoyo para cálculos científicos"
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:129
-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/AboutDialog.qml:130
-msgctxt "@label"
-msgid "Support library for handling STL files"
-msgstr "Biblioteca de apoyo para gestionar archivos STL"
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:131
-msgctxt "@label"
-msgid "Support library for handling 3MF files"
-msgstr "Biblioteca de compatibilidad para trabajar con archivos 3MF"
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:132
-msgctxt "@label"
-msgid "Serial communication library"
-msgstr "Biblioteca de comunicación en serie"
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:133
-msgctxt "@label"
-msgid "ZeroConf discovery library"
-msgstr "Biblioteca de detección para Zeroconf"
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:134
-msgctxt "@label"
-msgid "Polygon clipping library"
-msgstr "Biblioteca de recorte de polígonos"
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:135
-msgctxt "@Label"
-msgid "Python HTTP library"
-msgstr "Biblioteca HTTP de Python"
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:137
-msgctxt "@label"
-msgid "Font"
-msgstr "Fuente"
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:138
-msgctxt "@label"
-msgid "SVG icons"
-msgstr "Iconos SVG"
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:139
-msgctxt "@label"
-msgid "Linux cross-distribution application deployment"
-msgstr "Implementación de la aplicación de distribución múltiple de Linux"
-
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:42
-msgctxt "@label"
-msgid "Profile:"
-msgstr "Perfil:"
-
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:103
-msgctxt "@tooltip"
-msgid ""
-"Some setting/override values are different from the values stored in the profile.\n"
-"\n"
-"Click to open the profile manager."
-msgstr ""
-"Algunos valores de los ajustes o sobrescrituras son distintos a los valores almacenados en el perfil.\n"
-"\n"
-"Haga clic para abrir el administrador de perfiles."
-
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:199
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:68
msgctxt "@label:textbox"
-msgid "Search..."
-msgstr "Buscar..."
+msgid "search settings"
+msgstr "buscar ajustes"
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:544
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:466
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:553
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:475
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:590
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:512
msgctxt "@action:menu"
msgid "Hide this setting"
msgstr "Ocultar este ajuste"
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:608
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:525
msgctxt "@action:menu"
msgid "Don't show this setting"
msgstr "No mostrar este ajuste"
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:612
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:529
msgctxt "@action:menu"
msgid "Keep this setting visible"
msgstr "Mostrar este ajuste"
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:636
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:416
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:548
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:434
msgctxt "@action:menu"
msgid "Configure setting visibility..."
msgstr "Configurar visibilidad de los ajustes..."
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:643
-msgctxt "@action:inmenu"
-msgid "Collapse All"
-msgstr "Contraer todo"
-
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:648
-msgctxt "@action:inmenu"
-msgid "Expand All"
-msgstr "Ampliar todo"
-
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingCategory.qml:249
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingCategory.qml:237
msgctxt "@label"
msgid ""
"Some hidden settings use values different from their normal calculated value.\n"
@@ -3541,27 +3685,32 @@ msgstr ""
"\n"
"Haga clic para mostrar estos ajustes."
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:61
+#: /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:66
+#: /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:154
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:186
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:157
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:190
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:188
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:228
msgctxt "@label"
msgid ""
"This setting has a value that is different from the profile.\n"
@@ -3572,7 +3721,7 @@ msgstr ""
"\n"
"Haga clic para restaurar el valor del perfil."
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:286
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:322
msgctxt "@label"
msgid ""
"This setting is normally calculated, but it currently has an absolute value set.\n"
@@ -3583,116 +3732,210 @@ msgstr ""
"\n"
"Haga clic para restaurar el valor calculado."
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ManualPrinterControl.qml:129
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/PrintSetupSelectorContents.qml:144
+msgctxt "@button"
+msgid "Recommended"
+msgstr "Recomendado"
+
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/PrintSetupSelectorContents.qml:158
+msgctxt "@button"
+msgid "Custom"
+msgstr "Personalizado"
+
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedInfillDensitySelector.qml:193
+msgctxt "@label"
+msgid "Gradual infill"
+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:30
+msgctxt "@label"
+msgid "Support"
+msgstr "Soporte"
+
+#: /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/RecommendedAdhesionSelector.qml:29
+msgctxt "@label"
+msgid "Adhesion"
+msgstr "Adherencia"
+
+#: /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
+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 "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."
+
+#: /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 "Encendido"
+
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/PrintSetupSelectorHeader.qml:14
+msgctxt "@label:Should be short"
+msgid "Off"
+msgstr "Apagado"
+
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Custom/GlobalProfileSelector.qml:27
+msgctxt "@label"
+msgid "Profile"
+msgstr "Perfil"
+
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Custom/GlobalProfileSelector.qml:94
+msgctxt "@tooltip"
+msgid ""
+"Some setting/override values are different from the values stored in the profile.\n"
+"\n"
+"Click to open the profile manager."
+msgstr ""
+"Algunos valores de los ajustes o sobrescrituras son distintos a los valores almacenados en el perfil.\n"
+"\n"
+"Haga clic para abrir el administrador de perfiles."
+
+#: /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 "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"
msgid "Printer control"
msgstr "Control de impresoras"
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ManualPrinterControl.qml:144
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ManualPrinterControl.qml:67
msgctxt "@label"
msgid "Jog Position"
msgstr "Posición de desplazamiento"
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ManualPrinterControl.qml:162
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ManualPrinterControl.qml:85
msgctxt "@label"
msgid "X/Y"
msgstr "X/Y"
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ManualPrinterControl.qml:269
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ManualPrinterControl.qml:192
msgctxt "@label"
msgid "Z"
msgstr "Z"
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ManualPrinterControl.qml:334
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ManualPrinterControl.qml:257
msgctxt "@label"
msgid "Jog Distance"
msgstr "Distancia de desplazamiento"
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ManualPrinterControl.qml:443
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ManualPrinterControl.qml:301
msgctxt "@label"
msgid "Send G-code"
msgstr "Enviar GCode"
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ManualPrinterControl.qml:506
+#: /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:36
-#: /home/ruben/Projects/Cura/resources/qml/SidebarHeader.qml:272
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:38
msgctxt "@label"
msgid "Extruder"
msgstr "Extrusor"
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:66
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:68
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:98
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:100
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:172
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:174
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:336
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/HeatedBedBox.qml:331
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:338
+#: /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:339
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/HeatedBedBox.qml:334
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:341
+#: /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:365
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:367
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:401
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:403
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:433
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:435
msgctxt "@tooltip"
msgid "The material in this extruder."
msgstr "Material en este extrusor."
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:465
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:467
msgctxt "@tooltip"
msgid "The nozzle inserted in this extruder."
msgstr "Tobera insertada en este extrusor."
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/HeatedBedBox.qml:25
-#: /home/ruben/Projects/Cura/resources/qml/SidebarHeader.qml:493
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/OutputDeviceHeader.qml:55
+msgctxt "@info:status"
+msgid "The printer is not connected."
+msgstr "La impresora no está conectada."
+
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/HeatedBedBox.qml:26
msgctxt "@label"
msgid "Build plate"
msgstr "Placa de impresión"
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/HeatedBedBox.qml:55
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/HeatedBedBox.qml:56
msgctxt "@tooltip"
msgid "The target temperature of the heated bed. The bed will heat up or cool down towards this temperature. If this is 0, the bed heating is turned off."
msgstr "Temperatura objetivo de la plataforma calentada. La plataforma se calentará o enfriará en función de esta temperatura. Si el valor es 0, el calentamiento de la plataforma se desactivará."
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/HeatedBedBox.qml:87
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/HeatedBedBox.qml:88
msgctxt "@tooltip"
msgid "The current temperature of the heated bed."
msgstr "Temperatura actual de la plataforma caliente."
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/HeatedBedBox.qml:160
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/HeatedBedBox.qml:161
msgctxt "@tooltip of temperature input"
msgid "The temperature to pre-heat the bed to."
msgstr "Temperatura a la que se va a precalentar la plataforma."
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/HeatedBedBox.qml:360
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/HeatedBedBox.qml:361
msgctxt "@tooltip of pre-heat"
msgid "Heat the bed in advance before printing. You can continue adjusting your print while it is heating, and you won't have to wait for the bed to heat up when you're ready to print."
msgstr "Caliente la plataforma antes de imprimir. Puede continuar ajustando la impresión durante el calentamiento, así no tendrá que esperar a que la plataforma se caliente para poder imprimir."
@@ -3702,16 +3945,11 @@ msgctxt "@label:category menu label"
msgid "Material"
msgstr "Material"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/MaterialMenu.qml:37
+#: /home/ruben/Projects/Cura/resources/qml/Menus/MaterialMenu.qml:42
msgctxt "@label:category menu label"
msgid "Favorites"
msgstr "Favoritos"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/MaterialMenu.qml:61
-msgctxt "@label:category menu label"
-msgid "Generic"
-msgstr "Genérico"
-
#: /home/ruben/Projects/Cura/resources/qml/Menus/PrinterMenu.qml:25
msgctxt "@label:category menu label"
msgid "Network enabled printers"
@@ -3722,17 +3960,62 @@ msgctxt "@label:category menu label"
msgid "Local printers"
msgstr "Impresoras locales"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/ViewMenu.qml:12
-msgctxt "@title:menu menubar:toplevel"
-msgid "&View"
-msgstr "&Ver"
+#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:15
+msgctxt "@title:menu menubar:settings"
+msgid "&Printer"
+msgstr "&Impresora"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/ViewMenu.qml:39
+#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:32
+msgctxt "@title:menu"
+msgid "&Material"
+msgstr "&Material"
+
+#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:41
+msgctxt "@action:inmenu"
+msgid "Set as Active Extruder"
+msgstr "Definir como extrusor activo"
+
+#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:47
+msgctxt "@action:inmenu"
+msgid "Enable Extruder"
+msgstr "Habilitar extrusor"
+
+#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:54
+msgctxt "@action:inmenu"
+msgid "Disable Extruder"
+msgstr "Deshabilitar extrusor"
+
+#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:68
+msgctxt "@title:menu"
+msgid "&Build plate"
+msgstr "&Placa de impresión"
+
+#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:71
+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:54
+#: /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"
@@ -3742,16 +4025,31 @@ msgctxt "@action:inmenu"
msgid "Visible Settings"
msgstr "Ajustes visibles"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingVisibilityPresetsMenu.qml:43
+#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingVisibilityPresetsMenu.qml:42
msgctxt "@action:inmenu"
msgid "Show All Settings"
msgstr "Mostrar todos los ajustes"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingVisibilityPresetsMenu.qml:54
+#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingVisibilityPresetsMenu.qml:53
msgctxt "@action:inmenu"
msgid "Manage Setting Visibility..."
msgstr "Gestionar visibilidad de los ajustes..."
+#: /home/ruben/Projects/Cura/resources/qml/Menus/FileMenu.qml:32
+msgctxt "@title:menu menubar:file"
+msgid "&Save..."
+msgstr "&Guardar..."
+
+#: /home/ruben/Projects/Cura/resources/qml/Menus/FileMenu.qml:53
+msgctxt "@title:menu menubar:file"
+msgid "&Export..."
+msgstr "&Exportar..."
+
+#: /home/ruben/Projects/Cura/resources/qml/Menus/FileMenu.qml:64
+msgctxt "@action:inmenu menubar:file"
+msgid "Export Selection..."
+msgstr "Exportar selección..."
+
#: /home/ruben/Projects/Cura/resources/qml/Menus/ContextMenu.qml:27
msgctxt "@label"
msgid "Print Selected Model With:"
@@ -3771,634 +4069,509 @@ msgctxt "@label"
msgid "Number of Copies"
msgstr "Número de copias"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/ConfigurationListView.qml:33
-msgctxt "@label:header configurations"
-msgid "Available configurations"
-msgstr "Configuraciones disponibles"
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/AutoConfiguration.qml:18
+msgctxt "@header"
+msgid "Configurations"
+msgstr "Configuraciones"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/PrintCoreConfiguration.qml:28
-msgctxt "@label:extruder label"
-msgid "Extruder"
-msgstr "Extrusor"
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/ConfigurationMenu.qml:110
+msgctxt "@label"
+msgid "Select configuration"
+msgstr "Seleccionar configuración"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/SyncButton.qml:16
-msgctxt "@label:extruder label"
-msgid "Yes"
-msgstr "Sí"
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/ConfigurationMenu.qml:221
+msgctxt "@label"
+msgid "Configurations"
+msgstr "Configuraciones"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/SyncButton.qml:16
-msgctxt "@label:extruder label"
-msgid "No"
-msgstr "No"
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/ConfigurationListView.qml:57
+msgctxt "@label"
+msgid "Loading available configurations from the printer..."
+msgstr "Cargando configuraciones disponibles desde la impresora..."
-#: /home/ruben/Projects/Cura/resources/qml/Menus/RecentFilesMenu.qml:13
+#: /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 "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 "Personalizado"
+
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/CustomConfiguration.qml:61
+msgctxt "@label"
+msgid "Printer"
+msgstr "Impresora"
+
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/CustomConfiguration.qml:213
+msgctxt "@label"
+msgid "Enabled"
+msgstr "Habilitado"
+
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/CustomConfiguration.qml:250
+msgctxt "@label"
+msgid "Material"
+msgstr "Material"
+
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/CustomConfiguration.qml:375
+msgctxt "@label"
+msgid "Use glue for better adhesion with this material combination."
+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 "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 "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/PrepareSidebar.qml:150
-msgctxt "@label:listbox"
-msgid "Print Setup"
-msgstr "Configuración de impresión"
-
-#: /home/ruben/Projects/Cura/resources/qml/PrepareSidebar.qml:150
-msgctxt "@label:listbox"
-msgid ""
-"Print Setup disabled\n"
-"G-code files cannot be modified"
-msgstr ""
-"Ajustes de impresión deshabilitados\n"
-"No se pueden modificar los archivos GCode"
-
-#: /home/ruben/Projects/Cura/resources/qml/PrepareSidebar.qml:359
-msgctxt "@tooltip"
-msgid "Time specification"
-msgstr "Especificación de tiempos"
-
-#: /home/ruben/Projects/Cura/resources/qml/PrepareSidebar.qml:577
-msgctxt "@tooltip"
-msgid "Recommended Print Setup
Print with the recommended settings for the selected printer, material and quality."
-msgstr "Configuración de impresión recomendada
Imprimir con los ajustes recomendados para la impresora, el material y la calidad seleccionados."
-
-#: /home/ruben/Projects/Cura/resources/qml/PrepareSidebar.qml:582
-msgctxt "@tooltip"
-msgid "Custom Print Setup
Print with finegrained control over every last bit of the slicing process."
-msgstr "Configuración de impresión personalizada
Imprimir con un control muy detallado del proceso de segmentación."
-
-#: /home/ruben/Projects/Cura/resources/qml/PrintMonitor.qml:106
+#: /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:114
+#: /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:122
+#: /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:130
+#: /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/Actions.qml:78
+#: /home/ruben/Projects/Cura/resources/qml/ViewsSelector.qml:50
+msgctxt "@label"
+msgid "View type"
+msgstr "Ver tipo"
+
+#: /home/ruben/Projects/Cura/resources/qml/ObjectSelector.qml:59
+msgctxt "@label"
+msgid "Object list"
+msgstr "Lista de objetos"
+
+#: /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 "Cuenta de Ultimaker"
+
+#: /home/ruben/Projects/Cura/resources/qml/Account/UserOperations.qml:42
+msgctxt "@button"
+msgid "Sign out"
+msgstr "Cerrar sesión"
+
+#: /home/ruben/Projects/Cura/resources/qml/Account/AccountWidget.qml:24
+msgctxt "@action:button"
+msgid "Sign in"
+msgstr "Iniciar sesión"
+
+#: /home/ruben/Projects/Cura/resources/qml/Account/GeneralOperations.qml:40
+msgctxt "@label"
+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/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 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 "Crear cuenta"
+
+#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/OutputProcessWidget.qml:59
+msgctxt "@label"
+msgid "No time estimation available"
+msgstr "Ningún cálculo de tiempo disponible"
+
+#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/OutputProcessWidget.qml:77
+msgctxt "@label"
+msgid "No cost estimation available"
+msgstr "Ningún cálculo de costes disponible"
+
+#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/OutputProcessWidget.qml:127
+msgctxt "@button"
+msgid "Preview"
+msgstr "Vista previa"
+
+#: /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:67
+msgctxt "@label:PrintjobStatus"
+msgid "Unable to slice"
+msgstr "No se puede segmentar"
+
+#: /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 "Segmentación"
+
+#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/SliceProcessWidget.qml:104
+msgctxt "@label"
+msgid "Start the slicing process"
+msgstr "Iniciar el proceso de segmentación"
+
+#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/SliceProcessWidget.qml:118
+msgctxt "@button"
+msgid "Cancel"
+msgstr "Cancelar"
+
+#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/PrintJobInformation.qml:31
+msgctxt "@label"
+msgid "Time estimation"
+msgstr "Estimación de tiempos"
+
+#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/PrintJobInformation.qml:114
+msgctxt "@label"
+msgid "Material estimation"
+msgstr "Estimación de material"
+
+#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/PrintJobInformation.qml:164
+msgctxt "@label m for meter"
+msgid "%1m"
+msgstr "%1 m"
+
+#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/PrintJobInformation.qml:165
+msgctxt "@label g for grams"
+msgid "%1g"
+msgstr "%1 g"
+
+#: /home/ruben/Projects/Cura/resources/qml/PrinterSelector/MachineSelectorList.qml:19
+msgctxt "@label"
+msgid "Connected printers"
+msgstr "Impresoras conectadas"
+
+#: /home/ruben/Projects/Cura/resources/qml/PrinterSelector/MachineSelectorList.qml:19
+msgctxt "@label"
+msgid "Preset printers"
+msgstr "Impresoras preconfiguradas"
+
+#: /home/ruben/Projects/Cura/resources/qml/PrinterSelector/MachineSelector.qml:166
+msgctxt "@button"
+msgid "Add printer"
+msgstr "Agregar impresora"
+
+#: /home/ruben/Projects/Cura/resources/qml/PrinterSelector/MachineSelector.qml:182
+msgctxt "@button"
+msgid "Manage printers"
+msgstr "Administrar impresoras"
+
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:81
+msgctxt "@action:inmenu"
+msgid "Show Online Troubleshooting Guide"
+msgstr "Mostrar Guía de resolución de problemas en línea"
+
+#: /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:85
+#: /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:95
+#: /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:105
+#: /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:113
+#: /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:120
+#: /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:127
+#: /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:134
+#: /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:141
+#: /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:148
+#: /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:155
+#: /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:161
+#: /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:168
+#: /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:176
+#: /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:184
+#: /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:196
+#: /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:202
+#: /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:209
+#: /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:217
+#: /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:225
+#: /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:232
+#: /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:242
+#: /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:251
+#: /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:260
+#: /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:268
+#: /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:274
+#: /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:294
+#: /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:304
+#: /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:314
+#: /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:321
+#: /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:331
+#: /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:341
+#: /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:350
+#: /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:357
+#: /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:365
+#: /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:372
+#: /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:379
+#: /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:386
+#: /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:394
+#: /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:401
-msgctxt "@action:inmenu menubar:help"
-msgid "Show Engine &Log..."
-msgstr "&Mostrar registro del motor..."
-
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:409
+#: /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:423
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:441
msgctxt "@action:menu"
-msgid "Browse packages..."
-msgstr "Examinar paquetes..."
+msgid "&Marketplace"
+msgstr "&Marketplace"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:430
-msgctxt "@action:inmenu menubar:view"
-msgid "Expand/Collapse Sidebar"
-msgstr "Expandir/contraer barra lateral"
-
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:27
-msgctxt "@label:PrintjobStatus"
-msgid "Please load a 3D model"
-msgstr "Cargue un modelo en 3D"
-
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:37
-msgctxt "@label:PrintjobStatus"
-msgid "Ready to slice"
-msgstr "Preparado para segmentar"
-
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:39
-msgctxt "@label:PrintjobStatus"
-msgid "Slicing..."
-msgstr "Segmentando..."
-
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:41
-msgctxt "@label:PrintjobStatus %1 is target operation"
-msgid "Ready to %1"
-msgstr "Listo para %1"
-
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:43
-msgctxt "@label:PrintjobStatus"
-msgid "Unable to Slice"
-msgstr "No se puede segmentar"
-
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:45
-msgctxt "@label:PrintjobStatus"
-msgid "Slicing unavailable"
-msgstr "No se puede segmentar"
-
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:172
-msgctxt "@info:tooltip"
-msgid "Slice current printjob"
-msgstr "Fragmentar trabajo de impresión actual"
-
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:172
-msgctxt "@info:tooltip"
-msgid "Cancel slicing process"
-msgstr "Cancelar proceso de fragmentación"
-
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:184
-msgctxt "@label:Printjob"
-msgid "Prepare"
-msgstr "Preparar"
-
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:184
-msgctxt "@label:Printjob"
-msgid "Cancel"
-msgstr "Cancelar"
-
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:320
-msgctxt "@info:tooltip"
-msgid "Select the active output device"
-msgstr "Seleccione el dispositivo de salida activo"
-
-#: /home/ruben/Projects/Cura/resources/qml/OpenFilesIncludingProjectsDialog.qml:19
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:760
-msgctxt "@title:window"
-msgid "Open file(s)"
-msgstr "Abrir archivo(s)"
-
-#: /home/ruben/Projects/Cura/resources/qml/OpenFilesIncludingProjectsDialog.qml:64
-msgctxt "@text:window"
-msgid "We have found one or more project file(s) within the files you have selected. You can open only one project file at a time. We suggest to only import models from those files. Would you like to proceed?"
-msgstr "Hemos encontrado uno o más archivos del proyecto entre los archivos que ha seleccionado. Solo puede abrir los archivos de proyecto de uno en uno. Le recomendamos que solo importe modelos de esos archivos. ¿Desea continuar?"
-
-#: /home/ruben/Projects/Cura/resources/qml/OpenFilesIncludingProjectsDialog.qml:99
-msgctxt "@action:button"
-msgid "Import all as models"
-msgstr "Importar todos como modelos"
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:19
+#: /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:104
-msgctxt "@title:menu menubar:toplevel"
-msgid "&File"
-msgstr "&Archivo"
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:120
-msgctxt "@title:menu menubar:file"
-msgid "&Save..."
-msgstr "&Guardar..."
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:141
-msgctxt "@title:menu menubar:file"
-msgid "&Export..."
-msgstr "&Exportar..."
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:151
-msgctxt "@action:inmenu menubar:file"
-msgid "Export Selection..."
-msgstr "Exportar selección..."
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:168
-msgctxt "@title:menu menubar:toplevel"
-msgid "&Edit"
-msgstr "&Edición"
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:185
-msgctxt "@title:menu"
-msgid "&View"
-msgstr "&Ver"
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:190
-msgctxt "@title:menu"
-msgid "&Settings"
-msgstr "A&justes"
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:192
-msgctxt "@title:menu menubar:settings"
-msgid "&Printer"
-msgstr "&Impresora"
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:201
-msgctxt "@title:menu"
-msgid "&Material"
-msgstr "&Material"
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:210
-msgctxt "@action:inmenu"
-msgid "Set as Active Extruder"
-msgstr "Definir como extrusor activo"
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:216
-#: /home/ruben/Projects/Cura/resources/qml/SidebarHeader.qml:188
-msgctxt "@action:inmenu"
-msgid "Enable Extruder"
-msgstr "Habilitar extrusor"
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:223
-#: /home/ruben/Projects/Cura/resources/qml/SidebarHeader.qml:194
-msgctxt "@action:inmenu"
-msgid "Disable Extruder"
-msgstr "Deshabilitar extrusor"
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:235
-msgctxt "@title:menu"
-msgid "&Build plate"
-msgstr "&Placa de impresión"
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:236
-msgctxt "@title:settings"
-msgid "&Profile"
-msgstr "&Perfil"
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:246
-msgctxt "@title:menu menubar:toplevel"
-msgid "E&xtensions"
-msgstr "E&xtensiones"
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:280
-msgctxt "@title:menu menubar:toplevel"
-msgid "&Toolbox"
-msgstr "&Cuadro de herramientas"
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:287
-msgctxt "@title:menu menubar:toplevel"
-msgid "P&references"
-msgstr "Pre&ferencias"
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:295
-msgctxt "@title:menu menubar:toplevel"
-msgid "&Help"
-msgstr "A&yuda"
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:341
+#: /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:370
-msgctxt "@action:button"
-msgid "Open File"
-msgstr "Abrir archivo"
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:540
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:413
msgctxt "@title:tab"
msgid "Settings"
msgstr "Ajustes"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:586
-msgctxt "@title:window"
-msgid "New project"
-msgstr "Nuevo proyecto"
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:587
-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."
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:715
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:539
msgctxt "@title:window"
msgid "Closing Cura"
msgstr "Cerrando Cura"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:716
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:728
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:540
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:552
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:861
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:590
+#: /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:691
msgctxt "@window:title"
msgid "Install Package"
msgstr "Instalar paquete"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:868
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:699
msgctxt "@title:window"
msgid "Open File(s)"
msgstr "Abrir archivo(s)"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:871
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:702
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/WorkspaceSummaryDialog.qml:14
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:805
msgctxt "@title:window"
-msgid "Save Project"
-msgstr "Guardar proyecto"
+msgid "Add Printer"
+msgstr "Agregar impresora"
-#: /home/ruben/Projects/Cura/resources/qml/WorkspaceSummaryDialog.qml:120
-msgctxt "@action:label"
-msgid ""
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/WorkspaceSummaryDialog.qml:137
-msgctxt "@action:label"
-msgid "Build plate"
-msgstr "Placa de impresión"
-
-#: /home/ruben/Projects/Cura/resources/qml/WorkspaceSummaryDialog.qml:169
-msgctxt "@action:label"
-msgid "Extruder %1"
-msgstr "Extrusor %1"
-
-#: /home/ruben/Projects/Cura/resources/qml/WorkspaceSummaryDialog.qml:179
-msgctxt "@action:label"
-msgid "%1 & material"
-msgstr "%1 y material"
-
-#: /home/ruben/Projects/Cura/resources/qml/WorkspaceSummaryDialog.qml:268
-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/WorkspaceSummaryDialog.qml:287
-msgctxt "@action:button"
-msgid "Save"
-msgstr "Guardar"
-
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:192
-msgctxt "@label"
-msgid "Layer Height"
-msgstr "Altura de capa"
-
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:277
-msgctxt "@tooltip"
-msgid "This quality profile is not available for you current material and nozzle configuration. Please change these to enable this quality profile"
-msgstr "Este perfil de calidad no está disponible para la configuración de material y de tobera actual. Cámbiela para poder habilitar este perfil de calidad"
-
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:450
-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/SidebarSimple.qml:467
-msgctxt "@label"
-msgid "Print Speed"
-msgstr "Velocidad de impresión"
-
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:479
-msgctxt "@label"
-msgid "Slower"
-msgstr "Más lento"
-
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:490
-msgctxt "@label"
-msgid "Faster"
-msgstr "Más rápido"
-
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:518
-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/SidebarSimple.qml:541
-msgctxt "@label"
-msgid "Infill"
-msgstr "Relleno"
-
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:777
-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/SidebarSimple.qml:789
-msgctxt "@label"
-msgid "Enable gradual"
-msgstr "Habilitar gradual"
-
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:856
-msgctxt "@label"
-msgid "Generate Support"
-msgstr "Generar soporte"
-
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:890
-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/SidebarSimple.qml:962
-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/SidebarSimple.qml:985
-msgctxt "@label"
-msgid "Build Plate Adhesion"
-msgstr "Adherencia de la placa de impresión"
-
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:1040
-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/SidebarSimple.qml:1080
-msgctxt "@label"
-msgid "Need help improving your prints? Read the Ultimaker Troubleshooting Guides"
-msgstr "¿Necesita ayuda para mejorar sus impresiones? Lea las Guías de solución de problemas de Ultimaker"
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:813
+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"
@@ -4407,75 +4580,483 @@ msgid_plural "Print Selected Models with %1"
msgstr[0] "Imprimir modelo seleccionado con %1"
msgstr[1] "Imprimir modelos seleccionados con %1"
-#: /home/ruben/Projects/Cura/resources/qml/AskOpenAsProjectOrModelsDialog.qml:20
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/DiscardOrKeepProfileChangesDialog.qml:15
+msgctxt "@title:window"
+msgid "Discard or Keep changes"
+msgstr "Descartar o guardar cambios"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/DiscardOrKeepProfileChangesDialog.qml:57
+msgctxt "@text:window"
+msgid ""
+"You have customized some profile settings.\n"
+"Would you like to keep or discard those settings?"
+msgstr ""
+"Ha personalizado parte de los ajustes del perfil.\n"
+"¿Desea descartar los cambios o guardarlos?"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/DiscardOrKeepProfileChangesDialog.qml:110
+msgctxt "@title:column"
+msgid "Profile settings"
+msgstr "Ajustes del perfil"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/DiscardOrKeepProfileChangesDialog.qml:117
+msgctxt "@title:column"
+msgid "Default"
+msgstr "Valor predeterminado"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/DiscardOrKeepProfileChangesDialog.qml:124
+msgctxt "@title:column"
+msgid "Customized"
+msgstr "Valor personalizado"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/DiscardOrKeepProfileChangesDialog.qml:158
+msgctxt "@option:discardOrKeep"
+msgid "Discard and never ask again"
+msgstr "Descartar y no volver a preguntar"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/DiscardOrKeepProfileChangesDialog.qml:159
+msgctxt "@option:discardOrKeep"
+msgid "Keep and never ask again"
+msgstr "Guardar y no volver a preguntar"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/DiscardOrKeepProfileChangesDialog.qml:196
+msgctxt "@action:button"
+msgid "Discard"
+msgstr "Descartar"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/DiscardOrKeepProfileChangesDialog.qml:209
+msgctxt "@action:button"
+msgid "Keep"
+msgstr "Guardar"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/DiscardOrKeepProfileChangesDialog.qml:222
+msgctxt "@action:button"
+msgid "Create New Profile"
+msgstr "Crear nuevo perfil"
+
+#: /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
+msgctxt "@label"
+msgid "version: %1"
+msgstr "versión: %1"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:71
+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
+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 ""
+"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
+msgctxt "@label"
+msgid "Graphical user interface"
+msgstr "Interfaz gráfica de usuario (GUI)"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:135
+msgctxt "@label"
+msgid "Application framework"
+msgstr "Entorno de la aplicación"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:136
+msgctxt "@label"
+msgid "G-code generator"
+msgstr "Generador de GCode"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:137
+msgctxt "@label"
+msgid "Interprocess communication library"
+msgstr "Biblioteca de comunicación entre procesos"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:139
+msgctxt "@label"
+msgid "Programming language"
+msgstr "Lenguaje de programación"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:140
+msgctxt "@label"
+msgid "GUI framework"
+msgstr "Entorno de la GUI"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:141
+msgctxt "@label"
+msgid "GUI framework bindings"
+msgstr "Enlaces del entorno de la GUI"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:142
+msgctxt "@label"
+msgid "C/C++ Binding library"
+msgstr "Biblioteca de enlaces C/C++"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:143
+msgctxt "@label"
+msgid "Data interchange format"
+msgstr "Formato de intercambio de datos"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:144
+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
+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
+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
+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
+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
+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
+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
+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
+msgctxt "@label"
+msgid "Serial communication library"
+msgstr "Biblioteca de comunicación en serie"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:153
+msgctxt "@label"
+msgid "ZeroConf discovery library"
+msgstr "Biblioteca de detección para Zeroconf"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:154
+msgctxt "@label"
+msgid "Polygon clipping library"
+msgstr "Biblioteca de recorte de polígonos"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:155
+msgctxt "@Label"
+msgid "Python HTTP library"
+msgstr "Biblioteca HTTP de Python"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:157
+msgctxt "@label"
+msgid "Font"
+msgstr "Fuente"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:158
+msgctxt "@label"
+msgid "SVG icons"
+msgstr "Iconos SVG"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:159
+msgctxt "@label"
+msgid "Linux cross-distribution application deployment"
+msgstr "Implementación de la aplicación de distribución múltiple de Linux"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/OpenFilesIncludingProjectsDialog.qml:64
+msgctxt "@text:window"
+msgid "We have found one or more project file(s) within the files you have selected. You can open only one project file at a time. We suggest to only import models from those files. Would you like to proceed?"
+msgstr "Hemos encontrado uno o más archivos del proyecto entre los archivos que ha seleccionado. Solo puede abrir los archivos de proyecto de uno en uno. Le recomendamos que solo importe modelos de esos archivos. ¿Desea continuar?"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/OpenFilesIncludingProjectsDialog.qml:99
+msgctxt "@action:button"
+msgid "Import all as models"
+msgstr "Importar todos como modelos"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:15
+msgctxt "@title:window"
+msgid "Save Project"
+msgstr "Guardar proyecto"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:149
+msgctxt "@action:label"
+msgid "Build plate"
+msgstr "Placa de impresión"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:183
+msgctxt "@action:label"
+msgid "Extruder %1"
+msgstr "Extrusor %1"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:198
+msgctxt "@action:label"
+msgid "%1 & material"
+msgstr "%1 y material"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:200
+msgctxt "@action:label"
+msgid "Material"
+msgstr "Material"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:272
+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:291
+msgctxt "@action:button"
+msgid "Save"
+msgstr "Guardar"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AskOpenAsProjectOrModelsDialog.qml:20
msgctxt "@title:window"
msgid "Open project file"
msgstr "Abrir archivo de proyecto"
-#: /home/ruben/Projects/Cura/resources/qml/AskOpenAsProjectOrModelsDialog.qml:93
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AskOpenAsProjectOrModelsDialog.qml:93
msgctxt "@text:window"
msgid "This is a Cura project file. Would you like to open it as a project or import the models from it?"
msgstr "Este es un archivo de proyecto Cura. ¿Le gustaría abrirlo como un proyecto o importar sus modelos?"
-#: /home/ruben/Projects/Cura/resources/qml/AskOpenAsProjectOrModelsDialog.qml:103
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AskOpenAsProjectOrModelsDialog.qml:103
msgctxt "@text:window"
msgid "Remember my choice"
msgstr "Recordar mi selección"
-#: /home/ruben/Projects/Cura/resources/qml/AskOpenAsProjectOrModelsDialog.qml:122
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AskOpenAsProjectOrModelsDialog.qml:122
msgctxt "@action:button"
msgid "Open as project"
msgstr "Abrir como proyecto"
-#: /home/ruben/Projects/Cura/resources/qml/AskOpenAsProjectOrModelsDialog.qml:131
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AskOpenAsProjectOrModelsDialog.qml:131
msgctxt "@action:button"
msgid "Import models"
msgstr "Importar modelos"
-#: /home/ruben/Projects/Cura/resources/qml/EngineLog.qml:15
-msgctxt "@title:window"
-msgid "Engine Log"
-msgstr "Registro del motor"
-
-#: /home/ruben/Projects/Cura/resources/qml/SidebarHeader.qml:70
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/DropDownWidget.qml:93
msgctxt "@label"
-msgid "Printer type"
-msgstr "Tipo de impresora"
+msgid "Empty"
+msgstr "Vacío"
-#: /home/ruben/Projects/Cura/resources/qml/SidebarHeader.qml:376
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddNetworkOrLocalPrinterContent.qml:24
msgctxt "@label"
-msgid "Material"
-msgstr "Material"
+msgid "Add a printer"
+msgstr "Agregar una impresora"
-#: /home/ruben/Projects/Cura/resources/qml/SidebarHeader.qml:543
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddNetworkOrLocalPrinterContent.qml:39
msgctxt "@label"
-msgid "Use glue with this material combination"
-msgstr "Utilizar pegamento con esta combinación de materiales"
+msgid "Add a networked printer"
+msgstr "Agregar una impresora en red"
-#: /home/ruben/Projects/Cura/resources/qml/SidebarHeader.qml:575
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddNetworkOrLocalPrinterContent.qml:81
msgctxt "@label"
-msgid "Check compatibility"
-msgstr "Comprobar compatibilidad"
+msgid "Add a non-networked printer"
+msgstr "Agregar una impresora fuera de red"
-#: /home/ruben/Projects/Cura/resources/qml/SidebarHeader.qml:593
-msgctxt "@tooltip"
-msgid "Click to check the material compatibility on Ultimaker.com."
-msgstr "Haga clic para comprobar la compatibilidad de los materiales en Utimaker.com."
+#: /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/ObjectsList.qml:211
-msgctxt "@option:check"
-msgid "See only current build plate"
-msgstr "Ver solo placa de impresión actual"
+#: /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/ObjectsList.qml:227
-msgctxt "@action:button"
-msgid "Arrange to all build plates"
-msgstr "Organizar todas las placas de impresión"
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddPrinterByIpContent.qml:158
+msgctxt "@button"
+msgid "Add"
+msgstr "Agregar"
-#: /home/ruben/Projects/Cura/resources/qml/ObjectsList.qml:247
-msgctxt "@action:button"
-msgid "Arrange current build plate"
-msgstr "Organizar placa de impresión actual"
+#: /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:207
+msgctxt "@label"
+msgid "Printer name"
+msgstr "Nombre de la impresora"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddLocalPrinterScrollView.qml:220
+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"
#: MachineSettingsAction/plugin.json
msgctxt "description"
@@ -4547,26 +5128,36 @@ msgctxt "name"
msgid "God Mode"
msgstr "God Mode"
-#: ChangeLogPlugin/plugin.json
+#: FirmwareUpdater/plugin.json
msgctxt "description"
-msgid "Shows changes since latest checked version."
-msgstr "Muestra los cambios desde la última versión comprobada."
+msgid "Provides a machine actions for updating firmware."
+msgstr "Proporciona opciones a la máquina para actualizar el firmware."
-#: ChangeLogPlugin/plugin.json
+#: FirmwareUpdater/plugin.json
msgctxt "name"
-msgid "Changelog"
-msgstr "Registro de cambios"
+msgid "Firmware Updater"
+msgstr "Actualizador de firmware"
#: ProfileFlattener/plugin.json
msgctxt "description"
-msgid "Create a flattend quality changes profile."
+msgid "Create a flattened quality changes profile."
msgstr "Crear un perfil de cambios de calidad aplanado."
#: ProfileFlattener/plugin.json
msgctxt "name"
-msgid "Profile flatener"
+msgid "Profile Flattener"
msgstr "Aplanador de perfil"
+#: 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."
@@ -4577,26 +5168,6 @@ msgctxt "name"
msgid "USB printing"
msgstr "Impresión USB"
-#: UserAgreement/plugin.json
-msgctxt "description"
-msgid "Ask the user once if he/she agrees with our license."
-msgstr "Preguntar al usuario una vez si acepta la licencia."
-
-#: UserAgreement/plugin.json
-msgctxt "name"
-msgid "UserAgreement"
-msgstr "UserAgreement"
-
-#: X3GWriter/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)."
-
-#: X3GWriter/plugin.json
-msgctxt "name"
-msgid "X3GWriter"
-msgstr "X3GWriter"
-
#: GCodeGzWriter/plugin.json
msgctxt "description"
msgid "Writes g-code to a compressed archive."
@@ -4647,6 +5218,16 @@ msgctxt "name"
msgid "UM3 Network Connection"
msgstr "Conexión de red UM3"
+#: SettingsGuide/plugin.json
+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."
+
+#: SettingsGuide/plugin.json
+msgctxt "name"
+msgid "Settings Guide"
+msgstr "Guía de ajustes"
+
#: MonitorStage/plugin.json
msgctxt "description"
msgid "Provides a monitor stage in Cura."
@@ -4707,6 +5288,16 @@ 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."
@@ -4787,6 +5378,16 @@ 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."
@@ -4797,6 +5398,16 @@ 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."
@@ -4807,6 +5418,16 @@ 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."
@@ -4897,6 +5518,16 @@ 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."
@@ -4927,6 +5558,16 @@ 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.)."
@@ -4947,6 +5588,733 @@ msgctxt "name"
msgid "Cura Profile Reader"
msgstr "Lector de perfiles de Cura"
+#~ 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"
+
+#~ msgctxt "@info:status"
+#~ msgid "Nothing to slice because none of the models fit the build volume. Please scale or rotate models to fit."
+#~ msgstr "No hay nada que segmentar porque ninguno de los modelos se adapta al volumen de impresión. Escale o rote los modelos para que se adapten."
+
+#~ msgctxt "@info:status"
+#~ msgid "The selected material is incompatible with the selected machine or configuration."
+#~ msgstr "El material seleccionado no es compatible con la máquina o la configuración seleccionada."
+
+#~ msgctxt "@info:title"
+#~ msgid "Incompatible Material"
+#~ msgstr "Material incompatible"
+
+#~ msgctxt "@info:status Don't translate the XML tags or !"
+#~ msgid "Failed to import profile from {0}: {1}"
+#~ msgstr "Error al importar el perfil de {0}: {1}"
+
+#~ msgctxt "@title"
+#~ msgid "Toolbox"
+#~ msgstr "Cuadro de herramientas"
+
+#~ msgctxt "@label"
+#~ msgid "Not available"
+#~ msgstr "No disponible"
+
+#~ msgctxt "@label"
+#~ msgid "Unreachable"
+#~ msgstr "No se puede conectar"
+
+#~ msgctxt "@label"
+#~ msgid "Available"
+#~ msgstr "Disponible"
+
+#~ msgctxt "@label:status"
+#~ msgid "Preparing"
+#~ msgstr "Preparando"
+
+#~ msgctxt "@label:status"
+#~ msgid "Pausing"
+#~ msgstr "Pausando"
+
+#~ msgctxt "@label:status"
+#~ msgid "Resuming"
+#~ msgstr "Reanudando"
+
+#~ msgctxt "@label"
+#~ msgid "Waiting for: Unavailable printer"
+#~ msgstr "Esperando: impresora no disponible"
+
+#~ msgctxt "@label"
+#~ msgid "Waiting for: First available"
+#~ msgstr "Esperando: primera disponible"
+
+#~ msgctxt "@label"
+#~ msgid "Waiting for: "
+#~ msgstr "Esperando: "
+
+#~ msgctxt "@label"
+#~ msgid "Configuration change"
+#~ msgstr "Cambio de configuración"
+
+#~ msgctxt "@label"
+#~ msgid "The assigned printer, %1, requires the following configuration change(s):"
+#~ msgstr "Es necesario modificar la siguiente configuración de la impresora asignada %1:"
+
+#~ msgctxt "@label"
+#~ msgid "Override"
+#~ msgstr "Anular"
+
+#~ msgctxt "@label"
+#~ msgid "Starting a print job with an incompatible configuration could damage your 3D printer. Are you sure you want to override the configuration and print %1?"
+#~ msgstr "Iniciar un trabajo de impresión con una configuración no compatible puede causar daños en su impresora 3D. ¿Seguro de que desea sobrescribir la configuración e imprimir %1?"
+
+#~ msgctxt "@window:title"
+#~ msgid "Override configuration configuration and start print"
+#~ msgstr "Sobrescribir la configuración e iniciar la impresión"
+
+#~ msgctxt "@label link to connect manager"
+#~ msgid "Manage queue"
+#~ msgstr "Administrar cola"
+
+#~ msgctxt "@label"
+#~ msgid "Printing"
+#~ msgstr "Imprimiendo"
+
+#~ msgctxt "@label link to connect manager"
+#~ msgid "Manage printers"
+#~ msgstr "Administrar impresoras"
+
+#~ msgctxt "@action:button"
+#~ msgid "Activate Configuration"
+#~ msgstr "Activar configuración"
+
+#~ msgctxt "@info:tooltip"
+#~ msgid "Load the configuration of the printer into Cura"
+#~ msgstr "Carga la configuración de la impresora en Cura"
+
+#~ msgctxt "@label"
+#~ msgid "Show Travels"
+#~ msgstr "Mostrar desplazamientos"
+
+#~ msgctxt "@label"
+#~ msgid "Show Helpers"
+#~ msgstr "Mostrar asistentes"
+
+#~ msgctxt "@label"
+#~ msgid "Show Shell"
+#~ msgstr "Mostrar perímetro"
+
+#~ msgctxt "@label"
+#~ msgid "Show Infill"
+#~ msgstr "Mostrar relleno"
+
+#~ msgctxt "@text:window"
+#~ msgid "I don't want to send these data"
+#~ msgstr "No quiero enviar estos datos"
+
+#~ msgctxt "@text:window"
+#~ msgid "Allow sending these data to Ultimaker and help us improve Cura"
+#~ msgstr "Permita enviar estos datos a Ultimaker y ayúdenos a mejorar Cura"
+
+#~ msgctxt "@label"
+#~ msgid "Printer type:"
+#~ msgstr "Tipo de impresora:"
+
+#~ msgctxt "@label"
+#~ msgid "Connection:"
+#~ msgstr "Conexión:"
+
+#~ msgctxt "@label"
+#~ msgid "State:"
+#~ msgstr "Estado:"
+
+#~ msgctxt "@label:MonitorStatus"
+#~ msgid "Waiting for a printjob"
+#~ msgstr "Esperando un trabajo de impresión"
+
+#~ msgctxt "@label:MonitorStatus"
+#~ msgid "Waiting for someone to clear the build plate"
+#~ msgstr "Esperando a que alguien limpie la placa de impresión"
+
+#~ msgctxt "@label:MonitorStatus"
+#~ msgid "Aborting print..."
+#~ msgstr "Cancelando impresión..."
+
+#~ msgctxt "@label"
+#~ msgid "Protected profiles"
+#~ msgstr "Perfiles protegidos"
+
+#~ msgctxt "@label"
+#~ msgid "Printer Name:"
+#~ msgstr "Nombre de la impresora:"
+
+#~ msgctxt "@label"
+#~ msgid "Profile:"
+#~ msgstr "Perfil:"
+
+#~ msgctxt "@label:textbox"
+#~ msgid "Search..."
+#~ msgstr "Buscar..."
+
+#~ msgctxt "@action:inmenu"
+#~ msgid "Collapse All"
+#~ msgstr "Contraer todo"
+
+#~ msgctxt "@action:inmenu"
+#~ msgid "Expand All"
+#~ msgstr "Ampliar todo"
+
+#~ msgctxt "@label:header configurations"
+#~ msgid "Available configurations"
+#~ msgstr "Configuraciones disponibles"
+
+#~ msgctxt "@label:extruder label"
+#~ msgid "Extruder"
+#~ msgstr "Extrusor"
+
+#~ msgctxt "@label:extruder label"
+#~ msgid "Yes"
+#~ msgstr "Sí"
+
+#~ msgctxt "@label:extruder label"
+#~ msgid "No"
+#~ msgstr "No"
+
+#~ msgctxt "@label:listbox"
+#~ msgid "Print Setup"
+#~ msgstr "Configuración de impresión"
+
+#~ msgctxt "@label:listbox"
+#~ msgid ""
+#~ "Print Setup disabled\n"
+#~ "G-code files cannot be modified"
+#~ msgstr ""
+#~ "Ajustes de impresión deshabilitados\n"
+#~ "No se pueden modificar los archivos GCode"
+
+#~ msgctxt "@label Hours and minutes"
+#~ msgid "00h 00min"
+#~ msgstr "00 h 00 min"
+
+#~ msgctxt "@tooltip"
+#~ msgid "Time specification"
+#~ msgstr "Especificación de tiempos"
+
+#~ msgctxt "@label"
+#~ msgid "Cost specification"
+#~ msgstr "Especificación de costes"
+
+#~ msgctxt "@label"
+#~ msgid "Total:"
+#~ msgstr "Total:"
+
+#~ msgctxt "@tooltip"
+#~ msgid "Recommended Print Setup
Print with the recommended settings for the selected printer, material and quality."
+#~ msgstr "Configuración de impresión recomendada
Imprimir con los ajustes recomendados para la impresora, el material y la calidad seleccionados."
+
+#~ msgctxt "@tooltip"
+#~ msgid "Custom Print Setup
Print with finegrained control over every last bit of the slicing process."
+#~ msgstr "Configuración de impresión personalizada
Imprimir con un control muy detallado del proceso de segmentación."
+
+#~ msgctxt "@action:inmenu menubar:help"
+#~ msgid "Show Engine &Log..."
+#~ msgstr "&Mostrar registro del motor..."
+
+#~ msgctxt "@action:menu"
+#~ msgid "Browse packages..."
+#~ msgstr "Examinar paquetes..."
+
+#~ msgctxt "@action:inmenu menubar:view"
+#~ msgid "Expand/Collapse Sidebar"
+#~ msgstr "Expandir/contraer barra lateral"
+
+#~ msgctxt "@label:PrintjobStatus"
+#~ msgid "Please load a 3D model"
+#~ msgstr "Cargue un modelo en 3D"
+
+#~ msgctxt "@label:PrintjobStatus"
+#~ msgid "Ready to slice"
+#~ msgstr "Preparado para segmentar"
+
+#~ msgctxt "@label:PrintjobStatus %1 is target operation"
+#~ msgid "Ready to %1"
+#~ msgstr "Listo para %1"
+
+#~ msgctxt "@label:PrintjobStatus"
+#~ msgid "Slicing unavailable"
+#~ msgstr "No se puede segmentar"
+
+#~ msgctxt "@info:tooltip"
+#~ msgid "Slice current printjob"
+#~ msgstr "Fragmentar trabajo de impresión actual"
+
+#~ msgctxt "@info:tooltip"
+#~ msgid "Cancel slicing process"
+#~ msgstr "Cancelar proceso de fragmentación"
+
+#~ msgctxt "@label:Printjob"
+#~ msgid "Prepare"
+#~ msgstr "Preparar"
+
+#~ msgctxt "@label:Printjob"
+#~ msgid "Cancel"
+#~ msgstr "Cancelar"
+
+#~ msgctxt "@info:tooltip"
+#~ msgid "Select the active output device"
+#~ msgstr "Seleccione el dispositivo de salida activo"
+
+#~ msgctxt "@title:menu"
+#~ msgid "&View"
+#~ msgstr "&Ver"
+
+#~ msgctxt "@title:menu"
+#~ msgid "&Settings"
+#~ msgstr "A&justes"
+
+#~ msgctxt "@title:menu menubar:toplevel"
+#~ msgid "&Toolbox"
+#~ msgstr "&Cuadro de herramientas"
+
+#~ msgctxt "@action:button"
+#~ msgid "Open File"
+#~ msgstr "Abrir archivo"
+
+#~ msgctxt "@tooltip"
+#~ msgid "This quality profile is not available for you current material and nozzle configuration. Please change these to enable this quality profile"
+#~ msgstr "Este perfil de calidad no está disponible para la configuración de material y de tobera actual. Cámbiela para poder habilitar este perfil de calidad"
+
+#~ msgctxt "@label"
+#~ msgid "Print Speed"
+#~ msgstr "Velocidad de impresión"
+
+#~ msgctxt "@label"
+#~ msgid "Slower"
+#~ msgstr "Más lento"
+
+#~ msgctxt "@label"
+#~ msgid "Faster"
+#~ msgstr "Más rápido"
+
+#~ msgctxt "@label"
+#~ msgid "Enable gradual"
+#~ msgstr "Habilitar gradual"
+
+#~ msgctxt "@label"
+#~ msgid "Generate Support"
+#~ msgstr "Generar soporte"
+
+#~ msgctxt "@label"
+#~ msgid "Build Plate Adhesion"
+#~ msgstr "Adherencia de la placa de impresión"
+
+#~ msgctxt "@label"
+#~ msgid "Need help improving your prints? Read the Ultimaker Troubleshooting Guides"
+#~ msgstr "¿Necesita ayuda para mejorar sus impresiones? Lea las Guías de solución de problemas de Ultimaker"
+
+#~ msgctxt "@title:window"
+#~ msgid "Engine Log"
+#~ msgstr "Registro del motor"
+
+#~ msgctxt "@label"
+#~ msgid "Printer type"
+#~ msgstr "Tipo de impresora"
+
+#~ msgctxt "@label"
+#~ msgid "Use glue with this material combination"
+#~ msgstr "Utilizar pegamento con esta combinación de materiales"
+
+#~ msgctxt "@label"
+#~ msgid "Check compatibility"
+#~ msgstr "Comprobar compatibilidad"
+
+#~ msgctxt "@tooltip"
+#~ 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 "Shows changes since latest checked version."
+#~ msgstr "Muestra los cambios desde la última versión comprobada."
+
+#~ msgctxt "name"
+#~ msgid "Changelog"
+#~ msgstr "Registro de cambios"
+
+#~ msgctxt "description"
+#~ msgid "Create a flattend quality changes profile."
+#~ msgstr "Crear un perfil de cambios de calidad aplanado."
+
+#~ msgctxt "name"
+#~ msgid "Profile flatener"
+#~ msgstr "Aplanador de perfil"
+
+#~ msgctxt "description"
+#~ msgid "Ask the user once if he/she agrees with our license."
+#~ msgstr "Preguntar al usuario una vez si acepta la licencia."
+
+#~ msgctxt "name"
+#~ msgid "UserAgreement"
+#~ msgstr "UserAgreement"
+
+#~ msgctxt "@warning:status"
+#~ msgid "Please generate G-code before saving."
+#~ msgstr "Genere un G-code antes de guardar."
+
+#~ msgctxt "@action"
+#~ msgid "Upgrade Firmware"
+#~ msgstr "Actualizar firmware"
+
+#~ msgctxt "@label unknown material"
+#~ msgid "Unknown"
+#~ msgstr "Desconocido"
+
+#~ msgctxt "@info:status Don't translate the XML tags or !"
+#~ msgid "No custom profile to import in file {0}"
+#~ msgstr "No hay ningún perfil personalizado que importar en el archivo {0}"
+
+#~ msgctxt "@info:status Don't translate the XML tags or !"
+#~ msgid "This profile {0} contains incorrect data, could not import it."
+#~ msgstr "Este perfil {0} contiene datos incorrectos, no se han podido importar."
+
+#~ msgctxt "@info:status Don't translate the XML tags or !"
+#~ 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 "@title:window"
+#~ msgid "Confirm uninstall "
+#~ msgstr "Confirmar desinstalación "
+
+#~ msgctxt "@label Print estimates: m for meters, g for grams, %4 is currency and %3 is print cost"
+#~ msgid "%1m / ~ %2g / ~ %4 %3"
+#~ msgstr "%1 m/~ %2 g/~ %4 %3"
+
+#~ msgctxt "@label Print estimates: m for meters, g for grams"
+#~ msgid "%1m / ~ %2g"
+#~ msgstr "%1 m/~ %2 g"
+
+#~ msgctxt "@title"
+#~ msgid "Upgrade Firmware"
+#~ msgstr "Actualización de firmware"
+
#~ msgctxt "@action:button"
#~ msgid "Print with Doodle3D WiFi-Box"
#~ msgstr "Imprimir con un enrutador Doodle3D"
@@ -5039,10 +6407,6 @@ msgstr "Lector de perfiles de Cura"
#~ msgid "Lost connection with the printer"
#~ msgstr "Se ha perdido la conexión con la impresora."
-#~ msgctxt "@label:status"
-#~ msgid "Unavailable"
-#~ msgstr "No disponible"
-
#~ msgctxt "@label:status"
#~ msgid "Unknown"
#~ msgstr "Desconocido"
@@ -5369,7 +6733,7 @@ msgstr "Lector de perfiles de Cura"
#~ 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"
@@ -5461,7 +6825,7 @@ msgstr "Lector de perfiles de Cura"
#~ 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 ec191c5271..2183670518 100644
--- a/resources/i18n/es_ES/fdmextruder.def.json.po
+++ b/resources/i18n/es_ES/fdmextruder.def.json.po
@@ -1,14 +1,14 @@
# Cura
-# Copyright (C) 2018 Ultimaker
+# Copyright (C) 2019 Ultimaker B.V.
# This file is distributed under the same license as the Cura package.
-# Ruben Dulek , 2018.
+# Ruben Dulek , 2019.
#
msgid ""
msgstr ""
-"Project-Id-Version: Cura 3.5\n"
+"Project-Id-Version: Cura 4.2\n"
"Report-Msgid-Bugs-To: r.dulek@ultimaker.com\n"
-"POT-Creation-Date: 2018-09-19 17:07+0000\n"
-"PO-Revision-Date: 2018-09-28 14:25+0100\n"
+"POT-Creation-Date: 2019-07-16 14:38+0000\n"
+"PO-Revision-Date: 2019-03-13 14:00+0200\n"
"Last-Translator: Bothof \n"
"Language-Team: Spanish\n"
"Language: es_ES\n"
@@ -83,8 +83,8 @@ msgstr "GCode inicial del extrusor"
#: fdmextruder.def.json
msgctxt "machine_extruder_start_code description"
-msgid "Start g-code to execute whenever turning the extruder on."
-msgstr "Gcode inicial que se ejecuta cada vez que se enciende el extrusor."
+msgid "Start g-code to execute when switching to this extruder."
+msgstr "Iniciar GCode para ejecutarlo al cambiar a este extrusor."
#: fdmextruder.def.json
msgctxt "machine_extruder_start_pos_abs label"
@@ -123,8 +123,8 @@ msgstr "GCode final del extrusor"
#: fdmextruder.def.json
msgctxt "machine_extruder_end_code description"
-msgid "End g-code to execute whenever turning the extruder off."
-msgstr "Gcode final que se ejecuta cada vez que se apaga el extrusor."
+msgid "End g-code to execute when switching away from this extruder."
+msgstr "Finalizar GCode para ejecutarlo al cambiar desde este extrusor."
#: fdmextruder.def.json
msgctxt "machine_extruder_end_pos_abs label"
@@ -166,6 +166,16 @@ msgctxt "extruder_prime_pos_z description"
msgid "The Z coordinate of the position where the nozzle primes at the start of printing."
msgstr "Coordenada Z de la posición en la que la tobera queda preparada al inicio de la impresión."
+#: fdmextruder.def.json
+msgctxt "machine_extruder_cooling_fan_number label"
+msgid "Extruder Print Cooling Fan"
+msgstr "Ventilador de refrigeración de impresión del extrusor"
+
+#: fdmextruder.def.json
+msgctxt "machine_extruder_cooling_fan_number description"
+msgid "The number of the print cooling fan associated with this extruder. Only change this from the default value of 0 when you have a different print cooling fan for each extruder."
+msgstr "Número del ventilador de refrigeración de impresión asociado al extrusor. Modifique el valor predeterminado 0 solo cuando disponga de un ventilador de refrigeración de impresión diferente para cada extrusor."
+
#: fdmextruder.def.json
msgctxt "platform_adhesion label"
msgid "Build Plate Adhesion"
@@ -215,3 +225,11 @@ msgstr "Diámetro"
msgctxt "material_diameter description"
msgid "Adjusts the diameter of the filament used. Match this value with the diameter of the used filament."
msgstr "Ajusta el diámetro del filamento utilizado. Este valor debe coincidir con el diámetro del filamento utilizado."
+
+#~ msgctxt "machine_extruder_start_code description"
+#~ msgid "Start g-code to execute whenever turning the extruder on."
+#~ msgstr "Gcode inicial que se ejecuta cada vez que se enciende el extrusor."
+
+#~ msgctxt "machine_extruder_end_code description"
+#~ msgid "End g-code to execute whenever turning the extruder off."
+#~ msgstr "Gcode final que se ejecuta cada vez que se apaga el extrusor."
diff --git a/resources/i18n/es_ES/fdmprinter.def.json.po b/resources/i18n/es_ES/fdmprinter.def.json.po
index 99135813b2..1241f4b2c5 100644
--- a/resources/i18n/es_ES/fdmprinter.def.json.po
+++ b/resources/i18n/es_ES/fdmprinter.def.json.po
@@ -1,21 +1,21 @@
# Cura
-# Copyright (C) 2018 Ultimaker
+# Copyright (C) 2019 Ultimaker B.V.
# This file is distributed under the same license as the Cura package.
-# Ruben Dulek , 2018.
+# Ruben Dulek , 2019.
#
msgid ""
msgstr ""
-"Project-Id-Version: Cura 3.5\n"
+"Project-Id-Version: Cura 4.2\n"
"Report-Msgid-Bugs-To: r.dulek@ultimaker.com\n"
-"POT-Creation-Date: 2018-09-19 17:07+0000\n"
-"PO-Revision-Date: 2018-09-28 14:56+0200\n"
-"Last-Translator: Bothof \n"
-"Language-Team: Spanish\n"
+"POT-Creation-Date: 2019-07-16 14:38+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"
@@ -237,7 +237,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 +247,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 +257,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 +267,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 +277,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 +307,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 +317,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 +337,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 +402,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 +422,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 +432,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 +442,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 +472,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
@@ -1077,8 +1077,8 @@ msgstr "Conectar polígonos superiores/inferiores"
#: fdmprinter.def.json
msgctxt "connect_skin_polygons description"
-msgid "Connect top/bottom skin paths where they run next to each other. For the concentric pattern enabling this setting greatly reduces the travel time, but because the connections can happend midway over infill this feature can reduce the top surface quality."
-msgstr "Conectar las trayectorias de forro superior/inferior cuando están próximas entre sí. Al habilitar este ajuste, en el patrón concéntrico se reduce considerablemente el tiempo de desplazamiento, pero las conexiones pueden producirse en mitad del relleno, con lo que la bajaría la calidad de la superficie superior."
+msgid "Connect top/bottom skin paths where they run next to each other. For the concentric pattern enabling this setting greatly reduces the travel time, but because the connections can happen midway over infill this feature can reduce the top surface quality."
+msgstr "Conecta las trayectorias de forro superior/inferior cuando están próximas entre sí. Al habilitar este ajuste, en el patrón concéntrico se reduce considerablemente el tiempo de desplazamiento, pero las conexiones pueden producirse en mitad del relleno, con lo que bajaría la calidad de la superficie superior."
#: fdmprinter.def.json
msgctxt "skin_angles label"
@@ -1297,8 +1297,12 @@ 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 +1324,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 +1341,15 @@ 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"
@@ -1497,8 +1508,8 @@ msgstr "Patrón de relleno"
#: fdmprinter.def.json
msgctxt "infill_pattern description"
-msgid "The pattern of the infill material of the print. The line and zig zag infill swap direction on alternate layers, reducing material cost. The grid, triangle, tri-hexagon, cubic, octet, quarter cubic, cross and concentric patterns are fully printed every layer. Cubic, quarter cubic and octet infill change with every layer to provide a more equal distribution of strength over each direction."
-msgstr "Patrón del material de relleno de la impresión. El relleno de línea y zigzag cambia de dirección en capas alternas, con lo que se reduce el coste del material. Los patrones de rejilla, triángulo, trihexagonal, cúbico, de octeto, cúbico bitruncado y transversal y concéntrico se imprimen en todas las capas por completo. El relleno cúbico, cúbico bitruncado y de octeto cambian en cada capa para proporcionar una distribución de fuerza equitativa en cada dirección."
+msgid "The pattern of the infill material of the print. The line and zig zag infill swap direction on alternate layers, reducing material cost. The grid, triangle, tri-hexagon, cubic, octet, quarter cubic, cross and concentric patterns are fully printed every layer. Gyroid, cubic, quarter cubic and octet infill change with every layer to provide a more equal distribution of strength over each direction."
+msgstr "Patrón del material de relleno de la impresión. El relleno de línea y zigzag cambia de dirección en capas alternas, con lo que se reduce el coste de material. Los patrones de rejilla, triángulo, trihexágono, cubo, octeto, cubo bitruncado, transversal y concéntrico se imprimen en todas las capas por completo. El relleno giroide, cúbico, cúbico bitruncado y de octeto cambian en cada capa para proporcionar una distribución de fuerza equitativa en cada dirección."
#: fdmprinter.def.json
msgctxt "infill_pattern option grid"
@@ -1560,6 +1571,11 @@ msgctxt "infill_pattern option cross_3d"
msgid "Cross 3D"
msgstr "Cruz 3D"
+#: fdmprinter.def.json
+msgctxt "infill_pattern option gyroid"
+msgid "Gyroid"
+msgstr "Giroide"
+
#: fdmprinter.def.json
msgctxt "zig_zaggify_infill label"
msgid "Connect Infill Lines"
@@ -1603,7 +1619,7 @@ msgstr "El patrón de relleno se mueve esta distancia a lo largo del eje X."
#: fdmprinter.def.json
msgctxt "infill_offset_y label"
msgid "Infill Y Offset"
-msgstr "Desplazamiento del relleno sobre el eje X"
+msgstr "Desplazamiento del relleno sobre el eje Y"
#: fdmprinter.def.json
msgctxt "infill_offset_y description"
@@ -1671,8 +1687,8 @@ msgstr "Porcentaje de superposición del forro"
#: fdmprinter.def.json
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."
+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"
@@ -1681,8 +1697,8 @@ msgstr "Superposición del forro"
#: fdmprinter.def.json
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 "Cantidad de superposición entre el forro y las paredes. Una ligera superposición permite que las paredes conecten firmemente con el forro."
+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_wipe_dist label"
@@ -1864,6 +1880,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"
@@ -1974,6 +2000,87 @@ 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"
@@ -1984,6 +2091,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"
@@ -2101,8 +2328,9 @@ 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."
-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."
+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
msgctxt "material_standby_temperature label"
@@ -2121,8 +2349,8 @@ msgstr "Distancia de retracción del cambio de tobera"
#: fdmprinter.def.json
msgctxt "switch_extruder_retraction_amount description"
-msgid "The amount of retraction: Set at 0 for no retraction at all. This should generally be the same as the length of the heat zone."
-msgstr "Distancia de la retracción: utilice el valor cero para que no haya retracción. Por norma general, este valor debe ser igual a la longitud de la zona de calentamiento."
+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 "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"
@@ -2154,6 +2382,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"
@@ -2345,14 +2583,15 @@ 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"
@@ -2781,8 +3020,8 @@ 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 and also to only comb within the infill. Note that the 'Within Infill' option behaves exactly like the 'Not in Skin' option in earlier Cura releases."
-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 y además peinar solo en el relleno. La opción de «Sobre el relleno» actúa exactamente igual que la «No está en el forro» de las versiones de Cura anteriores."
+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 "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"
@@ -2924,6 +3163,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"
@@ -3194,6 +3443,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"
@@ -3264,6 +3518,36 @@ 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."
+#: fdmprinter.def.json
+msgctxt "support_brim_enable label"
+msgid "Enable Support Brim"
+msgstr "Habilitar borde de soporte"
+
+#: fdmprinter.def.json
+msgctxt "support_brim_enable description"
+msgid "Generate a brim within the support infill regions of the first layer. This brim is printed underneath the support, not around it. Enabling this setting increases the adhesion of support to the build plate."
+msgstr "Genera un borde dentro de las zonas de relleno del soporte de la primera capa. Este borde se imprime por debajo del soporte y no a su alrededor. Si habilita esta configuración aumentará la adhesión del soporte a la placa de impresión."
+
+#: fdmprinter.def.json
+msgctxt "support_brim_width label"
+msgid "Support Brim Width"
+msgstr "Ancho del borde de soporte"
+
+#: fdmprinter.def.json
+msgctxt "support_brim_width description"
+msgid "The width of the brim to print underneath the support. A larger brim enhances adhesion to the build plate, at the cost of some extra material."
+msgstr "Anchura del borde de impresión que se imprime por debajo del soporte. Una anchura de soporte amplia mejora la adhesión a la placa de impresión, pero requieren material adicional."
+
+#: fdmprinter.def.json
+msgctxt "support_brim_line_count label"
+msgid "Support Brim Line Count"
+msgstr "Recuento de líneas del borde de soporte"
+
+#: fdmprinter.def.json
+msgctxt "support_brim_line_count description"
+msgid "The number of lines used for the support brim. More brim lines enhance adhesion to the build plate, at the cost of some extra material."
+msgstr "Número de líneas utilizadas para el borde de soporte. Más líneas de borde mejoran la adhesión a la placa de impresión, pero requieren material adicional."
+
#: fdmprinter.def.json
msgctxt "support_z_distance label"
msgid "Support Z Distance"
@@ -3361,8 +3645,9 @@ 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"
@@ -3404,6 +3689,16 @@ msgctxt "gradual_support_infill_step_height description"
msgid "The height of support infill of a given density before switching to half the density."
msgstr "Altura del relleno de soporte de una determinada densidad antes de cambiar a la mitad de la densidad."
+#: fdmprinter.def.json
+msgctxt "minimum_support_area label"
+msgid "Minimum Support Area"
+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 "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"
msgid "Enable Support Interface"
@@ -3629,6 +3924,66 @@ msgctxt "support_bottom_pattern option zigzag"
msgid "Zig Zag"
msgstr "Zigzag"
+#: fdmprinter.def.json
+msgctxt "minimum_interface_area label"
+msgid "Minimum Support Interface Area"
+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 "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."
+
+#: fdmprinter.def.json
+msgctxt "minimum_roof_area label"
+msgid "Minimum Support Roof Area"
+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 "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."
+
+#: fdmprinter.def.json
+msgctxt "minimum_bottom_area label"
+msgid "Minimum Support Floor Area"
+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 "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."
+
+#: fdmprinter.def.json
+msgctxt "support_interface_offset label"
+msgid "Support Interface Horizontal Expansion"
+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 "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 "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 "Cantidad de desplazamiento aplicado a los techos del soporte."
+
+#: fdmprinter.def.json
+msgctxt "support_bottom_offset label"
+msgid "Support Floor Horizontal Expansion"
+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 "Cantidad de desplazamiento aplicado a los suelos del soporte."
+
#: fdmprinter.def.json
msgctxt "support_fan_enable label"
msgid "Fan Speed Override"
@@ -3670,14 +4025,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"
@@ -3833,6 +4188,16 @@ msgctxt "brim_line_count description"
msgid "The number of lines used for a brim. More brim lines enhance adhesion to the build plate, but also reduces the effective print area."
msgstr "Número de líneas utilizadas para un borde. Más líneas de borde mejoran la adhesión a la plataforma de impresión, pero también reducen el área de impresión efectiva."
+#: fdmprinter.def.json
+msgctxt "brim_replaces_support label"
+msgid "Brim Replaces Support"
+msgstr "Sustituir soporte por borde"
+
+#: fdmprinter.def.json
+msgctxt "brim_replaces_support description"
+msgid "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."
+msgstr "Aplica la impresión de un borde alrededor del modelo, aunque en esa posición debiera estar el soporte. Sustituye algunas áreas de la primera capa de soporte por áreas de borde."
+
#: fdmprinter.def.json
msgctxt "brim_outside_only label"
msgid "Brim Only on Outside"
@@ -4163,16 +4528,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"
@@ -4213,16 +4568,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"
@@ -4233,6 +4578,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"
@@ -4515,8 +4870,9 @@ 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"
@@ -4748,6 +5104,16 @@ 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."
+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."
+
#: fdmprinter.def.json
msgctxt "support_skip_some_zags label"
msgid "Break Up Support In Chunks"
@@ -5005,8 +5371,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"
@@ -5349,7 +5715,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
@@ -5359,7 +5725,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
@@ -5369,7 +5735,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
@@ -5379,7 +5745,7 @@ 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"
+msgid "Adaptive Layers Threshold"
msgstr "Umbral de las capas de adaptación"
#: fdmprinter.def.json
@@ -5597,6 +5963,156 @@ 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 "command_line_settings label"
msgid "Command Line Settings"
@@ -5657,6 +6173,162 @@ 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 "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."
+
+#~ 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 "Cantidad de superposición entre el forro y las paredes. Una ligera superposición permite que las paredes conecten firmemente con el forro."
+
+#~ msgctxt "switch_extruder_retraction_amount description"
+#~ msgid "The amount of retraction: Set at 0 for no retraction at all. This should generally be the same as the length of the heat zone."
+#~ msgstr "Distancia de la retracción: utilice el valor cero para que no haya retracción. Por norma general, este valor debe ser igual a la longitud de la zona de calentamiento."
+
+#~ 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 and also to only comb within the infill. Note that the 'Within Infill' option behaves exactly like the 'Not in Skin' option in earlier Cura releases."
+#~ 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 y además peinar solo en el relleno. La opción de «Sobre el relleno» actúa exactamente igual que la «No está en el forro» de las versiones de Cura anteriores."
+
+#~ msgctxt "connect_skin_polygons description"
+#~ msgid "Connect top/bottom skin paths where they run next to each other. For the concentric pattern enabling this setting greatly reduces the travel time, but because the connections can happend midway over infill this feature can reduce the top surface quality."
+#~ msgstr "Conectar las trayectorias de forro superior/inferior cuando están próximas entre sí. Al habilitar este ajuste, en el patrón concéntrico se reduce considerablemente el tiempo de desplazamiento, pero las conexiones pueden producirse en mitad del relleno, con lo que la bajaría la calidad de la superficie superior."
+
+#~ msgctxt "infill_pattern description"
+#~ msgid "The pattern of the infill material of the print. The line and zig zag infill swap direction on alternate layers, reducing material cost. The grid, triangle, tri-hexagon, cubic, octet, quarter cubic, cross and concentric patterns are fully printed every layer. Cubic, quarter cubic and octet infill change with every layer to provide a more equal distribution of strength over each direction."
+#~ msgstr "Patrón del material de relleno de la impresión. El relleno de línea y zigzag cambia de dirección en capas alternas, con lo que se reduce el coste del material. Los patrones de rejilla, triángulo, trihexagonal, cúbico, de octeto, cúbico bitruncado y transversal y concéntrico se imprimen en todas las capas por completo. El relleno cúbico, cúbico bitruncado y de octeto cambian en cada capa para proporcionar una distribución de fuerza equitativa en cada dirección."
+
#~ msgctxt "infill_pattern option concentric_3d"
#~ msgid "Concentric 3D"
#~ msgstr "Concéntrico 3D"
diff --git a/resources/i18n/fdmextruder.def.json.pot b/resources/i18n/fdmextruder.def.json.pot
index 5a89eaee33..991d418f7a 100644
--- a/resources/i18n/fdmextruder.def.json.pot
+++ b/resources/i18n/fdmextruder.def.json.pot
@@ -2,8 +2,8 @@
msgid ""
msgstr ""
"Project-Id-Version: Uranium json setting files\n"
-"Report-Msgid-Bugs-To: http://github.com/ultimaker/uranium\n"
-"POT-Creation-Date: 2018-09-19 17:07+0000\n"
+"Report-Msgid-Bugs-To: r.dulek@ultimaker.com\n"
+"POT-Creation-Date: 2019-07-16 14:38+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME \n"
"Language-Team: LANGUAGE\n"
@@ -80,7 +80,7 @@ msgstr ""
#: fdmextruder.def.json
msgctxt "machine_extruder_start_code description"
-msgid "Start g-code to execute whenever turning the extruder on."
+msgid "Start g-code to execute when switching to this extruder."
msgstr ""
#: fdmextruder.def.json
@@ -122,7 +122,7 @@ msgstr ""
#: fdmextruder.def.json
msgctxt "machine_extruder_end_code description"
-msgid "End g-code to execute whenever turning the extruder off."
+msgid "End g-code to execute when switching away from this extruder."
msgstr ""
#: fdmextruder.def.json
@@ -169,6 +169,19 @@ msgid ""
"printing."
msgstr ""
+#: fdmextruder.def.json
+msgctxt "machine_extruder_cooling_fan_number label"
+msgid "Extruder Print Cooling Fan"
+msgstr ""
+
+#: fdmextruder.def.json
+msgctxt "machine_extruder_cooling_fan_number description"
+msgid ""
+"The number of the print cooling fan associated with this extruder. Only "
+"change this from the default value of 0 when you have a different print "
+"cooling fan for each extruder."
+msgstr ""
+
#: fdmextruder.def.json
msgctxt "platform_adhesion label"
msgid "Build Plate Adhesion"
diff --git a/resources/i18n/fdmprinter.def.json.pot b/resources/i18n/fdmprinter.def.json.pot
index 79bcf5c7dc..fe62db7162 100644
--- a/resources/i18n/fdmprinter.def.json.pot
+++ b/resources/i18n/fdmprinter.def.json.pot
@@ -2,8 +2,8 @@
msgid ""
msgstr ""
"Project-Id-Version: Uranium json setting files\n"
-"Report-Msgid-Bugs-To: http://github.com/ultimaker/uranium\n"
-"POT-Creation-Date: 2018-09-19 17:07+0000\n"
+"Report-Msgid-Bugs-To: r.dulek@ultimaker.com\n"
+"POT-Creation-Date: 2019-07-16 14:38+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME \n"
"Language-Team: LANGUAGE\n"
@@ -244,7 +244,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 +255,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 +265,7 @@ msgstr ""
#: fdmprinter.def.json
msgctxt "machine_nozzle_head_distance label"
-msgid "Nozzle length"
+msgid "Nozzle Length"
msgstr ""
#: fdmprinter.def.json
@@ -277,7 +277,7 @@ msgstr ""
#: fdmprinter.def.json
msgctxt "machine_nozzle_expansion_angle label"
-msgid "Nozzle angle"
+msgid "Nozzle Angle"
msgstr ""
#: fdmprinter.def.json
@@ -289,7 +289,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 +325,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 +337,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 +362,7 @@ msgstr ""
#: fdmprinter.def.json
msgctxt "machine_gcode_flavor label"
-msgid "G-code flavour"
+msgid "G-code Flavor"
msgstr ""
#: fdmprinter.def.json
@@ -429,7 +429,7 @@ msgstr ""
#: fdmprinter.def.json
msgctxt "machine_disallowed_areas label"
-msgid "Disallowed areas"
+msgid "Disallowed Areas"
msgstr ""
#: fdmprinter.def.json
@@ -449,7 +449,7 @@ msgstr ""
#: fdmprinter.def.json
msgctxt "machine_head_polygon label"
-msgid "Machine head polygon"
+msgid "Machine Head Polygon"
msgstr ""
#: fdmprinter.def.json
@@ -459,7 +459,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 +469,7 @@ msgstr ""
#: fdmprinter.def.json
msgctxt "gantry_height label"
-msgid "Gantry height"
+msgid "Gantry Height"
msgstr ""
#: fdmprinter.def.json
@@ -503,7 +503,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
@@ -1171,7 +1171,7 @@ msgctxt "connect_skin_polygons description"
msgid ""
"Connect top/bottom skin paths where they run next to each other. For the "
"concentric pattern enabling this setting greatly reduces the travel time, "
-"but because the connections can happend midway over infill this feature can "
+"but because the connections can happen midway over infill this feature can "
"reduce the top surface quality."
msgstr ""
@@ -1448,7 +1448,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 +1473,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 +1493,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
@@ -1675,8 +1684,8 @@ msgid ""
"The pattern of the infill material of the print. The line and zig zag infill "
"swap direction on alternate layers, reducing material cost. The grid, "
"triangle, tri-hexagon, cubic, octet, quarter cubic, cross and concentric "
-"patterns are fully printed every layer. Cubic, quarter cubic and octet "
-"infill change with every layer to provide a more equal distribution of "
+"patterns are fully printed every layer. Gyroid, cubic, quarter cubic and "
+"octet infill change with every layer to provide a more equal distribution of "
"strength over each direction."
msgstr ""
@@ -1740,6 +1749,11 @@ msgctxt "infill_pattern option cross_3d"
msgid "Cross 3D"
msgstr ""
+#: fdmprinter.def.json
+msgctxt "infill_pattern option gyroid"
+msgid "Gyroid"
+msgstr ""
+
#: fdmprinter.def.json
msgctxt "zig_zaggify_infill label"
msgid "Connect Infill Lines"
@@ -1880,10 +1894,13 @@ msgstr ""
#: fdmprinter.def.json
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."
+"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
@@ -1894,8 +1911,12 @@ msgstr ""
#: fdmprinter.def.json
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."
+"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
@@ -2131,6 +2152,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"
@@ -2254,6 +2287,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"
@@ -2266,6 +2387,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"
@@ -2402,7 +2644,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 ""
@@ -2426,8 +2668,9 @@ msgstr ""
#: fdmprinter.def.json
msgctxt "switch_extruder_retraction_amount description"
msgid ""
-"The amount of retraction: Set at 0 for no retraction at all. This should "
-"generally be the same as the length of the heat zone."
+"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 ""
#: fdmprinter.def.json
@@ -2465,6 +2708,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"
@@ -2688,15 +2941,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
@@ -3179,9 +3433,7 @@ msgid ""
"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 and also to only comb within the infill. "
-"Note that the 'Within Infill' option behaves exactly like the 'Not in Skin' "
-"option in earlier Cura releases."
+"combing over top/bottom skin areas or to only comb within the infill."
msgstr ""
#: fdmprinter.def.json
@@ -3349,6 +3601,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"
@@ -3671,6 +3933,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,6 +4024,43 @@ msgid ""
"is rotated in the horizontal plane."
msgstr ""
+#: fdmprinter.def.json
+msgctxt "support_brim_enable label"
+msgid "Enable Support Brim"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "support_brim_enable description"
+msgid ""
+"Generate a brim within the support infill regions of the first layer. This "
+"brim is printed underneath the support, not around it. Enabling this setting "
+"increases the adhesion of support to the build plate."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "support_brim_width label"
+msgid "Support Brim Width"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "support_brim_width description"
+msgid ""
+"The width of the brim to print underneath the support. A larger brim "
+"enhances adhesion to the build plate, at the cost of some extra material."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "support_brim_line_count label"
+msgid "Support Brim Line Count"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "support_brim_line_count description"
+msgid ""
+"The number of lines used for the support brim. More brim lines enhance "
+"adhesion to the build plate, at the cost of some extra material."
+msgstr ""
+
#: fdmprinter.def.json
msgctxt "support_z_distance label"
msgid "Support Z Distance"
@@ -3871,7 +4175,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 ""
@@ -3924,6 +4228,18 @@ msgid ""
"density."
msgstr ""
+#: fdmprinter.def.json
+msgctxt "minimum_support_area label"
+msgid "Minimum Support Area"
+msgstr ""
+
+#: 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 ""
+
#: fdmprinter.def.json
msgctxt "support_interface_enable label"
msgid "Enable Support Interface"
@@ -4179,6 +4495,72 @@ msgctxt "support_bottom_pattern option zigzag"
msgid "Zig Zag"
msgstr ""
+#: fdmprinter.def.json
+msgctxt "minimum_interface_area label"
+msgid "Minimum Support Interface Area"
+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."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "minimum_roof_area label"
+msgid "Minimum Support Roof Area"
+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."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "minimum_bottom_area label"
+msgid "Minimum Support Floor Area"
+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."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "support_interface_offset label"
+msgid "Support Interface Horizontal Expansion"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "support_interface_offset description"
+msgid "Amount of offset applied to the support interface polygons."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "support_roof_offset label"
+msgid "Support Roof Horizontal Expansion"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "support_roof_offset description"
+msgid "Amount of offset applied to the roofs of the support."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "support_bottom_offset label"
+msgid "Support Floor Horizontal Expansion"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "support_bottom_offset description"
+msgid "Amount of offset applied to the floors of the support."
+msgstr ""
+
#: fdmprinter.def.json
msgctxt "support_fan_enable label"
msgid "Fan Speed Override"
@@ -4227,14 +4609,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 ""
@@ -4421,6 +4803,19 @@ msgid ""
"build plate, but also reduces the effective print area."
msgstr ""
+#: fdmprinter.def.json
+msgctxt "brim_replaces_support label"
+msgid "Brim Replaces Support"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "brim_replaces_support description"
+msgid ""
+"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."
+msgstr ""
+
#: fdmprinter.def.json
msgctxt "brim_outside_only label"
msgid "Brim Only on Outside"
@@ -4796,16 +5191,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"
@@ -4848,18 +5233,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"
@@ -4872,6 +5245,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"
@@ -5219,7 +5604,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 ""
@@ -5514,6 +5899,19 @@ msgid ""
"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."
+msgstr ""
+
#: fdmprinter.def.json
msgctxt "support_skip_some_zags label"
msgid "Break Up Support In Chunks"
@@ -5826,9 +6224,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
@@ -6243,7 +6639,7 @@ msgstr ""
#: fdmprinter.def.json
msgctxt "adaptive_layer_height_enabled label"
-msgid "Use adaptive layers"
+msgid "Use Adaptive Layers"
msgstr ""
#: fdmprinter.def.json
@@ -6255,7 +6651,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
@@ -6265,7 +6661,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
@@ -6277,7 +6673,7 @@ msgstr ""
#: fdmprinter.def.json
msgctxt "adaptive_layer_height_threshold label"
-msgid "Adaptive layers threshold"
+msgid "Adaptive Layers Threshold"
msgstr ""
#: fdmprinter.def.json
@@ -6529,6 +6925,173 @@ 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 "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 ede84960be..4a49ee7835 100644
--- a/resources/i18n/fi_FI/cura.po
+++ b/resources/i18n/fi_FI/cura.po
@@ -1,13 +1,13 @@
# Cura
-# Copyright (C) 2018 Ultimaker
+# Copyright (C) 2019 Ultimaker B.V.
# This file is distributed under the same license as the Cura package.
-# Ruben Dulek , 2018.
+# Ruben Dulek , 2019.
#
msgid ""
msgstr ""
-"Project-Id-Version: Cura 3.5\n"
+"Project-Id-Version: Cura 4.2\n"
"Report-Msgid-Bugs-To: r.dulek@ultimaker.com\n"
-"POT-Creation-Date: 2018-09-19 17:07+0200\n"
+"POT-Creation-Date: 2019-07-16 14:38+0200\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:27
msgctxt "@action"
msgid "Machine Settings"
msgstr "Laitteen asetukset"
@@ -46,15 +46,15 @@ msgstr ""
#: /home/ruben/Projects/Cura/plugins/GCodeWriter/GCodeWriter.py:73
#: /home/ruben/Projects/Cura/plugins/GCodeWriter/GCodeWriter.py:89
msgctxt "@warning:status"
-msgid "Please generate G-code before saving."
+msgid "Please prepare G-code before exporting."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/ModelChecker/ModelChecker.py:30
+#: /home/ruben/Projects/Cura/plugins/ModelChecker/ModelChecker.py:31
msgctxt "@info:title"
msgid "3D Model Assistant"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/ModelChecker/ModelChecker.py:80
+#: /home/ruben/Projects/Cura/plugins/ModelChecker/ModelChecker.py:90
#, python-brace-format
msgctxt "@info:status"
msgid ""
@@ -64,10 +64,10 @@ msgid ""
"
"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/CrashHandler.py:222
+#: /home/ruben/Projects/Cura/cura/CrashHandler.py:218
msgctxt "@title:groupbox"
msgid "Error traceback"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/CrashHandler.py:303
+#: /home/ruben/Projects/Cura/cura/CrashHandler.py:299
msgctxt "@title:groupbox"
msgid "Logs"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/CrashHandler.py:326
+#: /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:345
+#: /home/ruben/Projects/Cura/cura/CrashHandler.py:342
msgctxt "@action:button"
msgid "Send report"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:454
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:504
msgctxt "@info:progress"
msgid "Loading machines..."
msgstr "Ladataan laitteita..."
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:748
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:819
msgctxt "@info:progress"
msgid "Setting up scene..."
msgstr "Asetetaan näkymää..."
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:784
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:854
msgctxt "@info:progress"
msgid "Loading interface..."
msgstr "Ladataan käyttöliittymää..."
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:997
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1133
#, 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:1556
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1611
#, 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:1566
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1621
#, 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:1650
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1711
msgctxt "@info:status"
msgid "The selected model was too small to load."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:61
-msgctxt "@title"
-msgid "Machine Settings"
-msgstr "Laitteen asetukset"
-
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:80
-msgctxt "@title:tab"
-msgid "Printer"
-msgstr "Tulostin"
-
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:99
-msgctxt "@label"
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:58
+msgctxt "@title:label"
msgid "Printer Settings"
-msgstr "Tulostimen asetukset"
+msgstr ""
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:110
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:72
msgctxt "@label"
msgid "X (Width)"
msgstr "X (leveys)"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:111
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:121
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:131
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:237
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:386
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:402
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:420
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:432
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:857
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:76
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:90
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:104
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:194
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:213
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:232
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:253
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:272
+#: /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:120
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:86
msgctxt "@label"
msgid "Y (Depth)"
msgstr "Y (syvyys)"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:130
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:100
msgctxt "@label"
msgid "Z (Height)"
msgstr "Z (korkeus)"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:142
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:114
msgctxt "@label"
msgid "Build plate shape"
msgstr "Alustan muoto"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:151
-msgctxt "@option:check"
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:127
+msgctxt "@label"
msgid "Origin at center"
-msgstr "Alkukohta keskellä"
+msgstr ""
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:159
-msgctxt "@option:check"
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:139
+msgctxt "@label"
msgid "Heated bed"
-msgstr "Lämmitettävä pöytä"
+msgstr ""
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:170
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:151
msgctxt "@label"
msgid "G-code flavor"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:183
-msgctxt "@label"
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:176
+msgctxt "@title:label"
msgid "Printhead Settings"
-msgstr "Tulostuspään asetukset"
+msgstr ""
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:193
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:190
msgctxt "@label"
msgid "X min"
msgstr "X väh."
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:194
-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:203
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:209
msgctxt "@label"
msgid "Y min"
msgstr "Y väh."
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:204
-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:213
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:228
msgctxt "@label"
msgid "X max"
msgstr "X enint."
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:214
-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:223
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:249
msgctxt "@label"
msgid "Y max"
msgstr "Y enint."
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:224
-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:236
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:268
msgctxt "@label"
-msgid "Gantry height"
-msgstr "Korokkeen korkeus"
+msgid "Gantry Height"
+msgstr ""
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:238
-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:257
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:282
msgctxt "@label"
msgid "Number of Extruders"
msgstr "Suulakkeiden määrä"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:313
-msgctxt "@label"
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:341
+msgctxt "@title:label"
msgid "Start G-code"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:323
-msgctxt "@tooltip"
-msgid "G-code commands to be executed at the very start."
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:332
-msgctxt "@label"
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:355
+msgctxt "@title:label"
msgid "End G-code"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:342
-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:373
-msgctxt "@label"
-msgid "Nozzle Settings"
-msgstr "Suutinasetukset"
-
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:385
+#: /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:401
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsExtruderTab.qml:89
msgctxt "@label"
msgid "Compatible material diameter"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:403
-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:419
+#: /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:431
+#: /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/MachineSettingsExtruderTab.qml:162
+msgctxt "@title:label"
msgid "Extruder Start G-code"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:470
-msgctxt "@label"
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsExtruderTab.qml:176
+msgctxt "@title:label"
msgid "Extruder End G-code"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxProgressButton.qml:17
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxProgressButton.qml:18
msgctxt "@action:button"
msgid "Install"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxProgressButton.qml:19
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxProgressButton.qml:20
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailTileActions.qml:46
msgctxt "@action:button"
msgid "Installed"
msgstr "Asennettu"
@@ -1421,67 +1587,81 @@ msgctxt "@info"
msgid "Could not connect to the Cura Package database. Please check your connection."
msgstr ""
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/SmallRatingWidget.qml:27
+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:26
+#: /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:75
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:66
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:544
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledPage.qml:70
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxHeader.qml:44
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:80
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:417
msgctxt "@title:tab"
msgid "Materials"
msgstr "Materiaalit"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml:80
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml:91
+msgctxt "@label"
+msgid "Your rating"
+msgstr ""
+
+#: /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:86
+#: /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:92
+#: /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:98
+#: /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:117
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml:159
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:255
-msgctxt "@label"
-msgid "Unknown"
-msgstr "Tuntematon"
+#: /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:44
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml:30
+#: /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:45
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml:31
+#: /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:46
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml:32
+#: /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"
msgstr ""
#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/Toolbox.qml:13
msgctxt "@title"
-msgid "Toolbox"
+msgid "Marketplace"
msgstr ""
#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxBackColumn.qml:25
@@ -1491,7 +1671,7 @@ msgstr ""
#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxConfirmUninstallResetDialog.qml:20
msgctxt "@title:window"
-msgid "Confirm uninstall "
+msgid "Confirm uninstall"
msgstr ""
#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxConfirmUninstallResetDialog.qml:50
@@ -1509,17 +1689,27 @@ msgctxt "@text:window"
msgid "Profiles"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxConfirmUninstallResetDialog.qml:89
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxConfirmUninstallResetDialog.qml:90
msgctxt "@action:button"
msgid "Confirm"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxFooter.qml:17
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/RatingWidget.qml:54
+msgctxt "@label"
+msgid "You need to login first before you can rate"
+msgstr ""
+
+#: /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 ""
+
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxFooter.qml:19
msgctxt "@info"
msgid "You will need to restart Cura before changes in packages have effect."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxFooter.qml:34
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxFooter.qml:45
msgctxt "@info:button"
msgid "Quit Cura"
msgstr ""
@@ -1539,22 +1729,27 @@ msgctxt "@label"
msgid "Generic Materials"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxHeader.qml:54
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxHeader.qml:59
msgctxt "@title:tab"
msgid "Installed"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml:19
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml:22
msgctxt "@label"
msgid "Will install upon restarting"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml:51
+#: /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 ""
+
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml:71
msgctxt "@action:button"
msgid "Downgrade"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml:51
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml:71
msgctxt "@action:button"
msgid "Uninstall"
msgstr ""
@@ -1572,12 +1767,12 @@ msgid ""
"Do you agree with the terms below?"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxLicenseDialog.qml:54
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxLicenseDialog.qml:55
msgctxt "@action:button"
msgid "Accept"
msgstr "Hyväksy"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxLicenseDialog.qml:65
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxLicenseDialog.qml:66
msgctxt "@action:button"
msgid "Decline"
msgstr "Hylkää"
@@ -1587,22 +1782,42 @@ msgctxt "@label"
msgid "Featured"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:31
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:66
msgctxt "@label"
msgid "Compatibility"
msgstr ""
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:203
+msgctxt "@action:label"
+msgid "Technical Data Sheet"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:212
+msgctxt "@action:label"
+msgid "Safety Data Sheet"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:221
+msgctxt "@action:label"
+msgid "Printing Guidelines"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:230
+msgctxt "@action:label"
+msgid "Website"
+msgstr ""
+
#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxLoadingPage.qml:16
msgctxt "@info"
msgid "Fetching packages..."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxAuthorPage.qml:88
+#: /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:94
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxAuthorPage.qml:98
msgctxt "@label"
msgid "Email"
msgstr ""
@@ -1612,422 +1827,591 @@ 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
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:31
+msgctxt "@title"
+msgid "Update Firmware"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:39
msgctxt "@label"
-msgid "Changelog"
-msgstr "Muutosloki"
+msgid "Firmware is the piece of software running directly on your 3D printer. This firmware controls the step motors, regulates the temperature and ultimately makes your printer work."
+msgstr "Laiteohjelmisto on suoraan 3D-tulostimessa toimiva ohjelma. Laiteohjelmisto ohjaa askelmoottoreita, säätää lämpötilaa ja saa tulostimen toimimaan."
-#: /home/ruben/Projects/Cura/plugins/ChangeLogPlugin/ChangeLog.qml:37
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/FirmwareUpdateWindow.qml:84
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/UM3InfoComponents.qml:56
-#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.qml:464
-#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:508
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:121
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:148
-#: /home/ruben/Projects/Cura/resources/qml/EngineLog.qml:38
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:46
+msgctxt "@label"
+msgid "The firmware shipping with new printers works, but new versions tend to have more features and improvements."
+msgstr "Uusien tulostimien mukana toimitettava laiteohjelmisto toimii, mutta uusissa versioissa on yleensä enemmän toimintoja ja parannuksia."
+
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:58
msgctxt "@action:button"
-msgid "Close"
-msgstr "Sulje"
+msgid "Automatically upgrade Firmware"
+msgstr "Päivitä laiteohjelmisto automaattisesti"
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/FirmwareUpdateWindow.qml:22
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:69
+msgctxt "@action:button"
+msgid "Upload custom Firmware"
+msgstr "Lataa mukautettu laiteohjelmisto"
+
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:83
+msgctxt "@label"
+msgid "Firmware can not be updated because there is no connection with the printer."
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:91
+msgctxt "@label"
+msgid "Firmware can not be updated because the connection with the printer does not support upgrading firmware."
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:98
+msgctxt "@title:window"
+msgid "Select custom firmware"
+msgstr "Valitse mukautettu laiteohjelmisto"
+
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:119
msgctxt "@title:window"
msgid "Firmware Update"
msgstr "Laiteohjelmiston päivitys"
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/FirmwareUpdateWindow.qml:42
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:143
msgctxt "@label"
msgid "Updating firmware."
msgstr "Päivitetään laiteohjelmistoa."
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/FirmwareUpdateWindow.qml:44
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:145
msgctxt "@label"
msgid "Firmware update completed."
msgstr "Laiteohjelmiston päivitys suoritettu."
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/FirmwareUpdateWindow.qml:46
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:147
msgctxt "@label"
msgid "Firmware update failed due to an unknown error."
msgstr "Laiteohjelmiston päivitys epäonnistui tuntemattoman virheen takia."
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/FirmwareUpdateWindow.qml:48
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:149
msgctxt "@label"
msgid "Firmware update failed due to an communication error."
msgstr "Laiteohjelmiston päivitys epäonnistui tietoliikennevirheen takia."
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/FirmwareUpdateWindow.qml:50
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:151
msgctxt "@label"
msgid "Firmware update failed due to an input/output error."
msgstr "Laiteohjelmiston päivitys epäonnistui tiedoston lukemiseen tai kirjoittamiseen liittyvän virheen takia."
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/FirmwareUpdateWindow.qml:52
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:153
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:144
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobCard.qml:181
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:153
+msgctxt "@label"
+msgid "Glass"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:43
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:208
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobCard.qml:249
+msgctxt "@info"
+msgid "Please update your printer's firmware to manage the queue remotely."
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:241
+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:300
+msgctxt "@label:status"
+msgid "Loading..."
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:304
+msgctxt "@label:status"
+msgid "Unavailable"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:308
+msgctxt "@label:status"
+msgid "Unreachable"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:312
+msgctxt "@label:status"
+msgid "Idle"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:353
+msgctxt "@label"
+msgid "Untitled"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:374
+msgctxt "@label"
+msgid "Anonymous"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:401
+msgctxt "@label:status"
+msgid "Requires configuration changes"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:439
+msgctxt "@action:button"
+msgid "Details"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobCard.qml:130
+msgctxt "@label"
+msgid "Unavailable printer"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobCard.qml:132
+msgctxt "@label"
+msgid "First available"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml:31
+msgctxt "@label"
+msgid "Queued"
+msgstr "Jonossa"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml:67
+msgctxt "@label link to connect manager"
+msgid "Manage in browser"
+msgstr ""
+
+#: /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:116
+msgctxt "@label"
+msgid "Print jobs"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml:132
+msgctxt "@label"
+msgid "Total print time"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml:148
+msgctxt "@label"
+msgid "Waiting for"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:50
msgctxt "@window:title"
msgid "Existing Connection"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:45
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:52
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:62
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:69
msgctxt "@title:window"
msgid "Connect to Networked Printer"
msgstr "Yhdistä verkkotulostimeen"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:72
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:81
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:82
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:42
-msgctxt "@action:button"
-msgid "Add"
-msgstr "Lisää"
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:81
+msgctxt "@label"
+msgid "Select your printer from the list below:"
+msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:92
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:101
msgctxt "@action:button"
msgid "Edit"
msgstr "Muokkaa"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:103
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:128
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:48
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:117
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:112
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:146
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:55
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:121
msgctxt "@action:button"
msgid "Remove"
msgstr "Poista"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:111
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:120
msgctxt "@action:button"
msgid "Refresh"
msgstr "Päivitä"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:204
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:215
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:231
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:244
+#: /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:268
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:283
+#: /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:280
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:297
+#: /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:302
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:321
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:306
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:325
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:316
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:336
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:321
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/UM3InfoComponents.qml:39
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:341
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/UM3InfoComponents.qml:74
msgctxt "@action:button"
msgid "Connect"
msgstr "Yhdistä"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:335
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:354
+msgctxt "@title:window"
+msgid "Invalid IP address"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:355
+#: /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:366
msgctxt "@title:window"
msgid "Printer Address"
msgstr "Tulostimen osoite"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:358
-msgctxt "@alabel"
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:389
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddPrinterByIpContent.qml:102
+msgctxt "@label"
msgid "Enter the IP address or hostname of your printer on the network."
-msgstr "Anna verkon tulostimen IP-osoite tai isäntänimi."
+msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:387
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/MoreInfoWindow.qml:132
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:419
+#: /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/PrintWindow.qml:34
-msgctxt "@title:window"
-msgid "Print over network"
-msgstr "Tulosta verkon kautta"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintWindow.qml:65
-msgctxt "@label"
-msgid "Printer selection"
+#: /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/PrintWindow.qml:105
+#: /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: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:88
+msgctxt "@label:status"
+msgid "Aborting..."
+msgstr ""
+
+#: /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:94
+msgctxt "@label:status"
+msgid "Paused"
+msgstr ""
+
+#: /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:98
+msgctxt "@label:status"
+msgid "Action required"
+msgstr "Vaatii toimenpiteitä"
+
+#: /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/PrintJobInfoBlock.qml:142
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintWindow.qml:47
+msgctxt "@title:window"
+msgid "Print over network"
+msgstr "Tulosta verkon kautta"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintWindow.qml:79
msgctxt "@label"
-msgid "Waiting for: Unavailable printer"
+msgid "Printer selection"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintJobInfoBlock.qml:144
-msgctxt "@label"
-msgid "Waiting for: First available"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintJobInfoBlock.qml:148
-msgctxt "@label"
-msgid "Waiting for: "
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintJobInfoBlock.qml:213
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:54
msgctxt "@label"
msgid "Move to top"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintJobInfoBlock.qml:234
-msgctxt "@window:title"
-msgid "Move print job to top"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintJobInfoBlock.qml:236
-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 ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintJobInfoBlock.qml:245
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:70
msgctxt "@label"
msgid "Delete"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintJobInfoBlock.qml:264
-msgctxt "@window:title"
-msgid "Delete print job"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintJobInfoBlock.qml:266
-msgctxt "@label %1 is the name of a print job."
-msgid "Are you sure you want to delete %1?"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/ClusterMonitorItem.qml:32
-msgctxt "@label link to connect manager"
-msgid "Manage queue"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/ClusterMonitorItem.qml:54
-msgctxt "@label"
-msgid "Queued"
-msgstr "Jonossa"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/ClusterControlItem.qml:44
-msgctxt "@label"
-msgid "Printing"
-msgstr "Tulostetaan"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/ClusterControlItem.qml:54
-msgctxt "@label link to connect manager"
-msgid "Manage printers"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/ClusterControlItem.qml:212
-msgctxt "@label"
-msgid "Not available"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/ClusterControlItem.qml:215
-msgctxt "@label"
-msgid "Unreachable"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/ClusterControlItem.qml:221
-msgctxt "@label"
-msgid "Available"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/ClusterControlItem.qml:416
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:100
#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:289
msgctxt "@label"
msgid "Resume"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/ClusterControlItem.qml:416
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:102
+msgctxt "@label"
+msgid "Pausing..."
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:104
+msgctxt "@label"
+msgid "Resuming..."
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:106
#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:284
#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:293
msgctxt "@label"
msgid "Pause"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/ClusterControlItem.qml:444
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:124
+msgctxt "@label"
+msgid "Aborting..."
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:124
msgctxt "@label"
msgid "Abort"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/ClusterControlItem.qml:464
+#: /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 ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:144
+msgctxt "@window:title"
+msgid "Move print job to top"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:153
+msgctxt "@label %1 is the name of a print job."
+msgid "Are you sure you want to delete %1?"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:154
+msgctxt "@window:title"
+msgid "Delete print job"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:163
+msgctxt "@label %1 is the name of a print job."
+msgid "Are you sure you want to abort %1?"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:164
#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:335
msgctxt "@window:title"
msgid "Abort print"
msgstr "Keskeytä tulostus"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/ClusterControlItem.qml:466
-msgctxt "@label %1 is the name of a print job."
-msgid "Are you sure you want to abort %1?"
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:20
+msgctxt "@title:window"
+msgid "Configuration Changes"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/ClusterControlItem.qml:665
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/ClusterControlItem.qml:673
-msgctxt "@label:status"
-msgid "Aborted"
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:27
+msgctxt "@action:button"
+msgid "Override"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/ClusterControlItem.qml:667
-msgctxt "@label:status"
-msgid "Finished"
-msgstr "Valmis"
+#: /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/ClusterControlItem.qml:670
-msgctxt "@label:status"
-msgid "Preparing"
-msgstr "Valmistellaan"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/ClusterControlItem.qml:675
-msgctxt "@label:status"
-msgid "Pausing"
+#: /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/ClusterControlItem.qml:677
-msgctxt "@label:status"
-msgid "Paused"
+#: /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/ClusterControlItem.qml:679
-msgctxt "@label:status"
-msgid "Resuming"
+#: /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/ClusterControlItem.qml:681
-msgctxt "@label:status"
-msgid "Action required"
-msgstr "Vaatii toimenpiteitä"
+#: /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/UM3InfoComponents.qml:38
+#: /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: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: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/UM3NetworkPrinting/resources/qml/UM3InfoComponents.qml:117
-msgctxt "@info:tooltip"
-msgid "Load the configuration of the printer into Cura"
-msgstr "Lataa tulostimen määritys Curaan"
+#: /home/ruben/Projects/Cura/plugins/SettingsGuide/resources/qml/SettingsGuide.qml:16
+msgctxt "@title"
+msgid "Cura Settings Guide"
+msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/UM3InfoComponents.qml:118
-msgctxt "@action:button"
-msgid "Activate Configuration"
-msgstr "Aktivoi määritys"
+#: /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.\n"
+"- Check if you are signed in to discover cloud-connected printers."
+msgstr ""
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:130
+#: /home/ruben/Projects/Cura/plugins/MonitorStage/MonitorMain.qml:117
+msgctxt "@info"
+msgid "Please connect your printer to the network."
+msgstr ""
+
+#: /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:20
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:49
msgctxt "@label"
msgid "Color scheme"
msgstr "Värimalli"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:145
+#: /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/SimulationView.qml:149
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:111
msgctxt "@label:listbox"
msgid "Line Type"
msgstr "Linjojen tyyppi"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:153
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:115
msgctxt "@label:listbox"
msgid "Feedrate"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:157
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:119
msgctxt "@label:listbox"
msgid "Layer thickness"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:198
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:156
msgctxt "@label"
msgid "Compatibility Mode"
msgstr "Yhteensopivuustila"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:284
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:230
msgctxt "@label"
-msgid "Show Travels"
-msgstr "Näytä siirtoliikkeet"
+msgid "Travels"
+msgstr ""
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:290
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:236
msgctxt "@label"
-msgid "Show Helpers"
-msgstr "Näytä avustimet"
+msgid "Helpers"
+msgstr ""
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:296
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:242
msgctxt "@label"
-msgid "Show Shell"
-msgstr "Näytä kuori"
+msgid "Shell"
+msgstr ""
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:302
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:248
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedInfillDensitySelector.qml:65
msgctxt "@label"
-msgid "Show Infill"
-msgstr "Näytä täyttö"
+msgid "Infill"
+msgstr "Täyttö"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:355
+#: /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/SimulationView.qml:366
+#: /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/SimulationView.qml:379
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:322
msgctxt "@label"
msgid "Top / Bottom"
msgstr "Yläosa/alaosa"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:383
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:326
msgctxt "@label"
msgid "Inner Wall"
msgstr "Sisäseinämä"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:448
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:384
msgctxt "@label"
msgid "min"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:500
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:433
msgctxt "@label"
msgid "max"
msgstr ""
@@ -2042,39 +2426,39 @@ msgctxt "@label"
msgid "Post Processing Scripts"
msgstr "Jälkikäsittelykomentosarjat"
-#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.qml:225
+#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.qml:233
msgctxt "@action"
msgid "Add a script"
msgstr "Lisää komentosarja"
-#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.qml:271
+#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.qml:279
msgctxt "@label"
msgid "Settings"
msgstr "Asetukset"
-#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.qml:474
+#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.qml:493
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 these 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 these data to Ultimaker and help us improve Cura"
+msgid "Allow sending anonymous data"
msgstr ""
#: /home/ruben/Projects/Cura/plugins/ImageReader/ConfigUI.qml:19
@@ -2124,19 +2508,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."
@@ -2177,18 +2561,18 @@ msgctxt "@label"
msgid "Modify settings for infill of other models"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:341
+#: /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:383
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:388
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/resources/qml/Preferences/SettingVisibilityPage.qml:98
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/SettingVisibilityPage.qml:94
msgctxt "@label:textbox"
msgid "Filter..."
msgstr "Suodatin..."
@@ -2215,13 +2599,13 @@ msgid "Create new"
msgstr "Luo uusi"
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:70
-#: /home/ruben/Projects/Cura/resources/qml/WorkspaceSummaryDialog.qml:72
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:73
msgctxt "@action:title"
msgid "Summary - Cura Project"
msgstr "Yhteenveto – Cura-projekti"
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:92
-#: /home/ruben/Projects/Cura/resources/qml/WorkspaceSummaryDialog.qml:96
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:97
msgctxt "@action:label"
msgid "Printer settings"
msgstr "Tulostimen asetukset"
@@ -2238,18 +2622,19 @@ msgid "Update"
msgstr ""
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:143
-#: /home/ruben/Projects/Cura/resources/qml/WorkspaceSummaryDialog.qml:105
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:106
msgctxt "@action:label"
msgid "Type"
msgstr "Tyyppi"
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:159
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:121
msgctxt "@action:label"
msgid "Printer Group"
msgstr ""
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:180
-#: /home/ruben/Projects/Cura/resources/qml/WorkspaceSummaryDialog.qml:196
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:226
msgctxt "@action:label"
msgid "Profile settings"
msgstr "Profiilin asetukset"
@@ -2261,19 +2646,20 @@ 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/resources/qml/WorkspaceSummaryDialog.qml:220
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:121
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:250
msgctxt "@action:label"
msgid "Name"
msgstr "Nimi"
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:231
-#: /home/ruben/Projects/Cura/resources/qml/WorkspaceSummaryDialog.qml:204
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:234
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/WorkspaceSummaryDialog.qml:209
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:239
msgctxt "@action:label"
msgid "%1 override"
msgid_plural "%1 overrides"
@@ -2303,7 +2689,6 @@ 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/resources/qml/WorkspaceSummaryDialog.qml:237
msgctxt "@action:label"
msgid "Setting visibility"
msgstr "Asetusten näkyvyys"
@@ -2314,13 +2699,11 @@ msgid "Mode"
msgstr "Tila"
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:352
-#: /home/ruben/Projects/Cura/resources/qml/WorkspaceSummaryDialog.qml:246
msgctxt "@action:label"
msgid "Visible settings:"
msgstr "Näkyvät asetukset:"
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:357
-#: /home/ruben/Projects/Cura/resources/qml/WorkspaceSummaryDialog.qml:251
msgctxt "@action:label"
msgid "%1 out of %2"
msgstr "%1/%2"
@@ -2335,256 +2718,191 @@ msgctxt "@action:button"
msgid "Open"
msgstr "Avaa"
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/ProfileCreatorTabControls.qml:34
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/pages/BackupsPage.qml:28
+msgctxt "@title"
+msgid "My Backups"
+msgstr ""
+
+#: /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 ""
+
+#: /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 ""
+
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/pages/WelcomePage.qml:34
+msgctxt "@description"
+msgid "Backup and synchronize your Cura settings."
+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 ""
+
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/main.qml:24
+msgctxt "@title:window"
+msgid "Cura Backups"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListItemDetails.qml:21
+msgctxt "@backuplist:label"
+msgid "Cura Version"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListItemDetails.qml:29
+msgctxt "@backuplist:label"
+msgid "Machines"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListItemDetails.qml:37
+msgctxt "@backuplist:label"
+msgid "Materials"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListItemDetails.qml:45
+msgctxt "@backuplist:label"
+msgid "Profiles"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListItemDetails.qml:53
+msgctxt "@backuplist:label"
+msgid "Plugins"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListItem.qml:71
+msgctxt "@button"
+msgid "Restore"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListItem.qml:99
+msgctxt "@dialog:title"
+msgid "Delete Backup"
+msgstr ""
+
+#: /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 ""
+
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListItem.qml:108
+msgctxt "@dialog:title"
+msgid "Restore Backup"
+msgstr ""
+
+#: /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 ""
+
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListFooter.qml:22
+msgctxt "@button"
+msgid "Want more?"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListFooter.qml:31
+msgctxt "@button"
+msgid "Backup Now"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListFooter.qml:43
+msgctxt "@checkbox:description"
+msgid "Auto Backup"
+msgstr ""
+
+#: /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 ""
+
+#: /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:138
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:154
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:152
+#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/ProfileCreatorTabControls.qml:60
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:174
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:159
msgctxt "@action:button"
msgid "Export"
msgstr "Vie"
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/ProfileCreatorTabControls.qml:140
-msgctxt "@action:button"
-msgid "Next"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/ProfileCreatorPageCategoryView.qml:163
+#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/ProfileCreatorPageCategoryView.qml:209
msgctxt "@label"
msgid "Tip"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/CuraPrintProfileCreatorView.qml:80
-#: /home/ruben/Projects/Cura/resources/qml/PrepareSidebar.qml:341
-msgctxt "@label Hours and minutes"
-msgid "00h 00min"
+#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/ProfileCreatorMaterialMenu.qml:20
+#: /home/ruben/Projects/Cura/resources/qml/Menus/MaterialMenu.qml:66
+msgctxt "@label:category menu label"
+msgid "Generic"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/CuraPrintProfileCreatorView.qml:142
-#: /home/ruben/Projects/Cura/resources/qml/PrepareSidebar.qml:441
-msgctxt "@label"
-msgid "Cost specification"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/CuraPrintProfileCreatorView.qml:147
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/CuraPrintProfileCreatorView.qml:156
-#: /home/ruben/Projects/Cura/resources/qml/PrepareSidebar.qml:446
-#: /home/ruben/Projects/Cura/resources/qml/PrepareSidebar.qml:455
-msgctxt "@label m for meter"
-msgid "%1m"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/CuraPrintProfileCreatorView.qml:148
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/CuraPrintProfileCreatorView.qml:157
-#: /home/ruben/Projects/Cura/resources/qml/PrepareSidebar.qml:447
-#: /home/ruben/Projects/Cura/resources/qml/PrepareSidebar.qml:456
-msgctxt "@label g for grams"
-msgid "%1g"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/CuraPrintProfileCreatorView.qml:155
-#: /home/ruben/Projects/Cura/resources/qml/PrepareSidebar.qml:454
-msgctxt "@label"
-msgid "Total:"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/CuraPrintProfileCreatorView.qml:205
-msgctxt "@label Print estimates: m for meters, g for grams, %4 is currency and %3 is print cost"
-msgid "%1m / ~ %2g / ~ %4 %3"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/CuraPrintProfileCreatorView.qml:210
-msgctxt "@label Print estimates: m for meters, g for grams"
-msgid "%1m / ~ %2g"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/ProfileCreatorPage.qml:143
+#: /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:26
+#: /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
+#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UM2UpgradeSelectionMachineAction.qml:30
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
+#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UM2UpgradeSelectionMachineAction.qml:44
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/UpgradeFirmwareMachineAction.qml:30
-msgctxt "@title"
-msgid "Upgrade Firmware"
-msgstr "Laiteohjelmiston päivitys"
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UpgradeFirmwareMachineAction.qml:41
-msgctxt "@label"
-msgid "Firmware is the piece of software running directly on your 3D printer. This firmware controls the step motors, regulates the temperature and ultimately makes your printer work."
-msgstr "Laiteohjelmisto on suoraan 3D-tulostimessa toimiva ohjelma. Laiteohjelmisto ohjaa askelmoottoreita, säätää lämpötilaa ja saa tulostimen toimimaan."
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UpgradeFirmwareMachineAction.qml:51
-msgctxt "@label"
-msgid "The firmware shipping with new printers works, but new versions tend to have more features and improvements."
-msgstr "Uusien tulostimien mukana toimitettava laiteohjelmisto toimii, mutta uusissa versioissa on yleensä enemmän toimintoja ja parannuksia."
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UpgradeFirmwareMachineAction.qml:65
-msgctxt "@action:button"
-msgid "Automatically upgrade Firmware"
-msgstr "Päivitä laiteohjelmisto automaattisesti"
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UpgradeFirmwareMachineAction.qml:75
-msgctxt "@action:button"
-msgid "Upload custom Firmware"
-msgstr "Lataa mukautettu laiteohjelmisto"
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UpgradeFirmwareMachineAction.qml:87
-msgctxt "@title:window"
-msgid "Select custom firmware"
-msgstr "Valitse mukautettu laiteohjelmisto"
-
-#: /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"
@@ -2596,7 +2914,6 @@ msgid "Printer does not accept commands"
msgstr "Tulostin ei hyväksy komentoja"
#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:133
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:197
msgctxt "@label:MonitorStatus"
msgid "In maintenance. Please check the printer"
msgstr "Huolletaan. Tarkista tulostin"
@@ -2607,19 +2924,16 @@ msgid "Lost connection with the printer"
msgstr "Yhteys tulostimeen menetetty"
#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:146
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:187
msgctxt "@label:MonitorStatus"
msgid "Printing..."
msgstr "Tulostetaan..."
#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:149
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:189
msgctxt "@label:MonitorStatus"
msgid "Paused"
msgstr "Keskeytetty"
#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:152
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:191
msgctxt "@label:MonitorStatus"
msgid "Preparing..."
msgstr "Valmistellaan..."
@@ -2639,229 +2953,170 @@ msgctxt "@label"
msgid "Are you sure you want to abort the print?"
msgstr "Haluatko varmasti keskeyttää tulostuksen?"
-#: /home/ruben/Projects/Cura/resources/qml/DiscardOrKeepProfileChangesDialog.qml:15
-msgctxt "@title:window"
-msgid "Discard or Keep changes"
-msgstr "Hylkää tai säilytä muutokset"
-
-#: /home/ruben/Projects/Cura/resources/qml/DiscardOrKeepProfileChangesDialog.qml:57
-msgctxt "@text:window"
-msgid ""
-"You have customized some profile settings.\n"
-"Would you like to keep or discard those settings?"
-msgstr ""
-"Olet mukauttanut profiilin asetuksia.\n"
-"Haluatko säilyttää vai hylätä nämä asetukset?"
-
-#: /home/ruben/Projects/Cura/resources/qml/DiscardOrKeepProfileChangesDialog.qml:110
-msgctxt "@title:column"
-msgid "Profile settings"
-msgstr "Profiilin asetukset"
-
-#: /home/ruben/Projects/Cura/resources/qml/DiscardOrKeepProfileChangesDialog.qml:117
-msgctxt "@title:column"
-msgid "Default"
-msgstr "Oletusarvo"
-
-#: /home/ruben/Projects/Cura/resources/qml/DiscardOrKeepProfileChangesDialog.qml:124
-msgctxt "@title:column"
-msgid "Customized"
-msgstr "Mukautettu"
-
-#: /home/ruben/Projects/Cura/resources/qml/DiscardOrKeepProfileChangesDialog.qml:157
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:639
-msgctxt "@option:discardOrKeep"
-msgid "Always ask me this"
-msgstr "Kysy aina"
-
-#: /home/ruben/Projects/Cura/resources/qml/DiscardOrKeepProfileChangesDialog.qml:158
-msgctxt "@option:discardOrKeep"
-msgid "Discard and never ask again"
-msgstr "Hylkää äläkä kysy uudelleen"
-
-#: /home/ruben/Projects/Cura/resources/qml/DiscardOrKeepProfileChangesDialog.qml:159
-msgctxt "@option:discardOrKeep"
-msgid "Keep and never ask again"
-msgstr "Säilytä äläkä kysy uudelleen"
-
-#: /home/ruben/Projects/Cura/resources/qml/DiscardOrKeepProfileChangesDialog.qml:196
-msgctxt "@action:button"
-msgid "Discard"
-msgstr "Hylkää"
-
-#: /home/ruben/Projects/Cura/resources/qml/DiscardOrKeepProfileChangesDialog.qml:209
-msgctxt "@action:button"
-msgid "Keep"
-msgstr "Säilytä"
-
-#: /home/ruben/Projects/Cura/resources/qml/DiscardOrKeepProfileChangesDialog.qml:222
-msgctxt "@action:button"
-msgid "Create New Profile"
-msgstr "Luo uusi profiili"
-
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:71
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:73
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:102
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:103
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:127
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:137
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:147
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:157
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:207
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:209
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:224
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:258
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:275
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:293
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:302
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:316
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:323
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:334
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:347
msgctxt "@label"
msgid "Adhesion Information"
msgstr "Tarttuvuustiedot"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:378
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:373
+#: /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:35
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:72
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:99
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:40
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:73
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:117
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:131
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:160
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:148
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:223
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:239
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:287
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:253
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:240
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:290
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:254
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:304
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:312
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:313
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:317
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:335
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:343
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:347
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:353
msgctxt "@info:status Don't translate the XML tag !"
msgid "Successfully exported material to %1"
msgstr "Materiaalin vieminen onnistui kohteeseen %1"
@@ -2871,649 +3126,536 @@ msgctxt "@title:tab"
msgid "Setting Visibility"
msgstr "Näkyvyyden asettaminen"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/SettingVisibilityPage.qml:50
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/SettingVisibilityPage.qml:46
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:48
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:61
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:68
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:75
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:83
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:537
+#: /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:141
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:130
msgctxt "@label"
msgid "Interface"
msgstr "Käyttöliittymä"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:152
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:141
msgctxt "@label"
msgid "Language:"
msgstr "Kieli:"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:220
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:208
msgctxt "@label"
msgid "Currency:"
msgstr "Valuutta:"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:234
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:221
msgctxt "@label"
msgid "Theme:"
msgstr "Teema:"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:294
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:277
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:311
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:294
msgctxt "@info:tooltip"
msgid "Slice automatically when changing settings."
msgstr "Viipaloi automaattisesti, kun asetuksia muutetaan."
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:319
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:302
msgctxt "@option:check"
msgid "Slice automatically"
msgstr "Viipaloi automaattisesti"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:333
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:316
msgctxt "@label"
msgid "Viewport behavior"
msgstr "Näyttöikkunan käyttäytyminen"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:341
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:324
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:350
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:333
msgctxt "@option:check"
msgid "Display overhang"
msgstr "Näytä uloke"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:357
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:341
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:362
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:346
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:371
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:356
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:376
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:361
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:386
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:371
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:391
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:371
+msgctxt "@info:tooltip"
+msgid "Zooming towards the mouse is not supported in the orthogonal perspective."
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:376
msgctxt "@action:button"
msgid "Zoom toward mouse direction"
msgstr "Zoomaa hiiren suuntaan"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:401
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:402
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:406
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:407
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:415
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:416
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:420
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:421
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:432
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:433
msgctxt "@info:tooltip"
msgid "Show caution message in g-code reader."
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:441
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:442
msgctxt "@option:check"
msgid "Caution message in g-code reader"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:449
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:450
msgctxt "@info:tooltip"
msgid "Should layer be forced into compatibility mode?"
msgstr "Pakotetaanko kerros yhteensopivuustilaan?"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:454
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:455
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:470
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:465
+msgctxt "@info:tooltip"
+msgid "What type of camera rendering should be used?"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:472
+msgctxt "@window:text"
+msgid "Camera rendering: "
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:483
+msgid "Perspective"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:484
+msgid "Orthogonal"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:515
msgctxt "@label"
msgid "Opening and saving files"
msgstr "Tiedostojen avaaminen ja tallentaminen"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:477
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:522
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:482
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:527
msgctxt "@option:check"
msgid "Scale large models"
msgstr "Skaalaa suuret mallit"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:492
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:537
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:497
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:542
msgctxt "@option:check"
msgid "Scale extremely small models"
msgstr "Skaalaa erittäin pienet mallit"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:507
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:552
msgctxt "@info:tooltip"
msgid "Should models be selected after they are loaded?"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:512
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:557
msgctxt "@option:check"
msgid "Select models when loaded"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:522
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:567
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:527
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:572
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:537
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:582
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:541
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:586
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:551
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:596
msgctxt "@info:tooltip"
msgid "Default behavior when opening a project file"
msgstr "Projektitiedoston avaamisen oletustoimintatapa"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:559
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:604
msgctxt "@window:text"
msgid "Default behavior when opening a project file: "
msgstr "Projektitiedoston avaamisen oletustoimintatapa: "
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:573
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:618
msgctxt "@option:openProject"
msgid "Always ask me this"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:574
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:619
msgctxt "@option:openProject"
msgid "Always open as a project"
msgstr "Avaa aina projektina"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:575
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:620
msgctxt "@option:openProject"
msgid "Always import models"
msgstr "Tuo mallit aina"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:611
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:656
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:620
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:665
msgctxt "@label"
msgid "Profiles"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:625
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:670
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:640
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:684
+#: /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:685
msgctxt "@option:discardOrKeep"
msgid "Always discard changed settings"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:641
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:686
msgctxt "@option:discardOrKeep"
msgid "Always transfer changed settings to new profile"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:675
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:720
msgctxt "@label"
msgid "Privacy"
msgstr "Tietosuoja"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:683
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:727
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:688
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:732
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:699
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:742
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:704
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:747
msgctxt "@option:check"
msgid "Send (anonymous) print information"
msgstr "Lähetä (anonyymit) tulostustiedot"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:713
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:756
msgctxt "@action:button"
msgid "More information"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:731
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:774
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/PrintSetupSelectorHeader.qml:27
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ProfileMenu.qml:23
msgctxt "@label"
msgid "Experimental"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:738
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:781
msgctxt "@info:tooltip"
msgid "Use multi build plate functionality"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:743
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:786
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:542
+#: /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:55
-#: /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:134
msgctxt "@action:button"
msgid "Rename"
msgstr "Nimeä uudelleen"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:147
-msgctxt "@label"
-msgid "Printer type:"
-msgstr "Tulostimen tyyppi:"
-
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:156
-msgctxt "@label"
-msgid "Connection:"
-msgstr "Yhteys:"
-
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:162
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/OutputDeviceHeader.qml:47
-msgctxt "@info:status"
-msgid "The printer is not connected."
-msgstr "Tulostinta ei ole yhdistetty."
-
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:168
-msgctxt "@label"
-msgid "State:"
-msgstr "Tila:"
-
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:181
-msgctxt "@label:MonitorStatus"
-msgid "Waiting for a printjob"
-msgstr "Odotetaan tulostustyötä"
-
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:193
-msgctxt "@label:MonitorStatus"
-msgid "Waiting for someone to clear the build plate"
-msgstr "Odotetaan tulostusalustan tyhjennystä"
-
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:199
-msgctxt "@label:MonitorStatus"
-msgid "Aborting print..."
-msgstr "Keskeytetään tulostus..."
-
#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:36
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:546
+#: /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:89
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:105
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:181
msgctxt "@title:window"
msgid "Create Profile"
msgstr "Luo profiili"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:225
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:183
+msgctxt "@info"
+msgid "Please provide a name for this profile."
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:239
msgctxt "@title:window"
msgid "Duplicate Profile"
msgstr "Monista profiili"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:256
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:270
msgctxt "@title:window"
msgid "Rename Profile"
msgstr "Nimeä profiili uudelleen"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:269
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:283
msgctxt "@title:window"
msgid "Import Profile"
msgstr "Profiilin tuonti"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:295
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:309
msgctxt "@title:window"
msgid "Export Profile"
msgstr "Profiilin vienti"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:350
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:364
msgctxt "@label %1 is printer name"
msgid "Printer: %1"
msgstr "Tulostin: %1"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:403
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:420
msgctxt "@label"
-msgid "Protected profiles"
-msgstr "Suojatut profiilit"
+msgid "Default profiles"
+msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:403
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:420
msgctxt "@label"
msgid "Custom profiles"
msgstr "Mukautetut profiilit"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:480
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:500
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:487
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:507
msgctxt "@action:button"
msgid "Discard current changes"
msgstr "Hylkää tehdyt muutokset"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:504
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:524
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:511
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:531
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:530
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:550
msgctxt "@title:tab"
msgid "Global Settings"
msgstr "Yleiset asetukset"
-#: /home/ruben/Projects/Cura/resources/qml/AddMachineDialog.qml:18
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:946
-msgctxt "@title:window"
-msgid "Add Printer"
-msgstr "Lisää tulostin"
-
-#: /home/ruben/Projects/Cura/resources/qml/AddMachineDialog.qml:194
-msgctxt "@label"
-msgid "Printer Name:"
-msgstr "Tulostimen nimi:"
-
-#: /home/ruben/Projects/Cura/resources/qml/AddMachineDialog.qml:217
+#: /home/ruben/Projects/Cura/resources/qml/MainWindow/MainWindowHeader.qml:89
msgctxt "@action:button"
-msgid "Add Printer"
-msgstr "Lisää tulostin"
+msgid "Marketplace"
+msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/JobSpecs.qml:84
+#: /home/ruben/Projects/Cura/resources/qml/MainWindow/ApplicationMenu.qml:27
+#: /home/ruben/Projects/Cura/resources/qml/Menus/FileMenu.qml:13
+msgctxt "@title:menu menubar:toplevel"
+msgid "&File"
+msgstr "Tie&dosto"
+
+#: /home/ruben/Projects/Cura/resources/qml/MainWindow/ApplicationMenu.qml:31
+msgctxt "@title:menu menubar:toplevel"
+msgid "&Edit"
+msgstr "&Muokkaa"
+
+#: /home/ruben/Projects/Cura/resources/qml/MainWindow/ApplicationMenu.qml:48
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ViewMenu.qml:12
+msgctxt "@title:menu menubar:toplevel"
+msgid "&View"
+msgstr "&Näytä"
+
+#: /home/ruben/Projects/Cura/resources/qml/MainWindow/ApplicationMenu.qml:50
+#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:13
+msgctxt "@title:menu menubar:toplevel"
+msgid "&Settings"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/MainWindow/ApplicationMenu.qml:55
+msgctxt "@title:menu menubar:toplevel"
+msgid "E&xtensions"
+msgstr "Laa&jennukset"
+
+#: /home/ruben/Projects/Cura/resources/qml/MainWindow/ApplicationMenu.qml:89
+msgctxt "@title:menu menubar:toplevel"
+msgid "P&references"
+msgstr "L&isäasetukset"
+
+#: /home/ruben/Projects/Cura/resources/qml/MainWindow/ApplicationMenu.qml:97
+msgctxt "@title:menu menubar:toplevel"
+msgid "&Help"
+msgstr "&Ohje"
+
+#: /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: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."
+
+#: /home/ruben/Projects/Cura/resources/qml/JobSpecs.qml:88
msgctxt "@text Print job name"
msgid "Untitled"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:15
-msgctxt "@title:window"
-msgid "About Cura"
-msgstr "Tietoja Curasta"
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:43
-msgctxt "@label"
-msgid "version: %1"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:56
-msgctxt "@label"
-msgid "End-to-end solution for fused filament 3D printing."
-msgstr "Kokonaisvaltainen sulatettavan tulostuslangan 3D-tulostusratkaisu."
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:69
-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 ""
-"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/AboutDialog.qml:118
-msgctxt "@label"
-msgid "Graphical user interface"
-msgstr "Graafinen käyttöliittymä"
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:119
-msgctxt "@label"
-msgid "Application framework"
-msgstr "Sovelluskehys"
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:120
-msgctxt "@label"
-msgid "G-code generator"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:121
-msgctxt "@label"
-msgid "Interprocess communication library"
-msgstr "Prosessien välinen tietoliikennekirjasto"
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:123
-msgctxt "@label"
-msgid "Programming language"
-msgstr "Ohjelmointikieli"
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:124
-msgctxt "@label"
-msgid "GUI framework"
-msgstr "GUI-kehys"
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:125
-msgctxt "@label"
-msgid "GUI framework bindings"
-msgstr "GUI-kehyksen sidonnat"
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:126
-msgctxt "@label"
-msgid "C/C++ Binding library"
-msgstr "C/C++ -sidontakirjasto"
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:127
-msgctxt "@label"
-msgid "Data interchange format"
-msgstr "Data Interchange Format"
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:128
-msgctxt "@label"
-msgid "Support library for scientific computing"
-msgstr "Tieteellisen laskennan tukikirjasto"
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:129
-msgctxt "@label"
-msgid "Support library for faster math"
-msgstr "Nopeamman laskennan tukikirjasto"
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:130
-msgctxt "@label"
-msgid "Support library for handling STL files"
-msgstr "STL-tiedostojen käsittelyn tukikirjasto"
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:131
-msgctxt "@label"
-msgid "Support library for handling 3MF files"
-msgstr "Tukikirjasto 3MF-tiedostojen käsittelyyn"
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:132
-msgctxt "@label"
-msgid "Serial communication library"
-msgstr "Sarjatietoliikennekirjasto"
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:133
-msgctxt "@label"
-msgid "ZeroConf discovery library"
-msgstr "ZeroConf-etsintäkirjasto"
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:134
-msgctxt "@label"
-msgid "Polygon clipping library"
-msgstr "Monikulmion leikkauskirjasto"
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:135
-msgctxt "@Label"
-msgid "Python HTTP library"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:137
-msgctxt "@label"
-msgid "Font"
-msgstr "Fontti"
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:138
-msgctxt "@label"
-msgid "SVG icons"
-msgstr "SVG-kuvakkeet"
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:139
-msgctxt "@label"
-msgid "Linux cross-distribution application deployment"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:42
-msgctxt "@label"
-msgid "Profile:"
-msgstr "Profiili:"
-
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:103
-msgctxt "@tooltip"
-msgid ""
-"Some setting/override values are different from the values stored in the profile.\n"
-"\n"
-"Click to open the profile manager."
-msgstr ""
-"Jotkut asetusten ja ohitusten arvot eroavat profiiliin tallennetuista arvoista.\n"
-"\n"
-"Avaa profiilin hallinta napsauttamalla."
-
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:199
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:68
msgctxt "@label:textbox"
-msgid "Search..."
-msgstr "Haku…"
+msgid "search settings"
+msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:544
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:466
msgctxt "@action:menu"
msgid "Copy value to all extruders"
msgstr "Kopioi arvo kaikkiin suulakepuristimiin"
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:553
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:475
msgctxt "@action:menu"
msgid "Copy all changed values to all extruders"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:590
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:512
msgctxt "@action:menu"
msgid "Hide this setting"
msgstr "Piilota tämä asetus"
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:608
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:525
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:612
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:529
msgctxt "@action:menu"
msgid "Keep this setting visible"
msgstr "Pidä tämä asetus näkyvissä"
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:636
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:416
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:548
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:434
msgctxt "@action:menu"
msgid "Configure setting visibility..."
msgstr "Määritä asetusten näkyvyys..."
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:643
-msgctxt "@action:inmenu"
-msgid "Collapse All"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:648
-msgctxt "@action:inmenu"
-msgid "Expand All"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingCategory.qml:249
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingCategory.qml:237
msgctxt "@label"
msgid ""
"Some hidden settings use values different from their normal calculated value.\n"
@@ -3524,27 +3666,32 @@ msgstr ""
"\n"
"Tee asetuksista näkyviä napsauttamalla."
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:61
+#: /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:66
+#: /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:154
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:186
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:157
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:190
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:188
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:228
msgctxt "@label"
msgid ""
"This setting has a value that is different from the profile.\n"
@@ -3555,7 +3702,7 @@ msgstr ""
"\n"
"Palauta profiilin arvo napsauttamalla."
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:286
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:322
msgctxt "@label"
msgid ""
"This setting is normally calculated, but it currently has an absolute value set.\n"
@@ -3566,116 +3713,210 @@ msgstr ""
"\n"
"Palauta laskettu arvo napsauttamalla."
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ManualPrinterControl.qml:129
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/PrintSetupSelectorContents.qml:144
+msgctxt "@button"
+msgid "Recommended"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/PrintSetupSelectorContents.qml:158
+msgctxt "@button"
+msgid "Custom"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedInfillDensitySelector.qml:193
+msgctxt "@label"
+msgid "Gradual infill"
+msgstr ""
+
+#: /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 "Asteittainen täyttö lisää täytön tiheyttä vähitellen yläosaa kohti."
+
+#: /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: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/RecommendedAdhesionSelector.qml:29
+msgctxt "@label"
+msgid "Adhesion"
+msgstr ""
+
+#: /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
+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"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/PrintSetupSelectorHeader.qml:14
+msgctxt "@label:Should be short"
+msgid "Off"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Custom/GlobalProfileSelector.qml:27
+msgctxt "@label"
+msgid "Profile"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Custom/GlobalProfileSelector.qml:94
+msgctxt "@tooltip"
+msgid ""
+"Some setting/override values are different from the values stored in the profile.\n"
+"\n"
+"Click to open the profile manager."
+msgstr ""
+"Jotkut asetusten ja ohitusten arvot eroavat profiiliin tallennetuista arvoista.\n"
+"\n"
+"Avaa profiilin hallinta napsauttamalla."
+
+#: /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 ""
+
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ManualPrinterControl.qml:52
msgctxt "@label"
msgid "Printer control"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ManualPrinterControl.qml:144
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ManualPrinterControl.qml:67
msgctxt "@label"
msgid "Jog Position"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ManualPrinterControl.qml:162
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ManualPrinterControl.qml:85
msgctxt "@label"
msgid "X/Y"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ManualPrinterControl.qml:269
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ManualPrinterControl.qml:192
msgctxt "@label"
msgid "Z"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ManualPrinterControl.qml:334
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ManualPrinterControl.qml:257
msgctxt "@label"
msgid "Jog Distance"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ManualPrinterControl.qml:443
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ManualPrinterControl.qml:301
msgctxt "@label"
msgid "Send G-code"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ManualPrinterControl.qml:506
+#: /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:36
-#: /home/ruben/Projects/Cura/resources/qml/SidebarHeader.qml:272
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:38
msgctxt "@label"
msgid "Extruder"
msgstr "Suulake"
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:66
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:68
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:98
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:100
msgctxt "@tooltip"
msgid "The current temperature of this hotend."
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:172
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:174
msgctxt "@tooltip of temperature input"
msgid "The temperature to pre-heat the hotend to."
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:336
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/HeatedBedBox.qml:331
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:338
+#: /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:339
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/HeatedBedBox.qml:334
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:341
+#: /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:365
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:367
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:401
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:403
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:433
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:435
msgctxt "@tooltip"
msgid "The material in this extruder."
msgstr "Tämän suulakkeen materiaali."
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:465
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:467
msgctxt "@tooltip"
msgid "The nozzle inserted in this extruder."
msgstr "Tähän suulakkeeseen liitetty suutin."
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/HeatedBedBox.qml:25
-#: /home/ruben/Projects/Cura/resources/qml/SidebarHeader.qml:493
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/OutputDeviceHeader.qml:55
+msgctxt "@info:status"
+msgid "The printer is not connected."
+msgstr "Tulostinta ei ole yhdistetty."
+
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/HeatedBedBox.qml:26
msgctxt "@label"
msgid "Build plate"
msgstr "Alusta"
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/HeatedBedBox.qml:55
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/HeatedBedBox.qml:56
msgctxt "@tooltip"
msgid "The target temperature of the heated bed. The bed will heat up or cool down towards this temperature. If this is 0, the bed heating is turned off."
msgstr "Lämmitettävän pöydän kohdelämpötila. Pöytä lämpenee tai viilenee kohti tätä lämpötilaa. Jos asetus on 0, pöydän lämmitys sammutetaan."
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/HeatedBedBox.qml:87
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/HeatedBedBox.qml:88
msgctxt "@tooltip"
msgid "The current temperature of the heated bed."
msgstr "Lämmitettävän pöydän nykyinen lämpötila."
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/HeatedBedBox.qml:160
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/HeatedBedBox.qml:161
msgctxt "@tooltip of temperature input"
msgid "The temperature to pre-heat the bed to."
msgstr "Lämmitettävän pöydän esilämmityslämpötila."
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/HeatedBedBox.qml:360
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/HeatedBedBox.qml:361
msgctxt "@tooltip of pre-heat"
msgid "Heat the bed in advance before printing. You can continue adjusting your print while it is heating, and you won't have to wait for the bed to heat up when you're ready to print."
msgstr "Lämmitä pöytä ennen tulostusta. Voit edelleen säätää tulostinta sen lämmitessä, eikä sinun tarvitse odottaa pöydän lämpiämistä, kun olet valmis tulostamaan."
@@ -3685,16 +3926,11 @@ msgctxt "@label:category menu label"
msgid "Material"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Menus/MaterialMenu.qml:37
+#: /home/ruben/Projects/Cura/resources/qml/Menus/MaterialMenu.qml:42
msgctxt "@label:category menu label"
msgid "Favorites"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Menus/MaterialMenu.qml:61
-msgctxt "@label:category menu label"
-msgid "Generic"
-msgstr ""
-
#: /home/ruben/Projects/Cura/resources/qml/Menus/PrinterMenu.qml:25
msgctxt "@label:category menu label"
msgid "Network enabled printers"
@@ -3705,17 +3941,62 @@ msgctxt "@label:category menu label"
msgid "Local printers"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Menus/ViewMenu.qml:12
-msgctxt "@title:menu menubar:toplevel"
-msgid "&View"
-msgstr "&Näytä"
+#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:15
+msgctxt "@title:menu menubar:settings"
+msgid "&Printer"
+msgstr "&Tulostin"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/ViewMenu.qml:39
+#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:32
+msgctxt "@title:menu"
+msgid "&Material"
+msgstr "&Materiaali"
+
+#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:41
+msgctxt "@action:inmenu"
+msgid "Set as Active Extruder"
+msgstr "Aseta aktiiviseksi suulakepuristimeksi"
+
+#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:47
+msgctxt "@action:inmenu"
+msgid "Enable Extruder"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:54
+msgctxt "@action:inmenu"
+msgid "Disable Extruder"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:68
+msgctxt "@title:menu"
+msgid "&Build plate"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:71
+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:54
+#: /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 ""
@@ -3725,16 +4006,31 @@ msgctxt "@action:inmenu"
msgid "Visible Settings"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingVisibilityPresetsMenu.qml:43
+#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingVisibilityPresetsMenu.qml:42
msgctxt "@action:inmenu"
msgid "Show All Settings"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingVisibilityPresetsMenu.qml:54
+#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingVisibilityPresetsMenu.qml:53
msgctxt "@action:inmenu"
msgid "Manage Setting Visibility..."
msgstr ""
+#: /home/ruben/Projects/Cura/resources/qml/Menus/FileMenu.qml:32
+msgctxt "@title:menu menubar:file"
+msgid "&Save..."
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Menus/FileMenu.qml:53
+msgctxt "@title:menu menubar:file"
+msgid "&Export..."
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Menus/FileMenu.qml:64
+msgctxt "@action:inmenu menubar:file"
+msgid "Export Selection..."
+msgstr ""
+
#: /home/ruben/Projects/Cura/resources/qml/Menus/ContextMenu.qml:27
msgctxt "@label"
msgid "Print Selected Model With:"
@@ -3754,635 +4050,507 @@ msgctxt "@label"
msgid "Number of Copies"
msgstr "Kopioiden määrä"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/ConfigurationListView.qml:33
-msgctxt "@label:header configurations"
-msgid "Available configurations"
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/AutoConfiguration.qml:18
+msgctxt "@header"
+msgid "Configurations"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/PrintCoreConfiguration.qml:28
-msgctxt "@label:extruder label"
-msgid "Extruder"
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/ConfigurationMenu.qml:110
+msgctxt "@label"
+msgid "Select configuration"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/SyncButton.qml:16
-msgctxt "@label:extruder label"
-msgid "Yes"
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/ConfigurationMenu.qml:221
+msgctxt "@label"
+msgid "Configurations"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/SyncButton.qml:16
-msgctxt "@label:extruder label"
-msgid "No"
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/ConfigurationListView.qml:57
+msgctxt "@label"
+msgid "Loading available configurations from the printer..."
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Menus/RecentFilesMenu.qml:13
+#: /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 ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/CustomConfiguration.qml:25
+msgctxt "@header"
+msgid "Custom"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/CustomConfiguration.qml:61
+msgctxt "@label"
+msgid "Printer"
+msgstr ""
+
+#: /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:250
+msgctxt "@label"
+msgid "Material"
+msgstr "Materiaali"
+
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/CustomConfiguration.qml:375
+msgctxt "@label"
+msgid "Use glue for better adhesion with this material combination."
+msgstr ""
+
+#: /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 ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/ConfigurationItem.qml:129
+msgctxt "@label"
+msgid "Marketplace"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Menus/RecentFilesMenu.qml:15
msgctxt "@title:menu menubar:file"
msgid "Open &Recent"
msgstr "Avaa &viimeisin"
-#: /home/ruben/Projects/Cura/resources/qml/PrepareSidebar.qml:150
-msgctxt "@label:listbox"
-msgid "Print Setup"
-msgstr "Tulostuksen asennus"
-
-#: /home/ruben/Projects/Cura/resources/qml/PrepareSidebar.qml:150
-msgctxt "@label:listbox"
-msgid ""
-"Print Setup disabled\n"
-"G-code files cannot be modified"
-msgstr ""
-"Tulostuksen asennus ei käytössä\n"
-"G-code-tiedostoja ei voida muokata"
-
-#: /home/ruben/Projects/Cura/resources/qml/PrepareSidebar.qml:359
-msgctxt "@tooltip"
-msgid "Time specification"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/PrepareSidebar.qml:577
-msgctxt "@tooltip"
-msgid "Recommended Print Setup
Print with the recommended settings for the selected printer, material and quality."
-msgstr "Suositeltu tulostuksen asennus
Tulosta valitun tulostimen, materiaalin ja laadun suositelluilla asetuksilla."
-
-#: /home/ruben/Projects/Cura/resources/qml/PrepareSidebar.qml:582
-msgctxt "@tooltip"
-msgid "Custom Print Setup
Print with finegrained control over every last bit of the slicing process."
-msgstr "Mukautettu tulostuksen asennus
Tulosta hallitsemalla täysin kaikkia viipalointiprosessin vaiheita."
-
-#: /home/ruben/Projects/Cura/resources/qml/PrintMonitor.qml:106
+#: /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:114
+#: /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:122
+#: /home/ruben/Projects/Cura/resources/qml/PrintMonitor.qml:156
msgctxt "@label"
msgid "Printing Time"
msgstr "Tulostusaika"
-#: /home/ruben/Projects/Cura/resources/qml/PrintMonitor.qml:130
+#: /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/Actions.qml:78
+#: /home/ruben/Projects/Cura/resources/qml/ViewsSelector.qml:50
+msgctxt "@label"
+msgid "View type"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/ObjectSelector.qml:59
+msgctxt "@label"
+msgid "Object list"
+msgstr ""
+
+#: /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:42
+msgctxt "@button"
+msgid "Sign out"
+msgstr ""
+
+#: /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:40
+msgctxt "@label"
+msgid "The next generation 3D printing workflow"
+msgstr ""
+
+#: /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 print profiles from leading brands"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Account/GeneralOperations.qml:78
+msgctxt "@button"
+msgid "Create account"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/OutputProcessWidget.qml:59
+msgctxt "@label"
+msgid "No time estimation available"
+msgstr ""
+
+#: /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:127
+msgctxt "@button"
+msgid "Preview"
+msgstr ""
+
+#: /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:67
+msgctxt "@label:PrintjobStatus"
+msgid "Unable to slice"
+msgstr ""
+
+#: /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:104
+msgctxt "@label"
+msgid "Start the slicing process"
+msgstr ""
+
+#: /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 estimation"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/PrintJobInformation.qml:114
+msgctxt "@label"
+msgid "Material estimation"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/PrintJobInformation.qml:164
+msgctxt "@label m for meter"
+msgid "%1m"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/PrintJobInformation.qml:165
+msgctxt "@label g for grams"
+msgid "%1g"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/PrinterSelector/MachineSelectorList.qml:19
+msgctxt "@label"
+msgid "Connected printers"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/PrinterSelector/MachineSelectorList.qml:19
+msgctxt "@label"
+msgid "Preset printers"
+msgstr ""
+
+#: /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:182
+msgctxt "@button"
+msgid "Manage printers"
+msgstr ""
+
+#: /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:88
msgctxt "@action:inmenu"
msgid "Toggle Full Screen"
msgstr "Vaihda koko näyttöön"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:85
+#: /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:95
+#: /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:105
+#: /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:113
+#: /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:120
+#: /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:127
+#: /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:134
+#: /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:141
+#: /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:148
+#: /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:155
+#: /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:161
+#: /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:168
+#: /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:176
+#: /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:184
+#: /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:196
+#: /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:202
+#: /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:209
+#: /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:217
+#: /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:225
+#: /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:232
+#: /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:242
+#: /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:251
+#: /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:260
+#: /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:268
+#: /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:274
+#: /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:294
+#: /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:304
+#: /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:314
+#: /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:321
+#: /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:331
+#: /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:341
+#: /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:350
+#: /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:357
+#: /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:365
+#: /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:372
+#: /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:379
+#: /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:386
+#: /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:394
+#: /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:401
-msgctxt "@action:inmenu menubar:help"
-msgid "Show Engine &Log..."
-msgstr "Näytä moottorin l&oki"
-
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:409
+#: /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:423
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:441
msgctxt "@action:menu"
-msgid "Browse packages..."
+msgid "&Marketplace"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:430
-msgctxt "@action:inmenu menubar:view"
-msgid "Expand/Collapse Sidebar"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:27
-msgctxt "@label:PrintjobStatus"
-msgid "Please load a 3D model"
-msgstr "Lataa 3D-malli"
-
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:37
-msgctxt "@label:PrintjobStatus"
-msgid "Ready to slice"
-msgstr "Valmiina viipaloimaan"
-
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:39
-msgctxt "@label:PrintjobStatus"
-msgid "Slicing..."
-msgstr "Viipaloidaan..."
-
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:41
-msgctxt "@label:PrintjobStatus %1 is target operation"
-msgid "Ready to %1"
-msgstr "Valmis: %1"
-
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:43
-msgctxt "@label:PrintjobStatus"
-msgid "Unable to Slice"
-msgstr "Viipalointi ei onnistu"
-
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:45
-msgctxt "@label:PrintjobStatus"
-msgid "Slicing unavailable"
-msgstr "Viipalointi ei käytettävissä"
-
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:172
-msgctxt "@info:tooltip"
-msgid "Slice current printjob"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:172
-msgctxt "@info:tooltip"
-msgid "Cancel slicing process"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:184
-msgctxt "@label:Printjob"
-msgid "Prepare"
-msgstr "Valmistele"
-
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:184
-msgctxt "@label:Printjob"
-msgid "Cancel"
-msgstr "Peruuta"
-
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:320
-msgctxt "@info:tooltip"
-msgid "Select the active output device"
-msgstr "Valitse aktiivinen tulostusväline"
-
-#: /home/ruben/Projects/Cura/resources/qml/OpenFilesIncludingProjectsDialog.qml:19
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:760
-msgctxt "@title:window"
-msgid "Open file(s)"
-msgstr "Avaa tiedosto(t)"
-
-#: /home/ruben/Projects/Cura/resources/qml/OpenFilesIncludingProjectsDialog.qml:64
-msgctxt "@text:window"
-msgid "We have found one or more project file(s) within the files you have selected. You can open only one project file at a time. We suggest to only import models from those files. Would you like to proceed?"
-msgstr "Löysimme vähintään yhden projektitiedoston valitsemiesi tiedostojen joukosta. Voit avata vain yhden projektitiedoston kerrallaan. Suosittelemme, että tuot vain malleja niistä tiedostoista. Haluatko jatkaa?"
-
-#: /home/ruben/Projects/Cura/resources/qml/OpenFilesIncludingProjectsDialog.qml:99
-msgctxt "@action:button"
-msgid "Import all as models"
-msgstr "Tuo kaikki malleina"
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:19
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:24
msgctxt "@title:window"
msgid "Ultimaker Cura"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:104
-msgctxt "@title:menu menubar:toplevel"
-msgid "&File"
-msgstr "Tie&dosto"
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:120
-msgctxt "@title:menu menubar:file"
-msgid "&Save..."
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:141
-msgctxt "@title:menu menubar:file"
-msgid "&Export..."
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:151
-msgctxt "@action:inmenu menubar:file"
-msgid "Export Selection..."
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:168
-msgctxt "@title:menu menubar:toplevel"
-msgid "&Edit"
-msgstr "&Muokkaa"
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:185
-msgctxt "@title:menu"
-msgid "&View"
-msgstr "&Näytä"
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:190
-msgctxt "@title:menu"
-msgid "&Settings"
-msgstr "&Asetukset"
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:192
-msgctxt "@title:menu menubar:settings"
-msgid "&Printer"
-msgstr "&Tulostin"
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:201
-msgctxt "@title:menu"
-msgid "&Material"
-msgstr "&Materiaali"
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:210
-msgctxt "@action:inmenu"
-msgid "Set as Active Extruder"
-msgstr "Aseta aktiiviseksi suulakepuristimeksi"
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:216
-#: /home/ruben/Projects/Cura/resources/qml/SidebarHeader.qml:188
-msgctxt "@action:inmenu"
-msgid "Enable Extruder"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:223
-#: /home/ruben/Projects/Cura/resources/qml/SidebarHeader.qml:194
-msgctxt "@action:inmenu"
-msgid "Disable Extruder"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:235
-msgctxt "@title:menu"
-msgid "&Build plate"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:236
-msgctxt "@title:settings"
-msgid "&Profile"
-msgstr "&Profiili"
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:246
-msgctxt "@title:menu menubar:toplevel"
-msgid "E&xtensions"
-msgstr "Laa&jennukset"
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:280
-msgctxt "@title:menu menubar:toplevel"
-msgid "&Toolbox"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:287
-msgctxt "@title:menu menubar:toplevel"
-msgid "P&references"
-msgstr "L&isäasetukset"
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:295
-msgctxt "@title:menu menubar:toplevel"
-msgid "&Help"
-msgstr "&Ohje"
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:341
+#: /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:370
-msgctxt "@action:button"
-msgid "Open File"
-msgstr "Avaa tiedosto"
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:540
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:413
msgctxt "@title:tab"
msgid "Settings"
msgstr "Asetukset"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:586
-msgctxt "@title:window"
-msgid "New project"
-msgstr "Uusi projekti"
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:587
-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."
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:715
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:539
msgctxt "@title:window"
msgid "Closing Cura"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:716
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:728
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:540
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:552
msgctxt "@label"
msgid "Are you sure you want to exit Cura?"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:861
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:590
+#: /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:691
msgctxt "@window:title"
msgid "Install Package"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:868
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:699
msgctxt "@title:window"
msgid "Open File(s)"
msgstr "Avaa tiedosto(t)"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:871
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:702
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/WorkspaceSummaryDialog.qml:14
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:805
msgctxt "@title:window"
-msgid "Save Project"
-msgstr "Tallenna projekti"
+msgid "Add Printer"
+msgstr "Lisää tulostin"
-#: /home/ruben/Projects/Cura/resources/qml/WorkspaceSummaryDialog.qml:120
-msgctxt "@action:label"
-msgid ""
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:813
+msgctxt "@title:window"
+msgid "What's New"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/WorkspaceSummaryDialog.qml:137
-msgctxt "@action:label"
-msgid "Build plate"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/WorkspaceSummaryDialog.qml:169
-msgctxt "@action:label"
-msgid "Extruder %1"
-msgstr "Suulake %1"
-
-#: /home/ruben/Projects/Cura/resources/qml/WorkspaceSummaryDialog.qml:179
-msgctxt "@action:label"
-msgid "%1 & material"
-msgstr "%1 & materiaali"
-
-#: /home/ruben/Projects/Cura/resources/qml/WorkspaceSummaryDialog.qml:268
-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/WorkspaceSummaryDialog.qml:287
-msgctxt "@action:button"
-msgid "Save"
-msgstr "Tallenna"
-
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:192
-msgctxt "@label"
-msgid "Layer Height"
-msgstr "Kerroksen korkeus"
-
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:277
-msgctxt "@tooltip"
-msgid "This quality profile is not available for you current material and nozzle configuration. Please change these to enable this quality profile"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:450
-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/SidebarSimple.qml:467
-msgctxt "@label"
-msgid "Print Speed"
-msgstr "Tulostusnopeus"
-
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:479
-msgctxt "@label"
-msgid "Slower"
-msgstr "Hitaammin"
-
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:490
-msgctxt "@label"
-msgid "Faster"
-msgstr "Nopeammin"
-
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:518
-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/SidebarSimple.qml:541
-msgctxt "@label"
-msgid "Infill"
-msgstr "Täyttö"
-
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:777
-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/SidebarSimple.qml:789
-msgctxt "@label"
-msgid "Enable gradual"
-msgstr "Ota asteittainen käyttöön"
-
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:856
-msgctxt "@label"
-msgid "Generate Support"
-msgstr "Muodosta tuki"
-
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:890
-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/SidebarSimple.qml:962
-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/SidebarSimple.qml:985
-msgctxt "@label"
-msgid "Build Plate Adhesion"
-msgstr "Alustan tarttuvuus"
-
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:1040
-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/SidebarSimple.qml:1080
-msgctxt "@label"
-msgid "Need help improving your prints? Read the Ultimaker Troubleshooting Guides"
-msgstr "Tarvitsetko apua tulosteiden parantamiseen? Lue Ultimakerin vianmääritysoppaat"
-
#: /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"
@@ -4390,74 +4558,480 @@ msgid_plural "Print Selected Models with %1"
msgstr[0] "Tulosta valittu malli asetuksella %1"
msgstr[1] "Tulosta valitut mallit asetuksella %1"
-#: /home/ruben/Projects/Cura/resources/qml/AskOpenAsProjectOrModelsDialog.qml:20
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/DiscardOrKeepProfileChangesDialog.qml:15
+msgctxt "@title:window"
+msgid "Discard or Keep changes"
+msgstr "Hylkää tai säilytä muutokset"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/DiscardOrKeepProfileChangesDialog.qml:57
+msgctxt "@text:window"
+msgid ""
+"You have customized some profile settings.\n"
+"Would you like to keep or discard those settings?"
+msgstr ""
+"Olet mukauttanut profiilin asetuksia.\n"
+"Haluatko säilyttää vai hylätä nämä asetukset?"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/DiscardOrKeepProfileChangesDialog.qml:110
+msgctxt "@title:column"
+msgid "Profile settings"
+msgstr "Profiilin asetukset"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/DiscardOrKeepProfileChangesDialog.qml:117
+msgctxt "@title:column"
+msgid "Default"
+msgstr "Oletusarvo"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/DiscardOrKeepProfileChangesDialog.qml:124
+msgctxt "@title:column"
+msgid "Customized"
+msgstr "Mukautettu"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/DiscardOrKeepProfileChangesDialog.qml:158
+msgctxt "@option:discardOrKeep"
+msgid "Discard and never ask again"
+msgstr "Hylkää äläkä kysy uudelleen"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/DiscardOrKeepProfileChangesDialog.qml:159
+msgctxt "@option:discardOrKeep"
+msgid "Keep and never ask again"
+msgstr "Säilytä äläkä kysy uudelleen"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/DiscardOrKeepProfileChangesDialog.qml:196
+msgctxt "@action:button"
+msgid "Discard"
+msgstr "Hylkää"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/DiscardOrKeepProfileChangesDialog.qml:209
+msgctxt "@action:button"
+msgid "Keep"
+msgstr "Säilytä"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/DiscardOrKeepProfileChangesDialog.qml:222
+msgctxt "@action:button"
+msgid "Create New Profile"
+msgstr "Luo uusi profiili"
+
+#: /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
+msgctxt "@label"
+msgid "version: %1"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:71
+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
+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 ""
+"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
+msgctxt "@label"
+msgid "Graphical user interface"
+msgstr "Graafinen käyttöliittymä"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:135
+msgctxt "@label"
+msgid "Application framework"
+msgstr "Sovelluskehys"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:136
+msgctxt "@label"
+msgid "G-code generator"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:137
+msgctxt "@label"
+msgid "Interprocess communication library"
+msgstr "Prosessien välinen tietoliikennekirjasto"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:139
+msgctxt "@label"
+msgid "Programming language"
+msgstr "Ohjelmointikieli"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:140
+msgctxt "@label"
+msgid "GUI framework"
+msgstr "GUI-kehys"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:141
+msgctxt "@label"
+msgid "GUI framework bindings"
+msgstr "GUI-kehyksen sidonnat"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:142
+msgctxt "@label"
+msgid "C/C++ Binding library"
+msgstr "C/C++ -sidontakirjasto"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:143
+msgctxt "@label"
+msgid "Data interchange format"
+msgstr "Data Interchange Format"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:144
+msgctxt "@label"
+msgid "Support library for scientific computing"
+msgstr "Tieteellisen laskennan tukikirjasto"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:145
+msgctxt "@label"
+msgid "Support library for faster math"
+msgstr "Nopeamman laskennan tukikirjasto"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:146
+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
+msgctxt "@label"
+msgid "Support library for handling planar objects"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:148
+msgctxt "@label"
+msgid "Support library for handling triangular meshes"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:149
+msgctxt "@label"
+msgid "Support library for analysis of complex networks"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:150
+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
+msgctxt "@label"
+msgid "Support library for file metadata and streaming"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:152
+msgctxt "@label"
+msgid "Serial communication library"
+msgstr "Sarjatietoliikennekirjasto"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:153
+msgctxt "@label"
+msgid "ZeroConf discovery library"
+msgstr "ZeroConf-etsintäkirjasto"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:154
+msgctxt "@label"
+msgid "Polygon clipping library"
+msgstr "Monikulmion leikkauskirjasto"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:155
+msgctxt "@Label"
+msgid "Python HTTP library"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:157
+msgctxt "@label"
+msgid "Font"
+msgstr "Fontti"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:158
+msgctxt "@label"
+msgid "SVG icons"
+msgstr "SVG-kuvakkeet"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:159
+msgctxt "@label"
+msgid "Linux cross-distribution application deployment"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/OpenFilesIncludingProjectsDialog.qml:64
+msgctxt "@text:window"
+msgid "We have found one or more project file(s) within the files you have selected. You can open only one project file at a time. We suggest to only import models from those files. Would you like to proceed?"
+msgstr "Löysimme vähintään yhden projektitiedoston valitsemiesi tiedostojen joukosta. Voit avata vain yhden projektitiedoston kerrallaan. Suosittelemme, että tuot vain malleja niistä tiedostoista. Haluatko jatkaa?"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/OpenFilesIncludingProjectsDialog.qml:99
+msgctxt "@action:button"
+msgid "Import all as models"
+msgstr "Tuo kaikki malleina"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:15
+msgctxt "@title:window"
+msgid "Save Project"
+msgstr "Tallenna projekti"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:149
+msgctxt "@action:label"
+msgid "Build plate"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:183
+msgctxt "@action:label"
+msgid "Extruder %1"
+msgstr "Suulake %1"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:198
+msgctxt "@action:label"
+msgid "%1 & material"
+msgstr "%1 & materiaali"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:200
+msgctxt "@action:label"
+msgid "Material"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:272
+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:291
+msgctxt "@action:button"
+msgid "Save"
+msgstr "Tallenna"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AskOpenAsProjectOrModelsDialog.qml:20
msgctxt "@title:window"
msgid "Open project file"
msgstr "Avaa projektitiedosto"
-#: /home/ruben/Projects/Cura/resources/qml/AskOpenAsProjectOrModelsDialog.qml:93
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AskOpenAsProjectOrModelsDialog.qml:93
msgctxt "@text:window"
msgid "This is a Cura project file. Would you like to open it as a project or import the models from it?"
msgstr "Tämä on Cura-projektitiedosto. Haluatko avata sen projektina vai tuoda siinä olevat mallit?"
-#: /home/ruben/Projects/Cura/resources/qml/AskOpenAsProjectOrModelsDialog.qml:103
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AskOpenAsProjectOrModelsDialog.qml:103
msgctxt "@text:window"
msgid "Remember my choice"
msgstr "Muista valintani"
-#: /home/ruben/Projects/Cura/resources/qml/AskOpenAsProjectOrModelsDialog.qml:122
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AskOpenAsProjectOrModelsDialog.qml:122
msgctxt "@action:button"
msgid "Open as project"
msgstr "Avaa projektina"
-#: /home/ruben/Projects/Cura/resources/qml/AskOpenAsProjectOrModelsDialog.qml:131
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AskOpenAsProjectOrModelsDialog.qml:131
msgctxt "@action:button"
msgid "Import models"
msgstr "Tuo mallit"
-#: /home/ruben/Projects/Cura/resources/qml/EngineLog.qml:15
-msgctxt "@title:window"
-msgid "Engine Log"
-msgstr "Moottorin loki"
-
-#: /home/ruben/Projects/Cura/resources/qml/SidebarHeader.qml:70
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/DropDownWidget.qml:93
msgctxt "@label"
-msgid "Printer type"
+msgid "Empty"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/SidebarHeader.qml:376
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddNetworkOrLocalPrinterContent.qml:24
msgctxt "@label"
-msgid "Material"
-msgstr "Materiaali"
+msgid "Add a printer"
+msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/SidebarHeader.qml:543
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddNetworkOrLocalPrinterContent.qml:39
msgctxt "@label"
-msgid "Use glue with this material combination"
+msgid "Add a networked printer"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/SidebarHeader.qml:575
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddNetworkOrLocalPrinterContent.qml:81
msgctxt "@label"
-msgid "Check compatibility"
+msgid "Add a non-networked printer"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/SidebarHeader.qml:593
-msgctxt "@tooltip"
-msgid "Click to check the material compatibility on Ultimaker.com."
-msgstr "Napsauta ja tarkista materiaalin yhteensopivuus sivustolla Ultimaker.com."
-
-#: /home/ruben/Projects/Cura/resources/qml/ObjectsList.qml:211
-msgctxt "@option:check"
-msgid "See only current build plate"
+#: /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/ObjectsList.qml:227
-msgctxt "@action:button"
-msgid "Arrange to all build plates"
+#: /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/ObjectsList.qml:247
-msgctxt "@action:button"
-msgid "Arrange current build plate"
+#: /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:207
+msgctxt "@label"
+msgid "Printer name"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddLocalPrinterScrollView.qml:220
+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 ""
#: MachineSettingsAction/plugin.json
@@ -4530,25 +5104,35 @@ msgctxt "name"
msgid "God Mode"
msgstr "Jumala-tila"
-#: ChangeLogPlugin/plugin.json
+#: FirmwareUpdater/plugin.json
msgctxt "description"
-msgid "Shows changes since latest checked version."
-msgstr "Näyttää viimeisimmän tarkistetun version jälkeen tapahtuneet muutokset."
+msgid "Provides a machine actions for updating firmware."
+msgstr ""
-#: ChangeLogPlugin/plugin.json
+#: FirmwareUpdater/plugin.json
msgctxt "name"
-msgid "Changelog"
-msgstr "Muutosloki"
+msgid "Firmware Updater"
+msgstr ""
#: ProfileFlattener/plugin.json
msgctxt "description"
-msgid "Create a flattend quality changes profile."
-msgstr "Luo tasoitettu laatumuutosten profiili."
+msgid "Create a flattened quality changes profile."
+msgstr ""
#: ProfileFlattener/plugin.json
msgctxt "name"
-msgid "Profile flatener"
-msgstr "Profiilin tasoitus"
+msgid "Profile Flattener"
+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"
@@ -4560,26 +5144,6 @@ msgctxt "name"
msgid "USB printing"
msgstr "USB-tulostus"
-#: UserAgreement/plugin.json
-msgctxt "description"
-msgid "Ask the user once if he/she agrees with our license."
-msgstr ""
-
-#: UserAgreement/plugin.json
-msgctxt "name"
-msgid "UserAgreement"
-msgstr ""
-
-#: X3GWriter/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 ""
-
-#: X3GWriter/plugin.json
-msgctxt "name"
-msgid "X3GWriter"
-msgstr ""
-
#: GCodeGzWriter/plugin.json
msgctxt "description"
msgid "Writes g-code to a compressed archive."
@@ -4630,6 +5194,16 @@ msgctxt "name"
msgid "UM3 Network Connection"
msgstr "UM3-verkkoyhteys"
+#: SettingsGuide/plugin.json
+msgctxt "description"
+msgid "Provides extra information and explanations about settings in Cura, with images and animations."
+msgstr ""
+
+#: SettingsGuide/plugin.json
+msgctxt "name"
+msgid "Settings Guide"
+msgstr ""
+
#: MonitorStage/plugin.json
msgctxt "description"
msgid "Provides a monitor stage in Cura."
@@ -4690,6 +5264,16 @@ 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."
@@ -4770,6 +5354,16 @@ 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."
@@ -4780,6 +5374,16 @@ 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."
@@ -4790,6 +5394,16 @@ 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."
@@ -4880,6 +5494,16 @@ 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."
@@ -4910,6 +5534,16 @@ 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.)."
@@ -4930,6 +5564,319 @@ msgctxt "name"
msgid "Cura Profile Reader"
msgstr "Cura-profiilin lukija"
+#~ 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"
+
+#~ msgctxt "@info:status"
+#~ msgid "Nothing to slice because none of the models fit the build volume. Please scale or rotate models to fit."
+#~ msgstr "Ei viipaloitavaa, koska mikään malleista ei sovellu tulostustilavuuteen. Skaalaa tai pyöritä mallia, kunnes se on sopiva."
+
+#~ msgctxt "@info:status"
+#~ msgid "The selected material is incompatible with the selected machine or configuration."
+#~ msgstr "Valittu materiaali ei sovellu käytettäväksi valitun laitteen tai kokoonpanon kanssa."
+
+#~ msgctxt "@info:title"
+#~ msgid "Incompatible Material"
+#~ msgstr "Yhteensopimaton materiaali"
+
+#~ msgctxt "@info:status Don't translate the XML tags or !"
+#~ msgid "Failed to import profile from {0}: {1}"
+#~ msgstr "Profiilin tuonti epäonnistui tiedostosta {0}: {1}"
+
+#~ msgctxt "@label:status"
+#~ msgid "Preparing"
+#~ msgstr "Valmistellaan"
+
+#~ msgctxt "@label"
+#~ msgid "Printing"
+#~ msgstr "Tulostetaan"
+
+#~ msgctxt "@action:button"
+#~ msgid "Activate Configuration"
+#~ msgstr "Aktivoi määritys"
+
+#~ msgctxt "@info:tooltip"
+#~ msgid "Load the configuration of the printer into Cura"
+#~ msgstr "Lataa tulostimen määritys Curaan"
+
+#~ msgctxt "@label"
+#~ msgid "Show Travels"
+#~ msgstr "Näytä siirtoliikkeet"
+
+#~ msgctxt "@label"
+#~ msgid "Show Helpers"
+#~ msgstr "Näytä avustimet"
+
+#~ msgctxt "@label"
+#~ msgid "Show Shell"
+#~ msgstr "Näytä kuori"
+
+#~ msgctxt "@label"
+#~ msgid "Show Infill"
+#~ msgstr "Näytä täyttö"
+
+#~ msgctxt "@label"
+#~ msgid "Printer type:"
+#~ msgstr "Tulostimen tyyppi:"
+
+#~ msgctxt "@label"
+#~ msgid "Connection:"
+#~ msgstr "Yhteys:"
+
+#~ msgctxt "@label"
+#~ msgid "State:"
+#~ msgstr "Tila:"
+
+#~ msgctxt "@label:MonitorStatus"
+#~ msgid "Waiting for a printjob"
+#~ msgstr "Odotetaan tulostustyötä"
+
+#~ msgctxt "@label:MonitorStatus"
+#~ msgid "Waiting for someone to clear the build plate"
+#~ msgstr "Odotetaan tulostusalustan tyhjennystä"
+
+#~ msgctxt "@label:MonitorStatus"
+#~ msgid "Aborting print..."
+#~ msgstr "Keskeytetään tulostus..."
+
+#~ msgctxt "@label"
+#~ msgid "Protected profiles"
+#~ msgstr "Suojatut profiilit"
+
+#~ msgctxt "@label"
+#~ msgid "Printer Name:"
+#~ msgstr "Tulostimen nimi:"
+
+#~ msgctxt "@label"
+#~ msgid "Profile:"
+#~ msgstr "Profiili:"
+
+#~ msgctxt "@label:textbox"
+#~ msgid "Search..."
+#~ msgstr "Haku..."
+
+#~ msgctxt "@label:listbox"
+#~ msgid "Print Setup"
+#~ msgstr "Tulostuksen asennus"
+
+#~ msgctxt "@label:listbox"
+#~ msgid ""
+#~ "Print Setup disabled\n"
+#~ "G-code files cannot be modified"
+#~ msgstr ""
+#~ "Tulostuksen asennus ei käytössä\n"
+#~ "G-code-tiedostoja ei voida muokata"
+
+#~ msgctxt "@tooltip"
+#~ msgid "Recommended Print Setup
Print with the recommended settings for the selected printer, material and quality."
+#~ msgstr "Suositeltu tulostuksen asennus
Tulosta valitun tulostimen, materiaalin ja laadun suositelluilla asetuksilla."
+
+#~ msgctxt "@tooltip"
+#~ msgid "Custom Print Setup
Print with finegrained control over every last bit of the slicing process."
+#~ msgstr "Mukautettu tulostuksen asennus
Tulosta hallitsemalla täysin kaikkia viipalointiprosessin vaiheita."
+
+#~ msgctxt "@action:inmenu menubar:help"
+#~ msgid "Show Engine &Log..."
+#~ msgstr "Näytä moottorin l&oki"
+
+#~ msgctxt "@label:PrintjobStatus"
+#~ msgid "Please load a 3D model"
+#~ msgstr "Lataa 3D-malli"
+
+#~ msgctxt "@label:PrintjobStatus"
+#~ msgid "Ready to slice"
+#~ msgstr "Valmiina viipaloimaan"
+
+#~ msgctxt "@label:PrintjobStatus %1 is target operation"
+#~ msgid "Ready to %1"
+#~ msgstr "Valmis: %1"
+
+#~ msgctxt "@label:PrintjobStatus"
+#~ msgid "Slicing unavailable"
+#~ msgstr "Viipalointi ei käytettävissä"
+
+#~ msgctxt "@label:Printjob"
+#~ msgid "Prepare"
+#~ msgstr "Valmistele"
+
+#~ msgctxt "@label:Printjob"
+#~ msgid "Cancel"
+#~ msgstr "Peruuta"
+
+#~ msgctxt "@info:tooltip"
+#~ msgid "Select the active output device"
+#~ msgstr "Valitse aktiivinen tulostusväline"
+
+#~ msgctxt "@title:menu"
+#~ msgid "&View"
+#~ msgstr "&Näytä"
+
+#~ msgctxt "@title:menu"
+#~ msgid "&Settings"
+#~ msgstr "&Asetukset"
+
+#~ msgctxt "@action:button"
+#~ msgid "Open File"
+#~ msgstr "Avaa tiedosto"
+
+#~ msgctxt "@label"
+#~ msgid "Print Speed"
+#~ msgstr "Tulostusnopeus"
+
+#~ msgctxt "@label"
+#~ msgid "Slower"
+#~ msgstr "Hitaammin"
+
+#~ msgctxt "@label"
+#~ msgid "Faster"
+#~ msgstr "Nopeammin"
+
+#~ msgctxt "@label"
+#~ msgid "Enable gradual"
+#~ msgstr "Ota asteittainen käyttöön"
+
+#~ msgctxt "@label"
+#~ msgid "Generate Support"
+#~ msgstr "Muodosta tuki"
+
+#~ msgctxt "@label"
+#~ msgid "Build Plate Adhesion"
+#~ msgstr "Alustan tarttuvuus"
+
+#~ msgctxt "@label"
+#~ msgid "Need help improving your prints? Read the Ultimaker Troubleshooting Guides"
+#~ msgstr "Tarvitsetko apua tulosteiden parantamiseen? Lue Ultimakerin vianmääritysoppaat"
+
+#~ msgctxt "@title:window"
+#~ msgid "Engine Log"
+#~ msgstr "Moottorin loki"
+
+#~ msgctxt "@tooltip"
+#~ msgid "Click to check the material compatibility on Ultimaker.com."
+#~ msgstr "Napsauta ja tarkista materiaalin yhteensopivuus sivustolla Ultimaker.com."
+
+#~ msgctxt "description"
+#~ msgid "Shows changes since latest checked version."
+#~ msgstr "Näyttää viimeisimmän tarkistetun version jälkeen tapahtuneet muutokset."
+
+#~ msgctxt "name"
+#~ msgid "Changelog"
+#~ msgstr "Muutosloki"
+
+#~ msgctxt "description"
+#~ msgid "Create a flattend quality changes profile."
+#~ msgstr "Luo tasoitettu laatumuutosten profiili."
+
+#~ msgctxt "name"
+#~ msgid "Profile flatener"
+#~ msgstr "Profiilin tasoitus"
+
+#~ msgctxt "@action"
+#~ msgid "Upgrade Firmware"
+#~ msgstr "Päivitä laiteohjelmisto"
+
+#~ msgctxt "@title"
+#~ msgid "Upgrade Firmware"
+#~ msgstr "Laiteohjelmiston päivitys"
+
#~ msgctxt "@action:button"
#~ msgid "Print with Doodle3D WiFi-Box"
#~ msgstr "Tulostus Doodle3D WiFi-Boxin avulla"
@@ -5052,7 +5999,7 @@ msgstr "Cura-profiilin lukija"
#~ 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 381991d5e4..949d9518a5 100644
--- a/resources/i18n/fi_FI/fdmextruder.def.json.po
+++ b/resources/i18n/fi_FI/fdmextruder.def.json.po
@@ -1,13 +1,13 @@
# Cura JSON setting files
-# Copyright (C) 2018 Ultimaker
+# Copyright (C) 2019 Ultimaker B.V.
# This file is distributed under the same license as the Cura package.
-# Ruben Dulek , 2018.
+# Ruben Dulek , 2019.
#
msgid ""
msgstr ""
-"Project-Id-Version: Cura 3.5\n"
+"Project-Id-Version: Cura 4.2\n"
"Report-Msgid-Bugs-To: r.dulek@ultimaker.com\n"
-"POT-Creation-Date: 2018-09-19 17:07+0000\n"
+"POT-Creation-Date: 2019-07-16 14:38+0000\n"
"PO-Revision-Date: 2017-08-11 14:31+0200\n"
"Last-Translator: Bothof \n"
"Language-Team: Finnish\n"
@@ -83,8 +83,8 @@ msgstr "Suulakkeen aloitus-GCode"
#: fdmextruder.def.json
msgctxt "machine_extruder_start_code description"
-msgid "Start g-code to execute whenever turning the extruder on."
-msgstr "Aloitus-GCode, joka suoritetaan suulakkeen käynnistyksen yhteydessä."
+msgid "Start g-code to execute when switching to this extruder."
+msgstr ""
#: fdmextruder.def.json
msgctxt "machine_extruder_start_pos_abs label"
@@ -123,8 +123,8 @@ msgstr "Suulakkeen lopetus-GCode"
#: fdmextruder.def.json
msgctxt "machine_extruder_end_code description"
-msgid "End g-code to execute whenever turning the extruder off."
-msgstr "Lopetus-GCode, joka suoritetaan, kun suulake poistetaan käytöstä."
+msgid "End g-code to execute when switching away from this extruder."
+msgstr ""
#: fdmextruder.def.json
msgctxt "machine_extruder_end_pos_abs label"
@@ -166,6 +166,16 @@ msgctxt "extruder_prime_pos_z description"
msgid "The Z coordinate of the position where the nozzle primes at the start of printing."
msgstr "Z-koordinaatti sijainnille, jossa suutin esitäytetään tulostusta aloitettaessa."
+#: fdmextruder.def.json
+msgctxt "machine_extruder_cooling_fan_number label"
+msgid "Extruder Print Cooling Fan"
+msgstr ""
+
+#: fdmextruder.def.json
+msgctxt "machine_extruder_cooling_fan_number description"
+msgid "The number of the print cooling fan associated with this extruder. Only change this from the default value of 0 when you have a different print cooling fan for each extruder."
+msgstr ""
+
#: fdmextruder.def.json
msgctxt "platform_adhesion label"
msgid "Build Plate Adhesion"
@@ -215,3 +225,11 @@ msgstr ""
msgctxt "material_diameter description"
msgid "Adjusts the diameter of the filament used. Match this value with the diameter of the used filament."
msgstr ""
+
+#~ msgctxt "machine_extruder_start_code description"
+#~ msgid "Start g-code to execute whenever turning the extruder on."
+#~ msgstr "Aloitus-GCode, joka suoritetaan suulakkeen käynnistyksen yhteydessä."
+
+#~ msgctxt "machine_extruder_end_code description"
+#~ msgid "End g-code to execute whenever turning the extruder off."
+#~ msgstr "Lopetus-GCode, joka suoritetaan, kun suulake poistetaan käytöstä."
diff --git a/resources/i18n/fi_FI/fdmprinter.def.json.po b/resources/i18n/fi_FI/fdmprinter.def.json.po
index 6c1decafbf..39bc17831d 100644
--- a/resources/i18n/fi_FI/fdmprinter.def.json.po
+++ b/resources/i18n/fi_FI/fdmprinter.def.json.po
@@ -1,13 +1,13 @@
# Cura JSON setting files
-# Copyright (C) 2018 Ultimaker
+# Copyright (C) 2019 Ultimaker B.V.
# This file is distributed under the same license as the Cura package.
-# Ruben Dulek , 2018.
+# Ruben Dulek , 2019.
#
msgid ""
msgstr ""
-"Project-Id-Version: Cura 3.5\n"
+"Project-Id-Version: Cura 4.2\n"
"Report-Msgid-Bugs-To: r.dulek@ultimaker.com\n"
-"POT-Creation-Date: 2018-09-19 17:07+0000\n"
+"POT-Creation-Date: 2019-07-16 14:38+0000\n"
"PO-Revision-Date: 2017-09-27 12:27+0200\n"
"Last-Translator: Bothof \n"
"Language-Team: Finnish\n"
@@ -232,7 +232,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 +242,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 +252,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 +262,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 +272,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 +302,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 +312,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 +332,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 +397,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 +417,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 +427,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 +437,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 +467,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"
@@ -1072,7 +1072,7 @@ msgstr ""
#: fdmprinter.def.json
msgctxt "connect_skin_polygons description"
-msgid "Connect top/bottom skin paths where they run next to each other. For the concentric pattern enabling this setting greatly reduces the travel time, but because the connections can happend midway over infill this feature can reduce the top surface quality."
+msgid "Connect top/bottom skin paths where they run next to each other. For the concentric pattern enabling this setting greatly reduces the travel time, but because the connections can happen midway over infill this feature can reduce the top surface quality."
msgstr ""
#: fdmprinter.def.json
@@ -1292,8 +1292,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 +1315,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 +1332,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"
@@ -1492,7 +1497,7 @@ msgstr "Täyttökuvio"
#: fdmprinter.def.json
msgctxt "infill_pattern description"
-msgid "The pattern of the infill material of the print. The line and zig zag infill swap direction on alternate layers, reducing material cost. The grid, triangle, tri-hexagon, cubic, octet, quarter cubic, cross and concentric patterns are fully printed every layer. Cubic, quarter cubic and octet infill change with every layer to provide a more equal distribution of strength over each direction."
+msgid "The pattern of the infill material of the print. The line and zig zag infill swap direction on alternate layers, reducing material cost. The grid, triangle, tri-hexagon, cubic, octet, quarter cubic, cross and concentric patterns are fully printed every layer. Gyroid, cubic, quarter cubic and octet infill change with every layer to provide a more equal distribution of strength over each direction."
msgstr ""
#: fdmprinter.def.json
@@ -1555,6 +1560,11 @@ msgctxt "infill_pattern option cross_3d"
msgid "Cross 3D"
msgstr "Risti 3D"
+#: fdmprinter.def.json
+msgctxt "infill_pattern option gyroid"
+msgid "Gyroid"
+msgstr ""
+
#: fdmprinter.def.json
msgctxt "zig_zaggify_infill label"
msgid "Connect Infill Lines"
@@ -1664,7 +1674,7 @@ msgstr "Pintakalvon limityksen prosentti"
#: fdmprinter.def.json
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."
+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
@@ -1674,8 +1684,8 @@ msgstr "Pintakalvon limitys"
#: fdmprinter.def.json
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."
+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"
@@ -1857,6 +1867,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"
@@ -1967,6 +1987,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"
@@ -1977,6 +2077,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"
@@ -2094,7 +2314,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
@@ -2114,8 +2334,8 @@ msgstr "Suuttimen vaihdon takaisinvetoetäisyys"
#: fdmprinter.def.json
msgctxt "switch_extruder_retraction_amount description"
-msgid "The amount of retraction: Set at 0 for no retraction at all. This should generally be the same as the length of the heat zone."
-msgstr "Takaisinvedon määrä: 0 tarkoittaa, että takaisinvetoa ei ole lainkaan. Tämän on yleensä oltava sama kuin lämpöalueen pituus."
+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 ""
#: fdmprinter.def.json
msgctxt "switch_extruder_retraction_speeds label"
@@ -2147,6 +2367,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"
@@ -2338,14 +2568,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"
@@ -2774,7 +3004,7 @@ msgstr "Pyyhkäisytila"
#: 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 and also to only comb within the infill. Note that the 'Within Infill' option behaves exactly like the 'Not in Skin' option in earlier Cura releases."
+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 ""
#: fdmprinter.def.json
@@ -2917,6 +3147,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"
@@ -3187,6 +3427,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"
@@ -3257,6 +3502,36 @@ msgctxt "support_infill_angle description"
msgid "Orientation of the infill pattern for supports. The support infill pattern is rotated in the horizontal plane."
msgstr ""
+#: fdmprinter.def.json
+msgctxt "support_brim_enable label"
+msgid "Enable Support Brim"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "support_brim_enable description"
+msgid "Generate a brim within the support infill regions of the first layer. This brim is printed underneath the support, not around it. Enabling this setting increases the adhesion of support to the build plate."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "support_brim_width label"
+msgid "Support Brim Width"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "support_brim_width description"
+msgid "The width of the brim to print underneath the support. A larger brim enhances adhesion to the build plate, at the cost of some extra material."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "support_brim_line_count label"
+msgid "Support Brim Line Count"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "support_brim_line_count description"
+msgid "The number of lines used for the support brim. More brim lines enhance adhesion to the build plate, at the cost of some extra material."
+msgstr ""
+
#: fdmprinter.def.json
msgctxt "support_z_distance label"
msgid "Support Z Distance"
@@ -3354,8 +3629,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"
@@ -3397,6 +3672,16 @@ msgctxt "gradual_support_infill_step_height description"
msgid "The height of support infill of a given density before switching to half the density."
msgstr "Tietyn tiheysarvon tuen täytön korkeus ennen puoleen tiheyteen vaihtamista."
+#: fdmprinter.def.json
+msgctxt "minimum_support_area label"
+msgid "Minimum Support Area"
+msgstr ""
+
+#: 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 ""
+
#: fdmprinter.def.json
msgctxt "support_interface_enable label"
msgid "Enable Support Interface"
@@ -3622,6 +3907,66 @@ msgctxt "support_bottom_pattern option zigzag"
msgid "Zig Zag"
msgstr "Siksak"
+#: fdmprinter.def.json
+msgctxt "minimum_interface_area label"
+msgid "Minimum Support Interface Area"
+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."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "minimum_roof_area label"
+msgid "Minimum Support Roof Area"
+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."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "minimum_bottom_area label"
+msgid "Minimum Support Floor Area"
+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."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "support_interface_offset label"
+msgid "Support Interface Horizontal Expansion"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "support_interface_offset description"
+msgid "Amount of offset applied to the support interface polygons."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "support_roof_offset label"
+msgid "Support Roof Horizontal Expansion"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "support_roof_offset description"
+msgid "Amount of offset applied to the roofs of the support."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "support_bottom_offset label"
+msgid "Support Floor Horizontal Expansion"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "support_bottom_offset description"
+msgid "Amount of offset applied to the floors of the support."
+msgstr ""
+
#: fdmprinter.def.json
msgctxt "support_fan_enable label"
msgid "Fan Speed Override"
@@ -3663,14 +4008,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"
@@ -3824,6 +4169,16 @@ msgctxt "brim_line_count description"
msgid "The number of lines used for a brim. More brim lines enhance adhesion to the build plate, but also reduces the effective print area."
msgstr "Reunukseen käytettävien linjojen lukumäärä. Useampi reunuslinja parantaa kiinnitystä alustaan, mutta rajoittaa tehokasta tulostusaluetta."
+#: fdmprinter.def.json
+msgctxt "brim_replaces_support label"
+msgid "Brim Replaces Support"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "brim_replaces_support description"
+msgid "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."
+msgstr ""
+
#: fdmprinter.def.json
msgctxt "brim_outside_only label"
msgid "Brim Only on Outside"
@@ -4154,16 +4509,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"
@@ -4204,16 +4549,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"
@@ -4224,6 +4559,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"
@@ -4506,8 +4851,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"
@@ -4739,6 +5084,16 @@ 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."
+msgstr ""
+
#: fdmprinter.def.json
msgctxt "support_skip_some_zags label"
msgid "Break Up Support In Chunks"
@@ -4996,8 +5351,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"
@@ -5340,7 +5695,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
@@ -5350,7 +5705,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
@@ -5360,7 +5715,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
@@ -5370,7 +5725,7 @@ msgstr ""
#: fdmprinter.def.json
msgctxt "adaptive_layer_height_threshold label"
-msgid "Adaptive layers threshold"
+msgid "Adaptive Layers Threshold"
msgstr ""
#: fdmprinter.def.json
@@ -5588,6 +5943,156 @@ 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 "command_line_settings label"
msgid "Command Line Settings"
@@ -5648,6 +6153,102 @@ 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 "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."
+
+#~ msgctxt "switch_extruder_retraction_amount description"
+#~ msgid "The amount of retraction: Set at 0 for no retraction at all. This should generally be the same as the length of the heat zone."
+#~ msgstr "Takaisinvedon määrä: 0 tarkoittaa, että takaisinvetoa ei ole lainkaan. Tämän on yleensä oltava sama kuin lämpöalueen pituus."
+
#~ msgctxt "infill_pattern option concentric_3d"
#~ msgid "Concentric 3D"
#~ msgstr "Samankeskinen 3D"
diff --git a/resources/i18n/fr_FR/cura.po b/resources/i18n/fr_FR/cura.po
index eb7aa05b2b..41917b4933 100644
--- a/resources/i18n/fr_FR/cura.po
+++ b/resources/i18n/fr_FR/cura.po
@@ -1,24 +1,24 @@
# Cura
-# Copyright (C) 2018 Ultimaker
+# Copyright (C) 2019 Ultimaker B.V.
# This file is distributed under the same license as the Cura package.
-# Ruben Dulek , 2018.
+# Ruben Dulek , 2019.
#
msgid ""
msgstr ""
-"Project-Id-Version: Cura 3.5\n"
+"Project-Id-Version: Cura 4.2\n"
"Report-Msgid-Bugs-To: r.dulek@ultimaker.com\n"
-"POT-Creation-Date: 2018-09-19 17:07+0200\n"
-"PO-Revision-Date: 2018-09-28 14:59+0200\n"
-"Last-Translator: Bothof \n"
-"Language-Team: French\n"
+"POT-Creation-Date: 2019-07-16 14:38+0200\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:27
msgctxt "@action"
msgid "Machine Settings"
msgstr "Paramètres de la machine"
@@ -48,15 +48,15 @@ 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
msgctxt "@warning:status"
-msgid "Please generate G-code before saving."
-msgstr "Veuillez générer le G-Code avant d'enregistrer."
+msgid "Please prepare G-code before exporting."
+msgstr "Veuillez préparer le G-Code avant d'exporter."
-#: /home/ruben/Projects/Cura/plugins/ModelChecker/ModelChecker.py:30
+#: /home/ruben/Projects/Cura/plugins/ModelChecker/ModelChecker.py:31
msgctxt "@info:title"
msgid "3D Model Assistant"
msgstr "Assistant de modèle 3D"
-#: /home/ruben/Projects/Cura/plugins/ModelChecker/ModelChecker.py:80
+#: /home/ruben/Projects/Cura/plugins/ModelChecker/ModelChecker.py:90
#, python-brace-format
msgctxt "@info:status"
msgid ""
@@ -68,12 +68,12 @@ 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/ChangeLogPlugin/ChangeLog.py:32
-msgctxt "@item:inmenu"
-msgid "Show Changelog"
-msgstr "Afficher le récapitulatif des changements"
+#: /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"
@@ -85,37 +85,36 @@ 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:40
+#: /home/ruben/Projects/Cura/plugins/AMFReader/__init__.py:15
+msgctxt "@item:inlistbox"
+msgid "AMF File"
+msgstr "Fichier AMF"
+
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:37
msgctxt "@item:inmenu"
msgid "USB printing"
msgstr "Impression par USB"
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:41
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:38
msgctxt "@action:button Preceded by 'Ready to'."
msgid "Print via USB"
msgstr "Imprimer via USB"
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:42
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:39
msgctxt "@info:tooltip"
msgid "Print via USB"
msgstr "Imprimer via USB"
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:83
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:75
msgctxt "@info:status"
msgid "Connected via USB"
msgstr "Connecté via USB"
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:103
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:100
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/X3GWriter/build/GPX-prefix/src/GPX/slicerplugins/cura15.06/X3gWriter/__init__.py:16
msgctxt "X3g Writer Plugin Description"
msgid "Writes X3g to files"
@@ -126,6 +125,11 @@ msgctxt "X3g Writer File Description"
msgid "X3g File"
msgstr "Fichier X3G"
+#: /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/GCodeGzWriter/__init__.py:17
#: /home/ruben/Projects/Cura/plugins/GCodeGzReader/__init__.py:17
msgctxt "@item:inlistbox"
@@ -137,7 +141,8 @@ msgctxt "@error:not supported"
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:38
+#: /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"
@@ -159,7 +164,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/ClusterUM3OutputDevice.py:131
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/MeshFormatHandler.py:106
msgctxt "@info:status"
msgid "There are no file formats available to write with!"
msgstr "Aucun format de fichier n'est disponible pour écriture !"
@@ -196,9 +201,10 @@ 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/cura/Settings/CuraContainerRegistry.py:133
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:140
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1567
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py:188
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:134
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:141
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1622
msgctxt "@info:title"
msgid "Error"
msgstr "Erreur"
@@ -227,8 +233,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/CuraApplication.py:1557
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1651
+#: /home/ruben/Projects/Cura/cura/OAuth2/AuthorizationService.py:197
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1612
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1712
msgctxt "@info:title"
msgid "Warning"
msgstr "Avertissement"
@@ -255,274 +262,385 @@ 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:86
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:75
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:93
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:87
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:76
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:94
msgctxt "@properties:tooltip"
msgid "Print over network"
msgstr "Imprimer sur le réseau"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:88
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:95
msgctxt "@info:status"
msgid "Connected over the network."
msgstr "Connecté sur le réseau."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:91
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:98
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
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:100
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
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:105
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
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:108
msgctxt "@info:title"
msgid "Authentication status"
msgstr "Statut d'authentification"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:103
-msgctxt "@info:status"
-msgid ""
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:104
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:110
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:114
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:116
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:120
msgctxt "@info:title"
msgid "Authentication Status"
msgstr "Statut d'authentification"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:105
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:111
+#: /home/ruben/Projects/Cura/cura/OAuth2/AuthorizationService.py:198
msgctxt "@action:button"
msgid "Retry"
msgstr "Réessayer"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:106
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:112
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:109
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:115
msgctxt "@info:status"
msgid "Access to the printer accepted"
msgstr "Accès à l'imprimante accepté"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:113
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:119
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:115
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/UM3InfoComponents.qml:29
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/UM3InfoComponents.qml:73
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:121
+#: /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:117
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/UM3InfoComponents.qml:28
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/UM3InfoComponents.qml:72
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:123
+#: /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:202
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:208
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:204
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:210
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:210
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:232
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:216
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:238
msgctxt "@window:title"
msgid "Mismatched configuration"
msgstr "Configuration différente"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:224
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:230
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:226
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:232
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:253
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:197
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:259
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:176
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:181
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:260
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:216
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:232
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:266
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:194
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:211
msgctxt "@info:status"
msgid "Sending data to printer"
msgstr "Envoi des données à l'imprimante"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:261
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:217
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:233
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:267
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:196
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:213
msgctxt "@info:title"
msgid "Sending Data"
msgstr "Envoi des données"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:262
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:234
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxProgressButton.qml:18
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxConfirmUninstallResetDialog.qml:80
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:378
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintWindow.qml:92
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/MoreInfoWindow.qml:143
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:268
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:214
+#: /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:410
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintWindow.qml:20
+#: /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:391
-#: /home/ruben/Projects/Cura/resources/qml/OpenFilesIncludingProjectsDialog.qml:87
-#: /home/ruben/Projects/Cura/resources/qml/WorkspaceSummaryDialog.qml:279
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/OpenFilesIncludingProjectsDialog.qml:87
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:283
msgctxt "@action:button"
msgid "Cancel"
msgstr "Annuler"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:325
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:331
#, 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:331
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:337
#, 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:354
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:360
#, 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:363
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:369
#, 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:549
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:555
msgctxt "@window:title"
msgid "Sync with your printer"
msgstr "Synchroniser avec votre imprimante"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:551
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:557
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:553
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:559
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:89
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:96
msgctxt "@info:status"
msgid "Connected over the network"
msgstr "Connecté sur le réseau"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:310
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:289
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:370
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:312
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:291
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:371
msgctxt "@info:title"
msgid "Data Sent"
msgstr "Données envoyées"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:313
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:292
msgctxt "@action:button"
msgid "View in Monitor"
msgstr "Afficher sur le moniteur"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:420
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:411
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:318
#, python-brace-format
msgctxt "@info:status"
msgid "Printer '{printer_name}' has finished printing '{job_name}'."
msgstr "{printer_name} a terminé d'imprimer '{job_name}'."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:422
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:413
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:322
#, 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:423
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:414
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:316
msgctxt "@info:status"
msgid "Print finished"
msgstr "Impression terminée"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/DiscoverUM3Action.py:26
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:595
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:629
+msgctxt "@label:material"
+msgid "Empty"
+msgstr "Vide"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:596
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:630
+msgctxt "@label:material"
+msgid "Unknown"
+msgstr "Inconnu"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:169
+msgctxt "@action:button"
+msgid "Print via Cloud"
+msgstr "Imprimer via le cloud"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:170
+msgctxt "@properties:tooltip"
+msgid "Print via Cloud"
+msgstr "Imprimer via le cloud"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:171
+msgctxt "@info:status"
+msgid "Connected via Cloud"
+msgstr "Connecté via le cloud"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:182
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:359
+msgctxt "@info:title"
+msgid "Cloud error"
+msgstr "Erreur de cloud"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:199
+msgctxt "@info:status"
+msgid "Could not export print job."
+msgstr "Impossible d'exporter la tâche d'impression."
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:358
+msgctxt "@info:text"
+msgid "Could not upload the data to the printer."
+msgstr "Impossible de transférer les données à l'imprimante."
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/Utils.py:51
+msgctxt "@info:status"
+msgid "tomorrow"
+msgstr "demain"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/Utils.py:54
+msgctxt "@info:status"
+msgid "today"
+msgstr "aujourd'hui"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py:187
+msgctxt "@info:description"
+msgid "There was an error connecting to the cloud."
+msgstr "Une erreur s'est produite lors de la connexion au cloud."
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudProgressMessage.py:14
+msgctxt "@info:status"
+msgid "Sending Print Job"
+msgstr "Lancement d'une tâche d'impression"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudProgressMessage.py:15
+msgctxt "@info:status"
+msgid "Uploading via Ultimaker Cloud"
+msgstr "Téléchargement via Ultimaker Cloud"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py:621
+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/UM3OutputDevicePlugin.py:627
+msgctxt "@info:status Ultimaker Cloud is a brand name and shouldn't be translated."
+msgid "Connect to Ultimaker Cloud"
+msgstr "Se connecter à Ultimaker Cloud"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py:628
+msgctxt "@action"
+msgid "Don't ask me again for this printer."
+msgstr "Ne plus me demander pour cette imprimante."
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py:631
+msgctxt "@action"
+msgid "Get started"
+msgstr "Prise en main"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py:637
+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."
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py:643
+msgctxt "@info:status"
+msgid "Connected!"
+msgstr "Connecté !"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py:645
+msgctxt "@action"
+msgid "Review your connection"
+msgstr "Consulter votre connexion"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/DiscoverUM3Action.py:30
msgctxt "@action"
msgid "Connect via Network"
msgstr "Connecter via le réseau"
-#: /home/ruben/Projects/Cura/plugins/MonitorStage/__init__.py:12
+#: /home/ruben/Projects/Cura/plugins/MonitorStage/__init__.py:14
msgctxt "@item:inmenu"
msgid "Monitor"
msgstr "Surveiller"
-#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py:68
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py:118
+msgctxt "@info"
+msgid "Could not access update information."
+msgstr "Impossible d'accéder aux informations de mise à jour."
+
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerMessage.py:17
#, python-brace-format
msgctxt "@info Don't translate {machine_name}, since it gets replaced by a printer name!"
msgid "New features are available for your {machine_name}! It is recommended to update the firmware on your printer."
msgstr "De nouvelles fonctionnalités sont disponibles pour votre {machine_name} ! Il est recommandé de mettre à jour le firmware sur votre imprimante."
-#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py:72
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerMessage.py:21
#, python-format
msgctxt "@info:title The %s gets replaced with the printer name."
msgid "New %s firmware available"
msgstr "Nouveau firmware %s disponible"
-#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py:75
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerMessage.py:27
msgctxt "@action:button"
msgid "How to update"
msgstr "Comment effectuer la mise à jour"
-#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py:91
-msgctxt "@info"
-msgid "Could not access update information."
-msgstr "Impossible d'accéder aux informations de mise à jour."
-
-#: /home/ruben/Projects/Cura/plugins/SimulationView/__init__.py:14
+#: /home/ruben/Projects/Cura/plugins/SimulationView/__init__.py:15
msgctxt "@item:inlistbox"
msgid "Layer view"
msgstr "Vue en couches"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.py:102
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.py:114
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:103
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.py:115
msgctxt "@info:title"
msgid "Simulation View"
msgstr "Vue simulation"
-#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.py:28
+#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.py:35
+msgctxt "@item:inmenu"
+msgid "Post Processing"
+msgstr "Post-traitement"
+
+#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.py:36
+msgctxt "@item:inmenu"
msgid "Modify G-Code"
msgstr "Modifier le G-Code"
@@ -536,36 +654,6 @@ 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:43
-msgctxt "@info"
-msgid "Cura collects anonymized usage statistics."
-msgstr "Cura recueille des statistiques d'utilisation anonymes."
-
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/SliceInfo.py:46
-msgctxt "@info:title"
-msgid "Collecting Data"
-msgstr "Collecte des données"
-
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/SliceInfo.py:48
-msgctxt "@action:button"
-msgid "More info"
-msgstr "Plus d'informations"
-
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/SliceInfo.py:49
-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:51
-msgctxt "@action:button"
-msgid "Allow"
-msgstr "Autoriser"
-
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/SliceInfo.py:52
-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"
@@ -596,56 +684,56 @@ msgctxt "@item:inlistbox"
msgid "GIF Image"
msgstr "Image GIF"
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:333
+#: /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:333
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:364
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:388
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:397
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:406
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:415
+#: /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:363
+#: /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:387
+#: /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:396
+#: /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:405
+#: /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:414
+#: /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. Please scale or rotate models to fit."
-msgstr "Rien à couper car aucun des modèles ne convient au volume d'impression. Mettez à l'échelle ou faites pivoter les modèles pour les faire correspondre."
+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 "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:49
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py:242
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py:50
+#: /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:242
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py:256
msgctxt "@info:title"
msgid "Information"
msgstr "Informations"
@@ -661,13 +749,11 @@ 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/resources/qml/PrepareSidebar.qml:576
msgctxt "@title:tab"
msgid "Recommended"
msgstr "Recommandé"
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.py:177
-#: /home/ruben/Projects/Cura/resources/qml/PrepareSidebar.qml:581
msgctxt "@title:tab"
msgid "Custom"
msgstr "Personnalisé"
@@ -678,19 +764,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:711
+#: /home/ruben/Projects/Cura/plugins/3MFReader/ThreeMFWorkspaceReader.py:191
+#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:775
msgctxt "@label"
msgid "Nozzle"
msgstr "Buse"
-#: /home/ruben/Projects/Cura/plugins/3MFReader/ThreeMFWorkspaceReader.py:468
+#: /home/ruben/Projects/Cura/plugins/3MFReader/ThreeMFWorkspaceReader.py:474
#, 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:471
+#: /home/ruben/Projects/Cura/plugins/3MFReader/ThreeMFWorkspaceReader.py:477
msgctxt "@info:title"
msgid "Open Project File"
msgstr "Ouvrir un fichier de projet"
@@ -705,22 +791,65 @@ msgctxt "@item:inlistbox"
msgid "G File"
msgstr "Fichier G"
-#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:317
+#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:328
msgctxt "@info:status"
msgid "Parsing G-code"
msgstr "Analyse du G-Code"
-#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:319
-#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:466
+#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:330
+#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:483
msgctxt "@info:title"
msgid "G-code Details"
msgstr "Détails G-Code"
-#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:464
+#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:481
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."
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/DrivePluginExtension.py:64
+msgctxt "@item:inmenu"
+msgid "Manage backups"
+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
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/DriveApiService.py:55
+#: /home/ruben/Projects/Cura/cura/Backups/Backup.py:104
+msgctxt "@info:title"
+msgid "Backup"
+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 "Une erreur s’est produite lors du listage de vos sauvegardes."
+
+#: /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 "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 "Sauvegardes"
+
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/UploadBackupJob.py:27
+msgctxt "@info:backup_status"
+msgid "Uploading your backup..."
+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 "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 "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
msgctxt "@item:inlistbox"
@@ -732,7 +861,7 @@ msgctxt "@item:inmenu"
msgid "Profile Assistant"
msgstr "Assistant de profil"
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/__init__.py:17
+#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/__init__.py:18
msgctxt "@item:inlistbox"
msgid "Profile Assistant"
msgstr "Assistant de profil"
@@ -752,231 +881,266 @@ msgctxt "@error:zip"
msgid "Error writing 3mf file."
msgstr "Erreur d'écriture du fichier 3MF."
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UM2UpgradeSelection.py:17
+#: /home/ruben/Projects/Cura/plugins/PreviewStage/__init__.py:13
+msgctxt "@item:inmenu"
+msgid "Preview"
+msgstr "Aperçu"
+
+#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UM2UpgradeSelection.py:19
#: /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/UpgradeFirmwareMachineAction.py:12
-msgctxt "@action"
-msgid "Upgrade Firmware"
-msgstr "Mise à niveau du firmware"
-
-#: /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:98
-msgctxt "@tooltip"
-msgid "Outer Wall"
-msgstr "Paroi externe"
+#: /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/PrintInformation.py:99
-msgctxt "@tooltip"
-msgid "Inner Walls"
-msgstr "Parois internes"
+#: /home/ruben/Projects/Cura/cura/Settings/cura_empty_instance_containers.py:33
+msgctxt "@info:not supported profile"
+msgid "Not supported"
+msgstr "Non pris en charge"
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:100
-msgctxt "@tooltip"
-msgid "Skin"
-msgstr "Couche extérieure"
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:101
-msgctxt "@tooltip"
-msgid "Infill"
-msgstr "Remplissage"
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:102
-msgctxt "@tooltip"
-msgid "Support Infill"
-msgstr "Remplissage du support"
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:103
-msgctxt "@tooltip"
-msgid "Support Interface"
-msgstr "Interface du support"
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:104
-msgctxt "@tooltip"
-msgid "Support"
-msgstr "Support"
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:105
-msgctxt "@tooltip"
-msgid "Skirt"
-msgstr "Jupe"
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:106
-msgctxt "@tooltip"
-msgid "Travel"
-msgstr "Déplacement"
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:107
-msgctxt "@tooltip"
-msgid "Retractions"
-msgstr "Rétractions"
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:108
-msgctxt "@tooltip"
-msgid "Other"
-msgstr "Autre"
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:229
-msgctxt "@label unknown material"
-msgid "Unknown"
-msgstr "Inconnu"
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:314
-#, python-brace-format
-msgctxt "@label"
-msgid "Pre-sliced file {0}"
-msgstr "Fichier {0} prédécoupé"
-
-#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:186
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:121
+#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:203
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:122
msgctxt "@title:window"
msgid "File Already Exists"
msgstr "Le fichier existe déjà"
-#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:187
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:122
+#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:204
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:123
#, 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/ExtrudersModel.py:212
-msgctxt "@menuitem"
-msgid "Not overridden"
-msgstr "Pas écrasé"
-
-#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:120
+#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:427
+#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:430
msgctxt "@info:status"
-msgid "The selected material is incompatible with the selected machine or configuration."
-msgstr "Le matériau sélectionné est incompatible avec la machine ou la configuration sélectionnée."
+msgid "Invalid file URL:"
+msgstr "URL de fichier invalide :"
-#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:121
-msgctxt "@info:title"
-msgid "Incompatible Material"
-msgstr "Matériau incompatible"
+#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:925
+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:863
-#, 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:865
+#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:927
msgctxt "@info:title"
msgid "Settings updated"
msgstr "Paramètres mis à jour"
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:131
+#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:1481
+msgctxt "@info:title"
+msgid "Extruder(s) Disabled"
+msgstr "Extrudeuse(s) désactivée(s)"
+
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:132
#, 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:139
#, 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:144
#, 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:145
msgctxt "@info:title"
msgid "Export succeeded"
msgstr "L'exportation a réussi"
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:170
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:194
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:313
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:172
#, python-brace-format
-msgctxt "@info:status Don't translate the XML tags or !"
-msgid "Failed to import profile from {0}: {1}"
-msgstr "Échec de l'importation du profil depuis le fichier {0} : {1}"
+msgctxt "@info:status Don't translate the XML tags !"
+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:176
#, python-brace-format
-msgctxt "@info:status Don't translate the XML tags or !"
+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:192
+#, 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:218
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:228
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:196
#, python-brace-format
-msgctxt "@info:status Don't translate the XML tags or !"
+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:220
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:230
+#, 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:243
#, python-brace-format
-msgctxt "@info:status Don't translate the XML tags or !"
+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:316
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:315
+#, python-brace-format
+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} :"
+
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:318
#, 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:321
#, 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:324
#, 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:359
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:375
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:389
#, 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:59
+#: /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:306
+#, 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
+#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/ProfileCreatorTabControls.qml:62
+msgctxt "@action:button"
+msgid "Next"
+msgstr "Suivant"
+
+#: /home/ruben/Projects/Cura/cura/UI/ObjectsModel.py:61
#, 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/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:124
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:168
+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:91
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:48
+msgctxt "@action:button"
+msgid "Add"
+msgstr "Ajouter"
+
+#: /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:109
#, python-brace-format
@@ -989,45 +1153,79 @@ msgctxt "@item:inlistbox"
msgid "All Files (*)"
msgstr "Tous les fichiers (*)"
-#: /home/ruben/Projects/Cura/cura/Machines/MaterialManager.py:609
+#: /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
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:269
+msgctxt "@label"
+msgid "Unknown"
+msgstr "Inconnu"
+
+#: /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/Machines/MaterialManager.py:689
msgctxt "@label"
msgid "Custom Material"
msgstr "Matériau personnalisé"
-#: /home/ruben/Projects/Cura/cura/Machines/MaterialManager.py:610
+#: /home/ruben/Projects/Cura/cura/Machines/MaterialManager.py:690
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/ConfigurationMenu.qml:203
msgctxt "@label"
msgid "Custom"
msgstr "Personnalisé"
-#: /home/ruben/Projects/Cura/cura/BuildVolume.py:81
+#: /home/ruben/Projects/Cura/cura/BuildVolume.py:89
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:91
msgctxt "@info:title"
msgid "Build Volume"
msgstr "Volume d'impression"
-#: /home/ruben/Projects/Cura/cura/Backups/Backup.py:97
+#: /home/ruben/Projects/Cura/cura/Backups/Backup.py:99
msgctxt "@info:backup_failed"
msgid "Could not create archive from user data directory: {}"
msgstr "Impossible de créer une archive à partir du répertoire de données de l'utilisateur : {}"
-#: /home/ruben/Projects/Cura/cura/Backups/Backup.py:102
-msgctxt "@info:title"
-msgid "Backup"
-msgstr "Sauvegarde"
-
-#: /home/ruben/Projects/Cura/cura/Backups/Backup.py:112
+#: /home/ruben/Projects/Cura/cura/Backups/Backup.py:114
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:122
+#: /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/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:197
+msgctxt "@info"
+msgid "Unable to reach the Ultimaker account server."
+msgstr "Impossible d’atteindre le serveur du compte Ultimaker."
+
+#: /home/ruben/Projects/Cura/cura/OAuth2/AuthorizationRequestHandler.py:66
+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:73
+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:27
msgctxt "@info:status"
@@ -1035,42 +1233,46 @@ msgid "Multiplying and placing objects"
msgstr "Multiplication et placement d'objets"
#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:28
+msgctxt "@info:title"
+msgid "Placing Objects"
+msgstr "Placement des objets"
+
+#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:100
+#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsJob.py:103
+#: /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
msgctxt "@info:title"
msgid "Placing Object"
msgstr "Placement de l'objet"
-#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:100
-#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsJob.py:96
-#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsAllBuildPlatesJob.py:150
-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/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:97
-#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsAllBuildPlatesJob.py:151
+#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsJob.py:104
+#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsAllBuildPlatesJob.py:150
msgctxt "@info:title"
msgid "Can't Find Location"
msgstr "Impossible de trouver un emplacement"
-#: /home/ruben/Projects/Cura/cura/CrashHandler.py:87
+#: /home/ruben/Projects/Cura/cura/CrashHandler.py:83
msgctxt "@title:window"
msgid "Cura can't start"
msgstr "Échec du démarrage de Cura"
-#: /home/ruben/Projects/Cura/cura/CrashHandler.py:93
+#: /home/ruben/Projects/Cura/cura/CrashHandler.py:89
msgctxt "@label crash message"
msgid ""
"
Oops, Ultimaker Cura has encountered something that doesn't seem right.
\n"
@@ -1085,32 +1287,32 @@ msgstr ""
"
Veuillez nous envoyer ce rapport d'incident pour que nous puissions résoudre le problème.
\n"
" "
-#: /home/ruben/Projects/Cura/cura/CrashHandler.py:102
+#: /home/ruben/Projects/Cura/cura/CrashHandler.py:98
msgctxt "@action:button"
msgid "Send crash report to Ultimaker"
msgstr "Envoyer le rapport de d'incident à Ultimaker"
-#: /home/ruben/Projects/Cura/cura/CrashHandler.py:105
+#: /home/ruben/Projects/Cura/cura/CrashHandler.py:101
msgctxt "@action:button"
msgid "Show detailed crash report"
msgstr "Afficher le rapport d'incident détaillé"
-#: /home/ruben/Projects/Cura/cura/CrashHandler.py:109
+#: /home/ruben/Projects/Cura/cura/CrashHandler.py:105
msgctxt "@action:button"
msgid "Show configuration folder"
msgstr "Afficher le dossier de configuration"
-#: /home/ruben/Projects/Cura/cura/CrashHandler.py:120
+#: /home/ruben/Projects/Cura/cura/CrashHandler.py:116
msgctxt "@action:button"
msgid "Backup and Reset Configuration"
msgstr "Sauvegarder et réinitialiser la configuration"
-#: /home/ruben/Projects/Cura/cura/CrashHandler.py:149
+#: /home/ruben/Projects/Cura/cura/CrashHandler.py:145
msgctxt "@title:window"
msgid "Crash Report"
msgstr "Rapport d'incident"
-#: /home/ruben/Projects/Cura/cura/CrashHandler.py:169
+#: /home/ruben/Projects/Cura/cura/CrashHandler.py:165
msgctxt "@label crash message"
msgid ""
"
A fatal error has occurred in Cura. Please send us this Crash Report to fix the problem
\n"
@@ -1121,311 +1323,275 @@ msgstr ""
"
Veuillez utiliser le bouton « Envoyer rapport » pour publier automatiquement un rapport d'erreur sur nos serveurs
"
-#: /home/ruben/Projects/Cura/cura/CrashHandler.py:222
+#: /home/ruben/Projects/Cura/cura/CrashHandler.py:218
msgctxt "@title:groupbox"
msgid "Error traceback"
msgstr "Retraçage de l'erreur"
-#: /home/ruben/Projects/Cura/cura/CrashHandler.py:303
+#: /home/ruben/Projects/Cura/cura/CrashHandler.py:299
msgctxt "@title:groupbox"
msgid "Logs"
msgstr "Journaux"
-#: /home/ruben/Projects/Cura/cura/CrashHandler.py:326
+#: /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:345
+#: /home/ruben/Projects/Cura/cura/CrashHandler.py:342
msgctxt "@action:button"
msgid "Send report"
msgstr "Envoyer rapport"
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:454
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:504
msgctxt "@info:progress"
msgid "Loading machines..."
msgstr "Chargement des machines..."
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:748
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:819
msgctxt "@info:progress"
msgid "Setting up scene..."
msgstr "Préparation de la scène..."
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:784
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:854
msgctxt "@info:progress"
msgid "Loading interface..."
msgstr "Chargement de l'interface..."
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:997
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1133
#, 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:1556
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1611
#, 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:1566
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1621
#, 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:1650
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1711
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:61
-msgctxt "@title"
-msgid "Machine Settings"
-msgstr "Paramètres de la machine"
-
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:80
-msgctxt "@title:tab"
-msgid "Printer"
-msgstr "Imprimante"
-
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:99
-msgctxt "@label"
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:58
+msgctxt "@title:label"
msgid "Printer Settings"
msgstr "Paramètres de l'imprimante"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:110
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:72
msgctxt "@label"
msgid "X (Width)"
msgstr "X (Largeur)"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:111
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:121
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:131
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:237
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:386
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:402
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:420
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:432
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:857
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:76
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:90
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:104
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:194
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:213
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:232
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:253
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:272
+#: /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:120
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:86
msgctxt "@label"
msgid "Y (Depth)"
msgstr "Y (Profondeur)"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:130
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:100
msgctxt "@label"
msgid "Z (Height)"
msgstr "Z (Hauteur)"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:142
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:114
msgctxt "@label"
msgid "Build plate shape"
msgstr "Forme du plateau"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:151
-msgctxt "@option:check"
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:127
+msgctxt "@label"
msgid "Origin at center"
msgstr "Origine au centre"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:159
-msgctxt "@option:check"
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:139
+msgctxt "@label"
msgid "Heated bed"
msgstr "Plateau chauffant"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:170
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:151
msgctxt "@label"
msgid "G-code flavor"
msgstr "Parfum G-Code"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:183
-msgctxt "@label"
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:176
+msgctxt "@title:label"
msgid "Printhead Settings"
msgstr "Paramètres de la tête d'impression"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:193
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:190
msgctxt "@label"
msgid "X min"
msgstr "X min"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:194
-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:203
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:209
msgctxt "@label"
msgid "Y min"
msgstr "Y min"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:204
-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:213
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:228
msgctxt "@label"
msgid "X max"
msgstr "X max"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:214
-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:223
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:249
msgctxt "@label"
msgid "Y max"
msgstr "Y max"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:224
-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:236
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:268
msgctxt "@label"
-msgid "Gantry height"
+msgid "Gantry Height"
msgstr "Hauteur du portique"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:238
-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:257
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:282
msgctxt "@label"
msgid "Number of Extruders"
msgstr "Nombre d'extrudeuses"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:313
-msgctxt "@label"
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:341
+msgctxt "@title:label"
msgid "Start G-code"
msgstr "G-Code de démarrage"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:323
-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:332
-msgctxt "@label"
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:355
+msgctxt "@title:label"
msgid "End G-code"
msgstr "G-Code de fin"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:342
-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:373
-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:385
+#: /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:401
+#: /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:403
-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:419
+#: /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:431
+#: /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/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:470
-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"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxProgressButton.qml:17
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxProgressButton.qml:18
msgctxt "@action:button"
msgid "Install"
msgstr "Installer"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxProgressButton.qml:19
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxProgressButton.qml:20
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailTileActions.qml:46
msgctxt "@action:button"
msgid "Installed"
msgstr "Installé"
@@ -1435,68 +1601,82 @@ msgctxt "@info"
msgid "Could not connect to the Cura Package database. Please check your connection."
msgstr "Impossible de se connecter à la base de données Cura Package. Veuillez vérifier votre connexion."
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/SmallRatingWidget.qml:27
+msgctxt "@label"
+msgid "ratings"
+msgstr "évaluations"
+
#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledPage.qml:38
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxHeader.qml:26
+#: /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:75
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:66
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:544
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledPage.qml:70
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxHeader.qml:44
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:80
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:417
msgctxt "@title:tab"
msgid "Materials"
msgstr "Matériaux"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml:80
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml:91
+msgctxt "@label"
+msgid "Your rating"
+msgstr "Votre évaluation"
+
+#: /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:86
+#: /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:92
+#: /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:98
+#: /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:117
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml:159
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:255
-msgctxt "@label"
-msgid "Unknown"
-msgstr "Inconnu"
+#: /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 "Connexion nécessaire pour l'installation ou la mise à jour"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailTileActions.qml:44
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml:30
+#: /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:45
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml:31
+#: /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:46
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml:32
+#: /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"
msgstr "Mis à jour"
#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/Toolbox.qml:13
msgctxt "@title"
-msgid "Toolbox"
-msgstr "Boîte à outils"
+msgid "Marketplace"
+msgstr "Marché en ligne"
#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxBackColumn.qml:25
msgctxt "@action:button"
@@ -1505,8 +1685,8 @@ msgstr "Précédent"
#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxConfirmUninstallResetDialog.qml:20
msgctxt "@title:window"
-msgid "Confirm uninstall "
-msgstr "Confirmer la désinstallation "
+msgid "Confirm uninstall"
+msgstr "Confirmer la désinstallation"
#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxConfirmUninstallResetDialog.qml:50
msgctxt "@text:window"
@@ -1523,17 +1703,27 @@ msgctxt "@text:window"
msgid "Profiles"
msgstr "Profils"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxConfirmUninstallResetDialog.qml:89
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxConfirmUninstallResetDialog.qml:90
msgctxt "@action:button"
msgid "Confirm"
msgstr "Confirmer"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxFooter.qml:17
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/RatingWidget.qml:54
+msgctxt "@label"
+msgid "You need to login first before you can rate"
+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 "Vous devez installer le paquet avant de pouvoir effectuer une évaluation"
+
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxFooter.qml:19
msgctxt "@info"
msgid "You will need to restart Cura before changes in packages have effect."
msgstr "Vous devez redémarrer Cura pour que les changements apportés aux paquets ne prennent effet."
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxFooter.qml:34
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxFooter.qml:45
msgctxt "@info:button"
msgid "Quit Cura"
msgstr "Quitter Cura"
@@ -1553,22 +1743,27 @@ msgctxt "@label"
msgid "Generic Materials"
msgstr "Matériaux génériques"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxHeader.qml:54
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxHeader.qml:59
msgctxt "@title:tab"
msgid "Installed"
msgstr "Installé"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml:19
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml:22
msgctxt "@label"
msgid "Will install upon restarting"
msgstr "S'installera au redémarrage"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml:51
+#: /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 "Connexion nécessaire pour effectuer la mise à jour"
+
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml:71
msgctxt "@action:button"
msgid "Downgrade"
msgstr "Revenir à une version précédente"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml:51
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml:71
msgctxt "@action:button"
msgid "Uninstall"
msgstr "Désinstaller"
@@ -1589,12 +1784,12 @@ msgstr ""
"Vous devez approuver cette licence pour installer ce plug-in.\n"
"Acceptez-vous les clauses ci-dessous ?"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxLicenseDialog.qml:54
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxLicenseDialog.qml:55
msgctxt "@action:button"
msgid "Accept"
msgstr "Accepter"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxLicenseDialog.qml:65
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxLicenseDialog.qml:66
msgctxt "@action:button"
msgid "Decline"
msgstr "Refuser"
@@ -1604,22 +1799,42 @@ msgctxt "@label"
msgid "Featured"
msgstr "Fonctionnalités"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:31
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:66
msgctxt "@label"
msgid "Compatibility"
msgstr "Compatibilité"
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:203
+msgctxt "@action:label"
+msgid "Technical Data Sheet"
+msgstr "Fiche technique"
+
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:212
+msgctxt "@action:label"
+msgid "Safety Data Sheet"
+msgstr "Fiche de sécurité"
+
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:221
+msgctxt "@action:label"
+msgid "Printing Guidelines"
+msgstr "Directives d'impression"
+
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:230
+msgctxt "@action:label"
+msgid "Website"
+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:88
+#: /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:94
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxAuthorPage.qml:98
msgctxt "@label"
msgid "Email"
msgstr "E-mail"
@@ -1629,422 +1844,594 @@ 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
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:31
+msgctxt "@title"
+msgid "Update Firmware"
+msgstr "Mettre à jour le firmware"
+
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:39
msgctxt "@label"
-msgid "Changelog"
-msgstr "Récapitulatif des changements"
+msgid "Firmware is the piece of software running directly on your 3D printer. This firmware controls the step motors, regulates the temperature and ultimately makes your printer work."
+msgstr "Le firmware est le logiciel fonctionnant directement dans votre imprimante 3D. Ce firmware contrôle les moteurs pas à pas, régule la température et surtout, fait que votre machine fonctionne."
-#: /home/ruben/Projects/Cura/plugins/ChangeLogPlugin/ChangeLog.qml:37
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/FirmwareUpdateWindow.qml:84
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/UM3InfoComponents.qml:56
-#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.qml:464
-#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:508
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:121
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:148
-#: /home/ruben/Projects/Cura/resources/qml/EngineLog.qml:38
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:46
+msgctxt "@label"
+msgid "The firmware shipping with new printers works, but new versions tend to have more features and improvements."
+msgstr "Le firmware fourni avec les nouvelles imprimantes fonctionne, mais les nouvelles versions ont tendance à fournir davantage de fonctionnalités ainsi que des améliorations."
+
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:58
msgctxt "@action:button"
-msgid "Close"
-msgstr "Fermer"
+msgid "Automatically upgrade Firmware"
+msgstr "Mise à niveau automatique du firmware"
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/FirmwareUpdateWindow.qml:22
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:69
+msgctxt "@action:button"
+msgid "Upload custom Firmware"
+msgstr "Charger le firmware personnalisé"
+
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:83
+msgctxt "@label"
+msgid "Firmware can not be updated because there is no connection with the printer."
+msgstr "Impossible de se connecter à l'imprimante ; échec de la mise à jour du firmware."
+
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:91
+msgctxt "@label"
+msgid "Firmware can not be updated because the connection with the printer does not support upgrading firmware."
+msgstr "Échec de la mise à jour du firmware, car cette fonctionnalité n'est pas prise en charge par la connexion avec l'imprimante."
+
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:98
+msgctxt "@title:window"
+msgid "Select custom firmware"
+msgstr "Sélectionner le firmware personnalisé"
+
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:119
msgctxt "@title:window"
msgid "Firmware Update"
msgstr "Mise à jour du firmware"
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/FirmwareUpdateWindow.qml:42
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:143
msgctxt "@label"
msgid "Updating firmware."
msgstr "Mise à jour du firmware en cours."
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/FirmwareUpdateWindow.qml:44
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:145
msgctxt "@label"
msgid "Firmware update completed."
msgstr "Mise à jour du firmware terminée."
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/FirmwareUpdateWindow.qml:46
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:147
msgctxt "@label"
msgid "Firmware update failed due to an unknown error."
msgstr "Échec de la mise à jour du firmware en raison d'une erreur inconnue."
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/FirmwareUpdateWindow.qml:48
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:149
msgctxt "@label"
msgid "Firmware update failed due to an communication error."
msgstr "Échec de la mise à jour du firmware en raison d'une erreur de communication."
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/FirmwareUpdateWindow.qml:50
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:151
msgctxt "@label"
msgid "Firmware update failed due to an input/output error."
msgstr "Échec de la mise à jour du firmware en raison d'une erreur d'entrée/de sortie."
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/FirmwareUpdateWindow.qml:52
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:153
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:144
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobCard.qml:181
+#: /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/DiscoverUM3Action.qml:43
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:208
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobCard.qml:249
+msgctxt "@info"
+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
+msgctxt "@info"
+msgid "The webcam is not available because you are monitoring a cloud printer."
+msgstr "La webcam n'est pas disponible car vous surveillez une imprimante cloud."
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:300
+msgctxt "@label:status"
+msgid "Loading..."
+msgstr "Chargement..."
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:304
+msgctxt "@label:status"
+msgid "Unavailable"
+msgstr "Indisponible"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:308
+msgctxt "@label:status"
+msgid "Unreachable"
+msgstr "Injoignable"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:312
+msgctxt "@label:status"
+msgid "Idle"
+msgstr "Inactif"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:353
+msgctxt "@label"
+msgid "Untitled"
+msgstr "Sans titre"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:374
+msgctxt "@label"
+msgid "Anonymous"
+msgstr "Anonyme"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:401
+msgctxt "@label:status"
+msgid "Requires configuration changes"
+msgstr "Nécessite des modifications de configuration"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:439
+msgctxt "@action:button"
+msgid "Details"
+msgstr "Détails"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobCard.qml:130
+msgctxt "@label"
+msgid "Unavailable printer"
+msgstr "Imprimante indisponible"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobCard.qml:132
+msgctxt "@label"
+msgid "First available"
+msgstr "Premier disponible"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml:31
+msgctxt "@label"
+msgid "Queued"
+msgstr "Mis en file d'attente"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml:67
+msgctxt "@label link to connect manager"
+msgid "Manage in browser"
+msgstr "Gérer dans le navigateur"
+
+#: /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:116
+msgctxt "@label"
+msgid "Print jobs"
+msgstr "Tâches d'impression"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml:132
+msgctxt "@label"
+msgid "Total print time"
+msgstr "Temps total d'impression"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml:148
+msgctxt "@label"
+msgid "Waiting for"
+msgstr "Attente de"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:50
msgctxt "@window:title"
msgid "Existing Connection"
msgstr "Connexion existante"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:45
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:52
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:62
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:69
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:72
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:81
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:82
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:42
-msgctxt "@action:button"
-msgid "Add"
-msgstr "Ajouter"
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:81
+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:92
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:101
msgctxt "@action:button"
msgid "Edit"
msgstr "Modifier"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:103
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:128
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:48
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:117
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:112
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:146
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:55
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:121
msgctxt "@action:button"
msgid "Remove"
msgstr "Supprimer"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:111
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:120
msgctxt "@action:button"
msgid "Refresh"
msgstr "Rafraîchir"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:204
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:215
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:231
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:244
+#: /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:268
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:283
+#: /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:280
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:297
+#: /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:302
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:321
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:306
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:325
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:316
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:336
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:321
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/UM3InfoComponents.qml:39
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:341
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/UM3InfoComponents.qml:74
msgctxt "@action:button"
msgid "Connect"
msgstr "Connecter"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:335
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:354
+msgctxt "@title:window"
+msgid "Invalid IP address"
+msgstr "Adresse IP non valide"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:355
+#: /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:366
msgctxt "@title:window"
msgid "Printer Address"
msgstr "Adresse de l'imprimante"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:358
-msgctxt "@alabel"
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:389
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddPrinterByIpContent.qml:102
+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."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:387
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/MoreInfoWindow.qml:132
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:419
+#: /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/PrintWindow.qml:34
-msgctxt "@title:window"
-msgid "Print over network"
-msgstr "Imprimer sur le réseau"
+#: /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/PrintWindow.qml:65
-msgctxt "@label"
-msgid "Printer selection"
-msgstr "Sélection d'imprimantes"
+#: /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/PrintWindow.qml:105
+#: /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 "Préparation..."
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:88
+msgctxt "@label:status"
+msgid "Aborting..."
+msgstr "Abandon..."
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:92
+msgctxt "@label:status"
+msgid "Pausing..."
+msgstr "Mise en pause..."
+
+#: /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:96
+msgctxt "@label:status"
+msgid "Resuming..."
+msgstr "Reprise..."
+
+#: /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:100
+msgctxt "@label:status"
+msgid "Finishes %1 at %2"
+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/PrintJobInfoBlock.qml:142
-msgctxt "@label"
-msgid "Waiting for: Unavailable printer"
-msgstr "En attente : imprimante non disponible"
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintWindow.qml:47
+msgctxt "@title:window"
+msgid "Print over network"
+msgstr "Imprimer sur le réseau"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintJobInfoBlock.qml:144
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintWindow.qml:79
msgctxt "@label"
-msgid "Waiting for: First available"
-msgstr "En attente : première imprimante disponible"
+msgid "Printer selection"
+msgstr "Sélection d'imprimantes"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintJobInfoBlock.qml:148
-msgctxt "@label"
-msgid "Waiting for: "
-msgstr "En attente : "
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintJobInfoBlock.qml:213
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:54
msgctxt "@label"
msgid "Move to top"
msgstr "Déplacer l'impression en haut"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintJobInfoBlock.qml:234
-msgctxt "@window:title"
-msgid "Move print job to top"
-msgstr "Déplacer l'impression en haut de la file d'attente"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintJobInfoBlock.qml:236
-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 "Êtes-vous sûr de vouloir déplacer %1 en haut de la file d'attente ?"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintJobInfoBlock.qml:245
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:70
msgctxt "@label"
msgid "Delete"
msgstr "Effacer"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintJobInfoBlock.qml:264
-msgctxt "@window:title"
-msgid "Delete print job"
-msgstr "Supprimer l'impression"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintJobInfoBlock.qml:266
-msgctxt "@label %1 is the name of a print job."
-msgid "Are you sure you want to delete %1?"
-msgstr "Êtes-vous sûr de vouloir supprimer %1 ?"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/ClusterMonitorItem.qml:32
-msgctxt "@label link to connect manager"
-msgid "Manage queue"
-msgstr "Gérer la file d'attente"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/ClusterMonitorItem.qml:54
-msgctxt "@label"
-msgid "Queued"
-msgstr "Mis en file d'attente"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/ClusterControlItem.qml:44
-msgctxt "@label"
-msgid "Printing"
-msgstr "Impression"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/ClusterControlItem.qml:54
-msgctxt "@label link to connect manager"
-msgid "Manage printers"
-msgstr "Gérer les imprimantes"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/ClusterControlItem.qml:212
-msgctxt "@label"
-msgid "Not available"
-msgstr "Non disponible"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/ClusterControlItem.qml:215
-msgctxt "@label"
-msgid "Unreachable"
-msgstr "Injoignable"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/ClusterControlItem.qml:221
-msgctxt "@label"
-msgid "Available"
-msgstr "Disponible"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/ClusterControlItem.qml:416
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:100
#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:289
msgctxt "@label"
msgid "Resume"
msgstr "Reprendre"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/ClusterControlItem.qml:416
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:102
+msgctxt "@label"
+msgid "Pausing..."
+msgstr "Mise en pause..."
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:104
+msgctxt "@label"
+msgid "Resuming..."
+msgstr "Reprise..."
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:106
#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:284
#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:293
msgctxt "@label"
msgid "Pause"
msgstr "Pause"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/ClusterControlItem.qml:444
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:124
+msgctxt "@label"
+msgid "Aborting..."
+msgstr "Abandon..."
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:124
msgctxt "@label"
msgid "Abort"
msgstr "Abandonner"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/ClusterControlItem.qml:464
+#: /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 "Êtes-vous sûr de vouloir déplacer %1 en haut de la file d'attente ?"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:144
+msgctxt "@window:title"
+msgid "Move print job to top"
+msgstr "Déplacer l'impression en haut de la file d'attente"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:153
+msgctxt "@label %1 is the name of a print job."
+msgid "Are you sure you want to delete %1?"
+msgstr "Êtes-vous sûr de vouloir supprimer %1 ?"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:154
+msgctxt "@window:title"
+msgid "Delete print job"
+msgstr "Supprimer l'impression"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:163
+msgctxt "@label %1 is the name of a print job."
+msgid "Are you sure you want to abort %1?"
+msgstr "Êtes-vous sûr de vouloir annuler %1 ?"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:164
#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:335
msgctxt "@window:title"
msgid "Abort print"
msgstr "Abandonner l'impression"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/ClusterControlItem.qml:466
-msgctxt "@label %1 is the name of a print job."
-msgid "Are you sure you want to abort %1?"
-msgstr "Êtes-vous sûr de vouloir annuler %1 ?"
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:20
+msgctxt "@title:window"
+msgid "Configuration Changes"
+msgstr "Modifications de configuration"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/ClusterControlItem.qml:665
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/ClusterControlItem.qml:673
-msgctxt "@label:status"
-msgid "Aborted"
-msgstr "Abandonné"
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:27
+msgctxt "@action:button"
+msgid "Override"
+msgstr "Remplacer"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/ClusterControlItem.qml:667
-msgctxt "@label:status"
-msgid "Finished"
-msgstr "Terminé"
+#: /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] "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/ClusterControlItem.qml:670
-msgctxt "@label:status"
-msgid "Preparing"
-msgstr "Préparation"
+#: /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/ClusterControlItem.qml:675
-msgctxt "@label:status"
-msgid "Pausing"
-msgstr "Mise en pause"
+#: /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/ClusterControlItem.qml:677
-msgctxt "@label:status"
-msgid "Paused"
-msgstr "En pause"
+#: /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/ClusterControlItem.qml:679
-msgctxt "@label:status"
-msgid "Resuming"
-msgstr "Reprise"
+#: /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/ClusterControlItem.qml:681
-msgctxt "@label:status"
-msgid "Action required"
-msgstr "Action requise"
+#: /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/UM3InfoComponents.qml:38
+#: /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 "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: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/UM3NetworkPrinting/resources/qml/UM3InfoComponents.qml:117
-msgctxt "@info:tooltip"
-msgid "Load the configuration of the printer into Cura"
-msgstr "Charger la configuration de l'imprimante dans Cura"
+#: /home/ruben/Projects/Cura/plugins/SettingsGuide/resources/qml/SettingsGuide.qml:16
+msgctxt "@title"
+msgid "Cura Settings Guide"
+msgstr "Guide des paramètres de Cura"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/UM3InfoComponents.qml:118
-msgctxt "@action:button"
-msgid "Activate Configuration"
-msgstr "Activer la configuration"
+#: /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.\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/SimulationView/SimulationView.qml:130
+#: /home/ruben/Projects/Cura/plugins/MonitorStage/MonitorMain.qml:117
+msgctxt "@info"
+msgid "Please connect your printer to the network."
+msgstr "Veuillez connecter votre imprimante au réseau."
+
+#: /home/ruben/Projects/Cura/plugins/MonitorStage/MonitorMain.qml:156
+msgctxt "@label link to technical assistance"
+msgid "View user manuals online"
+msgstr "Voir les manuels d'utilisation en ligne"
+
+#: /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/SimulationView.qml:145
+#: /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/SimulationView.qml:149
+#: /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/SimulationView.qml:153
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:115
msgctxt "@label:listbox"
msgid "Feedrate"
msgstr "Taux d'alimentation"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:157
+#: /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/SimulationView.qml:198
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:156
msgctxt "@label"
msgid "Compatibility Mode"
msgstr "Mode de compatibilité"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:284
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:230
msgctxt "@label"
-msgid "Show Travels"
-msgstr "Afficher les déplacements"
+msgid "Travels"
+msgstr "Déplacements"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:290
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:236
msgctxt "@label"
-msgid "Show Helpers"
-msgstr "Afficher les aides"
+msgid "Helpers"
+msgstr "Aides"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:296
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:242
msgctxt "@label"
-msgid "Show Shell"
-msgstr "Afficher la coque"
+msgid "Shell"
+msgstr "Coque"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:302
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:248
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedInfillDensitySelector.qml:65
msgctxt "@label"
-msgid "Show Infill"
-msgstr "Afficher le remplissage"
+msgid "Infill"
+msgstr "Remplissage"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:355
+#: /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/SimulationView.qml:366
+#: /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/SimulationView.qml:379
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:322
msgctxt "@label"
msgid "Top / Bottom"
msgstr "Haut / bas"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:383
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:326
msgctxt "@label"
msgid "Inner Wall"
msgstr "Paroi interne"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:448
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:384
msgctxt "@label"
msgid "min"
msgstr "min."
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:500
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:433
msgctxt "@label"
msgid "max"
msgstr "max."
@@ -2059,40 +2446,40 @@ msgctxt "@label"
msgid "Post Processing Scripts"
msgstr "Scripts de post-traitement"
-#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.qml:225
+#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.qml:233
msgctxt "@action"
msgid "Add a script"
msgstr "Ajouter un script"
-#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.qml:271
+#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.qml:279
msgctxt "@label"
msgid "Settings"
msgstr "Paramètres"
-#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.qml:474
+#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.qml:493
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 these data"
-msgstr "Je ne veux pas envoyer ces données"
+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 these data to Ultimaker and help us improve Cura"
-msgstr "Permettre l'envoi de ces données à Ultimaker et nous aider à améliorer Cura"
+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"
@@ -2141,19 +2528,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."
@@ -2194,18 +2581,18 @@ 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:341
+#: /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:383
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:388
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/resources/qml/Preferences/SettingVisibilityPage.qml:98
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/SettingVisibilityPage.qml:94
msgctxt "@label:textbox"
msgid "Filter..."
msgstr "Filtrer..."
@@ -2232,13 +2619,13 @@ msgid "Create new"
msgstr "Créer"
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:70
-#: /home/ruben/Projects/Cura/resources/qml/WorkspaceSummaryDialog.qml:72
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:73
msgctxt "@action:title"
msgid "Summary - Cura Project"
msgstr "Résumé - Projet Cura"
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:92
-#: /home/ruben/Projects/Cura/resources/qml/WorkspaceSummaryDialog.qml:96
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:97
msgctxt "@action:label"
msgid "Printer settings"
msgstr "Paramètres de l'imprimante"
@@ -2255,18 +2642,19 @@ msgid "Update"
msgstr "Mise à jour"
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:143
-#: /home/ruben/Projects/Cura/resources/qml/WorkspaceSummaryDialog.qml:105
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:106
msgctxt "@action:label"
msgid "Type"
msgstr "Type"
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:159
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:121
msgctxt "@action:label"
msgid "Printer Group"
msgstr "Groupe d'imprimantes"
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:180
-#: /home/ruben/Projects/Cura/resources/qml/WorkspaceSummaryDialog.qml:196
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:226
msgctxt "@action:label"
msgid "Profile settings"
msgstr "Paramètres de profil"
@@ -2278,19 +2666,20 @@ 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/resources/qml/WorkspaceSummaryDialog.qml:220
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:121
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:250
msgctxt "@action:label"
msgid "Name"
msgstr "Nom"
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:231
-#: /home/ruben/Projects/Cura/resources/qml/WorkspaceSummaryDialog.qml:204
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:234
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/WorkspaceSummaryDialog.qml:209
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:239
msgctxt "@action:label"
msgid "%1 override"
msgid_plural "%1 overrides"
@@ -2320,7 +2709,6 @@ 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/resources/qml/WorkspaceSummaryDialog.qml:237
msgctxt "@action:label"
msgid "Setting visibility"
msgstr "Visibilité des paramètres"
@@ -2331,13 +2719,11 @@ msgid "Mode"
msgstr "Mode"
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:352
-#: /home/ruben/Projects/Cura/resources/qml/WorkspaceSummaryDialog.qml:246
msgctxt "@action:label"
msgid "Visible settings:"
msgstr "Paramètres visibles :"
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:357
-#: /home/ruben/Projects/Cura/resources/qml/WorkspaceSummaryDialog.qml:251
msgctxt "@action:label"
msgid "%1 out of %2"
msgstr "%1 sur %2"
@@ -2352,256 +2738,191 @@ msgctxt "@action:button"
msgid "Open"
msgstr "Ouvrir"
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/ProfileCreatorTabControls.qml:34
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/pages/BackupsPage.qml:28
+msgctxt "@title"
+msgid "My Backups"
+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 "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 "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 "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 "Se connecter"
+
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/main.qml:24
+msgctxt "@title:window"
+msgid "Cura Backups"
+msgstr "Sauvegardes Cura"
+
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListItemDetails.qml:21
+msgctxt "@backuplist:label"
+msgid "Cura Version"
+msgstr "Version Cura"
+
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListItemDetails.qml:29
+msgctxt "@backuplist:label"
+msgid "Machines"
+msgstr "Machines"
+
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListItemDetails.qml:37
+msgctxt "@backuplist:label"
+msgid "Materials"
+msgstr "Matériaux"
+
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListItemDetails.qml:45
+msgctxt "@backuplist:label"
+msgid "Profiles"
+msgstr "Profils"
+
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListItemDetails.qml:53
+msgctxt "@backuplist:label"
+msgid "Plugins"
+msgstr "Plug-ins"
+
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListItem.qml:71
+msgctxt "@button"
+msgid "Restore"
+msgstr "Restaurer"
+
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListItem.qml:99
+msgctxt "@dialog:title"
+msgid "Delete Backup"
+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 "Ê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 "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 "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 "Vous en voulez plus ?"
+
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListFooter.qml:31
+msgctxt "@button"
+msgid "Backup Now"
+msgstr "Sauvegarder maintenant"
+
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListFooter.qml:43
+msgctxt "@checkbox:description"
+msgid "Auto Backup"
+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 "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 "Non pris en charge"
+
+#: /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:138
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:154
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:152
+#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/ProfileCreatorTabControls.qml:60
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:174
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:159
msgctxt "@action:button"
msgid "Export"
msgstr "Exporter"
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/ProfileCreatorTabControls.qml:140
-msgctxt "@action:button"
-msgid "Next"
-msgstr "Suivant"
-
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/ProfileCreatorPageCategoryView.qml:163
+#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/ProfileCreatorPageCategoryView.qml:209
msgctxt "@label"
msgid "Tip"
msgstr "Astuce"
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/CuraPrintProfileCreatorView.qml:80
-#: /home/ruben/Projects/Cura/resources/qml/PrepareSidebar.qml:341
-msgctxt "@label Hours and minutes"
-msgid "00h 00min"
-msgstr "00h 00min"
+#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/ProfileCreatorMaterialMenu.qml:20
+#: /home/ruben/Projects/Cura/resources/qml/Menus/MaterialMenu.qml:66
+msgctxt "@label:category menu label"
+msgid "Generic"
+msgstr "Générique"
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/CuraPrintProfileCreatorView.qml:142
-#: /home/ruben/Projects/Cura/resources/qml/PrepareSidebar.qml:441
-msgctxt "@label"
-msgid "Cost specification"
-msgstr "Spécification de coût"
-
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/CuraPrintProfileCreatorView.qml:147
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/CuraPrintProfileCreatorView.qml:156
-#: /home/ruben/Projects/Cura/resources/qml/PrepareSidebar.qml:446
-#: /home/ruben/Projects/Cura/resources/qml/PrepareSidebar.qml:455
-msgctxt "@label m for meter"
-msgid "%1m"
-msgstr "%1m"
-
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/CuraPrintProfileCreatorView.qml:148
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/CuraPrintProfileCreatorView.qml:157
-#: /home/ruben/Projects/Cura/resources/qml/PrepareSidebar.qml:447
-#: /home/ruben/Projects/Cura/resources/qml/PrepareSidebar.qml:456
-msgctxt "@label g for grams"
-msgid "%1g"
-msgstr "%1g"
-
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/CuraPrintProfileCreatorView.qml:155
-#: /home/ruben/Projects/Cura/resources/qml/PrepareSidebar.qml:454
-msgctxt "@label"
-msgid "Total:"
-msgstr "Total :"
-
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/CuraPrintProfileCreatorView.qml:205
-msgctxt "@label Print estimates: m for meters, g for grams, %4 is currency and %3 is print cost"
-msgid "%1m / ~ %2g / ~ %4 %3"
-msgstr "%1m / ~ %2g / ~ %4 %3"
-
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/CuraPrintProfileCreatorView.qml:210
-msgctxt "@label Print estimates: m for meters, g for grams"
-msgid "%1m / ~ %2g"
-msgstr "%1m / ~ %2g"
-
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/ProfileCreatorPage.qml:143
+#: /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:26
+#: /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
+#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UM2UpgradeSelectionMachineAction.qml:30
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
+#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UM2UpgradeSelectionMachineAction.qml:44
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/UpgradeFirmwareMachineAction.qml:30
-msgctxt "@title"
-msgid "Upgrade Firmware"
-msgstr "Mise à niveau du firmware"
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UpgradeFirmwareMachineAction.qml:41
-msgctxt "@label"
-msgid "Firmware is the piece of software running directly on your 3D printer. This firmware controls the step motors, regulates the temperature and ultimately makes your printer work."
-msgstr "Le firmware est le logiciel fonctionnant directement dans votre imprimante 3D. Ce firmware contrôle les moteurs pas à pas, régule la température et surtout, fait que votre machine fonctionne."
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UpgradeFirmwareMachineAction.qml:51
-msgctxt "@label"
-msgid "The firmware shipping with new printers works, but new versions tend to have more features and improvements."
-msgstr "Le firmware fourni avec les nouvelles imprimantes fonctionne, mais les nouvelles versions ont tendance à fournir davantage de fonctionnalités ainsi que des améliorations."
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UpgradeFirmwareMachineAction.qml:65
-msgctxt "@action:button"
-msgid "Automatically upgrade Firmware"
-msgstr "Mise à niveau automatique du firmware"
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UpgradeFirmwareMachineAction.qml:75
-msgctxt "@action:button"
-msgid "Upload custom Firmware"
-msgstr "Charger le firmware personnalisé"
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UpgradeFirmwareMachineAction.qml:87
-msgctxt "@title:window"
-msgid "Select custom firmware"
-msgstr "Sélectionner le firmware personnalisé"
-
-#: /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"
@@ -2613,7 +2934,6 @@ msgid "Printer does not accept commands"
msgstr "L'imprimante n'accepte pas les commandes"
#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:133
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:197
msgctxt "@label:MonitorStatus"
msgid "In maintenance. Please check the printer"
msgstr "En maintenance. Vérifiez l'imprimante"
@@ -2624,19 +2944,16 @@ msgid "Lost connection with the printer"
msgstr "Connexion avec l'imprimante perdue"
#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:146
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:187
msgctxt "@label:MonitorStatus"
msgid "Printing..."
msgstr "Impression..."
#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:149
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:189
msgctxt "@label:MonitorStatus"
msgid "Paused"
msgstr "En pause"
#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:152
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:191
msgctxt "@label:MonitorStatus"
msgid "Preparing..."
msgstr "Préparation..."
@@ -2656,229 +2973,170 @@ 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/DiscardOrKeepProfileChangesDialog.qml:15
-msgctxt "@title:window"
-msgid "Discard or Keep changes"
-msgstr "Annuler ou conserver les modifications"
-
-#: /home/ruben/Projects/Cura/resources/qml/DiscardOrKeepProfileChangesDialog.qml:57
-msgctxt "@text:window"
-msgid ""
-"You have customized some profile settings.\n"
-"Would you like to keep or discard those settings?"
-msgstr ""
-"Vous avez personnalisé certains paramètres du profil.\n"
-"Souhaitez-vous conserver ces changements, ou les annuler ?"
-
-#: /home/ruben/Projects/Cura/resources/qml/DiscardOrKeepProfileChangesDialog.qml:110
-msgctxt "@title:column"
-msgid "Profile settings"
-msgstr "Paramètres du profil"
-
-#: /home/ruben/Projects/Cura/resources/qml/DiscardOrKeepProfileChangesDialog.qml:117
-msgctxt "@title:column"
-msgid "Default"
-msgstr "Par défaut"
-
-#: /home/ruben/Projects/Cura/resources/qml/DiscardOrKeepProfileChangesDialog.qml:124
-msgctxt "@title:column"
-msgid "Customized"
-msgstr "Personnalisé"
-
-#: /home/ruben/Projects/Cura/resources/qml/DiscardOrKeepProfileChangesDialog.qml:157
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:639
-msgctxt "@option:discardOrKeep"
-msgid "Always ask me this"
-msgstr "Toujours me demander"
-
-#: /home/ruben/Projects/Cura/resources/qml/DiscardOrKeepProfileChangesDialog.qml:158
-msgctxt "@option:discardOrKeep"
-msgid "Discard and never ask again"
-msgstr "Annuler et ne plus me demander"
-
-#: /home/ruben/Projects/Cura/resources/qml/DiscardOrKeepProfileChangesDialog.qml:159
-msgctxt "@option:discardOrKeep"
-msgid "Keep and never ask again"
-msgstr "Conserver et ne plus me demander"
-
-#: /home/ruben/Projects/Cura/resources/qml/DiscardOrKeepProfileChangesDialog.qml:196
-msgctxt "@action:button"
-msgid "Discard"
-msgstr "Annuler"
-
-#: /home/ruben/Projects/Cura/resources/qml/DiscardOrKeepProfileChangesDialog.qml:209
-msgctxt "@action:button"
-msgid "Keep"
-msgstr "Conserver"
-
-#: /home/ruben/Projects/Cura/resources/qml/DiscardOrKeepProfileChangesDialog.qml:222
-msgctxt "@action:button"
-msgid "Create New Profile"
-msgstr "Créer un nouveau profil"
-
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:71
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:73
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:102
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:103
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:127
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:137
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:147
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:157
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:207
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:209
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:224
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:258
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:275
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:293
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:302
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:316
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:323
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:334
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:347
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/Preferences/Materials/MaterialsView.qml:373
+#: /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:35
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:72
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:99
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:40
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:73
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:117
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:131
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:160
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:148
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:223
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:239
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:287
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:253
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:240
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:290
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:254
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:304
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:312
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:313
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:317
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:335
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:343
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:347
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:353
msgctxt "@info:status Don't translate the XML tag !"
msgid "Successfully exported material to %1"
msgstr "Matériau exporté avec succès vers %1"
@@ -2888,649 +3146,536 @@ msgctxt "@title:tab"
msgid "Setting Visibility"
msgstr "Visibilité des paramètres"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/SettingVisibilityPage.qml:50
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/SettingVisibilityPage.qml:46
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:48
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:61
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:68
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:75
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:83
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:537
+#: /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:141
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:130
msgctxt "@label"
msgid "Interface"
msgstr "Interface"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:152
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:141
msgctxt "@label"
msgid "Language:"
msgstr "Langue :"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:220
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:208
msgctxt "@label"
msgid "Currency:"
msgstr "Devise :"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:234
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:221
msgctxt "@label"
msgid "Theme:"
msgstr "Thème :"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:294
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:277
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:311
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:294
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:319
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:302
msgctxt "@option:check"
msgid "Slice automatically"
msgstr "Découper automatiquement"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:333
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:316
msgctxt "@label"
msgid "Viewport behavior"
msgstr "Comportement Viewport"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:341
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:324
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:350
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:333
msgctxt "@option:check"
msgid "Display overhang"
msgstr "Mettre en surbrillance les porte-à-faux"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:357
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:341
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:362
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:346
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:371
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:356
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:376
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:361
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:386
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:371
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:391
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:371
+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."
+
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:376
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:401
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:402
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:406
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:407
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:415
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:416
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:420
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:421
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:432
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:433
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:441
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:442
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:449
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:450
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:454
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:455
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:470
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:465
+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:472
+msgctxt "@window:text"
+msgid "Camera rendering: "
+msgstr "Rendu caméra : "
+
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:483
+msgid "Perspective"
+msgstr "Perspective"
+
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:484
+msgid "Orthogonal"
+msgstr "Orthogonale"
+
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:515
msgctxt "@label"
msgid "Opening and saving files"
msgstr "Ouvrir et enregistrer des fichiers"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:477
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:522
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:482
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:527
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:492
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:537
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:497
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:542
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:507
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:552
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:512
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:557
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:522
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:567
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:527
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:572
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:537
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:582
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:541
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:586
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:551
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:596
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:559
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:604
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:573
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:618
msgctxt "@option:openProject"
msgid "Always ask me this"
msgstr "Toujours me demander"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:574
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:619
msgctxt "@option:openProject"
msgid "Always open as a project"
msgstr "Toujours ouvrir comme projet"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:575
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:620
msgctxt "@option:openProject"
msgid "Always import models"
msgstr "Toujours importer les modèles"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:611
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:656
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:620
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:665
msgctxt "@label"
msgid "Profiles"
msgstr "Profils"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:625
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:670
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:640
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:684
+#: /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:685
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:641
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:686
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:675
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:720
msgctxt "@label"
msgid "Privacy"
msgstr "Confidentialité"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:683
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:727
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:688
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:732
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:699
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:742
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:704
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:747
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:713
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:756
msgctxt "@action:button"
msgid "More information"
msgstr "Plus d'informations"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:731
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:774
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/PrintSetupSelectorHeader.qml:27
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ProfileMenu.qml:23
msgctxt "@label"
msgid "Experimental"
msgstr "Expérimental"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:738
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:781
msgctxt "@info:tooltip"
msgid "Use multi build plate functionality"
msgstr "Utiliser la fonctionnalité multi-plateau"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:743
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:786
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:542
+#: /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:55
-#: /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:134
msgctxt "@action:button"
msgid "Rename"
msgstr "Renommer"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:147
-msgctxt "@label"
-msgid "Printer type:"
-msgstr "Type d'imprimante :"
-
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:156
-msgctxt "@label"
-msgid "Connection:"
-msgstr "Connexion :"
-
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:162
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/OutputDeviceHeader.qml:47
-msgctxt "@info:status"
-msgid "The printer is not connected."
-msgstr "L'imprimante n'est pas connectée."
-
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:168
-msgctxt "@label"
-msgid "State:"
-msgstr "État :"
-
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:181
-msgctxt "@label:MonitorStatus"
-msgid "Waiting for a printjob"
-msgstr "En attente d'une tâche d'impression"
-
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:193
-msgctxt "@label:MonitorStatus"
-msgid "Waiting for someone to clear the build plate"
-msgstr "En attente du dégagement du plateau"
-
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:199
-msgctxt "@label:MonitorStatus"
-msgid "Aborting print..."
-msgstr "Abandon de l'impression..."
-
#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:36
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:546
+#: /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:89
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:105
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:181
msgctxt "@title:window"
msgid "Create Profile"
msgstr "Créer un profil"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:225
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:183
+msgctxt "@info"
+msgid "Please provide a name for this profile."
+msgstr "Veuillez fournir un nom pour ce profil."
+
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:239
msgctxt "@title:window"
msgid "Duplicate Profile"
msgstr "Dupliquer un profil"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:256
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:270
msgctxt "@title:window"
msgid "Rename Profile"
msgstr "Renommer le profil"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:269
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:283
msgctxt "@title:window"
msgid "Import Profile"
msgstr "Importer un profil"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:295
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:309
msgctxt "@title:window"
msgid "Export Profile"
msgstr "Exporter un profil"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:350
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:364
msgctxt "@label %1 is printer name"
msgid "Printer: %1"
msgstr "Imprimante : %1"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:403
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:420
msgctxt "@label"
-msgid "Protected profiles"
-msgstr "Profils protégés"
+msgid "Default profiles"
+msgstr "Profils par défaut"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:403
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:420
msgctxt "@label"
msgid "Custom profiles"
msgstr "Personnaliser les profils"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:480
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:500
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:487
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:507
msgctxt "@action:button"
msgid "Discard current changes"
msgstr "Ignorer les modifications actuelles"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:504
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:524
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:511
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:531
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:530
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:550
msgctxt "@title:tab"
msgid "Global Settings"
msgstr "Paramètres généraux"
-#: /home/ruben/Projects/Cura/resources/qml/AddMachineDialog.qml:18
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:946
-msgctxt "@title:window"
-msgid "Add Printer"
-msgstr "Ajouter une imprimante"
-
-#: /home/ruben/Projects/Cura/resources/qml/AddMachineDialog.qml:194
-msgctxt "@label"
-msgid "Printer Name:"
-msgstr "Nom de l'imprimante :"
-
-#: /home/ruben/Projects/Cura/resources/qml/AddMachineDialog.qml:217
+#: /home/ruben/Projects/Cura/resources/qml/MainWindow/MainWindowHeader.qml:89
msgctxt "@action:button"
-msgid "Add Printer"
-msgstr "Ajouter une imprimante"
+msgid "Marketplace"
+msgstr "Marché en ligne"
-#: /home/ruben/Projects/Cura/resources/qml/JobSpecs.qml:84
+#: /home/ruben/Projects/Cura/resources/qml/MainWindow/ApplicationMenu.qml:27
+#: /home/ruben/Projects/Cura/resources/qml/Menus/FileMenu.qml:13
+msgctxt "@title:menu menubar:toplevel"
+msgid "&File"
+msgstr "&Fichier"
+
+#: /home/ruben/Projects/Cura/resources/qml/MainWindow/ApplicationMenu.qml:31
+msgctxt "@title:menu menubar:toplevel"
+msgid "&Edit"
+msgstr "&Modifier"
+
+#: /home/ruben/Projects/Cura/resources/qml/MainWindow/ApplicationMenu.qml:48
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ViewMenu.qml:12
+msgctxt "@title:menu menubar:toplevel"
+msgid "&View"
+msgstr "&Visualisation"
+
+#: /home/ruben/Projects/Cura/resources/qml/MainWindow/ApplicationMenu.qml:50
+#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:13
+msgctxt "@title:menu menubar:toplevel"
+msgid "&Settings"
+msgstr "&Paramètres"
+
+#: /home/ruben/Projects/Cura/resources/qml/MainWindow/ApplicationMenu.qml:55
+msgctxt "@title:menu menubar:toplevel"
+msgid "E&xtensions"
+msgstr "E&xtensions"
+
+#: /home/ruben/Projects/Cura/resources/qml/MainWindow/ApplicationMenu.qml:89
+msgctxt "@title:menu menubar:toplevel"
+msgid "P&references"
+msgstr "P&références"
+
+#: /home/ruben/Projects/Cura/resources/qml/MainWindow/ApplicationMenu.qml:97
+msgctxt "@title:menu menubar:toplevel"
+msgid "&Help"
+msgstr "&Aide"
+
+#: /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: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."
+
+#: /home/ruben/Projects/Cura/resources/qml/JobSpecs.qml:88
msgctxt "@text Print job name"
msgid "Untitled"
msgstr "Sans titre"
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:15
-msgctxt "@title:window"
-msgid "About Cura"
-msgstr "À propos de Cura"
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:43
-msgctxt "@label"
-msgid "version: %1"
-msgstr "version : %1"
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:56
-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/AboutDialog.qml:69
-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 ""
-"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/AboutDialog.qml:118
-msgctxt "@label"
-msgid "Graphical user interface"
-msgstr "Interface utilisateur graphique"
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:119
-msgctxt "@label"
-msgid "Application framework"
-msgstr "Cadre d'application"
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:120
-msgctxt "@label"
-msgid "G-code generator"
-msgstr "Générateur G-Code"
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:121
-msgctxt "@label"
-msgid "Interprocess communication library"
-msgstr "Bibliothèque de communication interprocess"
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:123
-msgctxt "@label"
-msgid "Programming language"
-msgstr "Langage de programmation"
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:124
-msgctxt "@label"
-msgid "GUI framework"
-msgstr "Cadre IUG"
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:125
-msgctxt "@label"
-msgid "GUI framework bindings"
-msgstr "Liens cadre IUG"
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:126
-msgctxt "@label"
-msgid "C/C++ Binding library"
-msgstr "Bibliothèque C/C++ Binding"
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:127
-msgctxt "@label"
-msgid "Data interchange format"
-msgstr "Format d'échange de données"
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:128
-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/AboutDialog.qml:129
-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/AboutDialog.qml:130
-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/AboutDialog.qml:131
-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/AboutDialog.qml:132
-msgctxt "@label"
-msgid "Serial communication library"
-msgstr "Bibliothèque de communication série"
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:133
-msgctxt "@label"
-msgid "ZeroConf discovery library"
-msgstr "Bibliothèque de découverte ZeroConf"
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:134
-msgctxt "@label"
-msgid "Polygon clipping library"
-msgstr "Bibliothèque de découpe polygone"
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:135
-msgctxt "@Label"
-msgid "Python HTTP library"
-msgstr "Bibliothèque Python HTTP"
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:137
-msgctxt "@label"
-msgid "Font"
-msgstr "Police"
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:138
-msgctxt "@label"
-msgid "SVG icons"
-msgstr "Icônes SVG"
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:139
-msgctxt "@label"
-msgid "Linux cross-distribution application deployment"
-msgstr "Déploiement d'applications sur multiples distributions Linux"
-
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:42
-msgctxt "@label"
-msgid "Profile:"
-msgstr "Profil :"
-
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:103
-msgctxt "@tooltip"
-msgid ""
-"Some setting/override values are different from the values stored in the profile.\n"
-"\n"
-"Click to open the profile manager."
-msgstr ""
-"Certaines valeurs de paramètre / forçage sont différentes des valeurs enregistrées dans le profil. \n"
-"\n"
-"Cliquez pour ouvrir le gestionnaire de profils."
-
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:199
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:68
msgctxt "@label:textbox"
-msgid "Search..."
-msgstr "Rechercher..."
+msgid "search settings"
+msgstr "paramètres de recherche"
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:544
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:466
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:553
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:475
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:590
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:512
msgctxt "@action:menu"
msgid "Hide this setting"
msgstr "Masquer ce paramètre"
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:608
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:525
msgctxt "@action:menu"
msgid "Don't show this setting"
msgstr "Masquer ce paramètre"
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:612
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:529
msgctxt "@action:menu"
msgid "Keep this setting visible"
msgstr "Afficher ce paramètre"
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:636
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:416
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:548
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:434
msgctxt "@action:menu"
msgid "Configure setting visibility..."
msgstr "Configurer la visibilité des paramètres..."
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:643
-msgctxt "@action:inmenu"
-msgid "Collapse All"
-msgstr "Réduire tout"
-
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:648
-msgctxt "@action:inmenu"
-msgid "Expand All"
-msgstr "Développer tout"
-
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingCategory.qml:249
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingCategory.qml:237
msgctxt "@label"
msgid ""
"Some hidden settings use values different from their normal calculated value.\n"
@@ -3541,27 +3686,32 @@ msgstr ""
"\n"
"Cliquez pour rendre ces paramètres visibles."
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:61
+#: /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:66
+#: /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:154
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:186
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:157
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:190
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:188
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:228
msgctxt "@label"
msgid ""
"This setting has a value that is different from the profile.\n"
@@ -3572,7 +3722,7 @@ msgstr ""
"\n"
"Cliquez pour restaurer la valeur du profil."
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:286
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:322
msgctxt "@label"
msgid ""
"This setting is normally calculated, but it currently has an absolute value set.\n"
@@ -3583,116 +3733,210 @@ msgstr ""
"\n"
"Cliquez pour restaurer la valeur calculée."
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ManualPrinterControl.qml:129
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/PrintSetupSelectorContents.qml:144
+msgctxt "@button"
+msgid "Recommended"
+msgstr "Recommandé"
+
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/PrintSetupSelectorContents.qml:158
+msgctxt "@button"
+msgid "Custom"
+msgstr "Personnalisé"
+
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedInfillDensitySelector.qml:193
+msgctxt "@label"
+msgid "Gradual infill"
+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:30
+msgctxt "@label"
+msgid "Support"
+msgstr "Support"
+
+#: /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/RecommendedAdhesionSelector.qml:29
+msgctxt "@label"
+msgid "Adhesion"
+msgstr "Adhérence"
+
+#: /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
+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 "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é."
+
+#: /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 "On"
+
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/PrintSetupSelectorHeader.qml:14
+msgctxt "@label:Should be short"
+msgid "Off"
+msgstr "Off"
+
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Custom/GlobalProfileSelector.qml:27
+msgctxt "@label"
+msgid "Profile"
+msgstr "Profil"
+
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Custom/GlobalProfileSelector.qml:94
+msgctxt "@tooltip"
+msgid ""
+"Some setting/override values are different from the values stored in the profile.\n"
+"\n"
+"Click to open the profile manager."
+msgstr ""
+"Certaines valeurs de paramètre / forçage sont différentes des valeurs enregistrées dans le profil. \n"
+"\n"
+"Cliquez pour ouvrir le gestionnaire de 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 "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"
msgid "Printer control"
msgstr "Contrôle de l'imprimante"
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ManualPrinterControl.qml:144
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ManualPrinterControl.qml:67
msgctxt "@label"
msgid "Jog Position"
msgstr "Position de coupe"
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ManualPrinterControl.qml:162
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ManualPrinterControl.qml:85
msgctxt "@label"
msgid "X/Y"
msgstr "X/Y"
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ManualPrinterControl.qml:269
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ManualPrinterControl.qml:192
msgctxt "@label"
msgid "Z"
msgstr "Z"
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ManualPrinterControl.qml:334
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ManualPrinterControl.qml:257
msgctxt "@label"
msgid "Jog Distance"
msgstr "Distance de coupe"
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ManualPrinterControl.qml:443
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ManualPrinterControl.qml:301
msgctxt "@label"
msgid "Send G-code"
msgstr "Envoyer G-Code"
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ManualPrinterControl.qml:506
+#: /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:36
-#: /home/ruben/Projects/Cura/resources/qml/SidebarHeader.qml:272
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:38
msgctxt "@label"
msgid "Extruder"
msgstr "Extrudeuse"
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:66
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:68
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:98
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:100
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:172
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:174
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:336
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/HeatedBedBox.qml:331
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:338
+#: /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:339
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/HeatedBedBox.qml:334
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:341
+#: /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:365
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:367
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:401
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:403
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:433
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:435
msgctxt "@tooltip"
msgid "The material in this extruder."
msgstr "Matériau dans cet extrudeur."
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:465
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:467
msgctxt "@tooltip"
msgid "The nozzle inserted in this extruder."
msgstr "Buse insérée dans cet extrudeur."
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/HeatedBedBox.qml:25
-#: /home/ruben/Projects/Cura/resources/qml/SidebarHeader.qml:493
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/OutputDeviceHeader.qml:55
+msgctxt "@info:status"
+msgid "The printer is not connected."
+msgstr "L'imprimante n'est pas connectée."
+
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/HeatedBedBox.qml:26
msgctxt "@label"
msgid "Build plate"
msgstr "Plateau"
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/HeatedBedBox.qml:55
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/HeatedBedBox.qml:56
msgctxt "@tooltip"
msgid "The target temperature of the heated bed. The bed will heat up or cool down towards this temperature. If this is 0, the bed heating is turned off."
msgstr "Température cible du plateau chauffant. Le plateau sera chauffé ou refroidi pour tendre vers cette température. Si la valeur est 0, le chauffage du plateau sera éteint."
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/HeatedBedBox.qml:87
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/HeatedBedBox.qml:88
msgctxt "@tooltip"
msgid "The current temperature of the heated bed."
msgstr "Température actuelle du plateau chauffant."
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/HeatedBedBox.qml:160
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/HeatedBedBox.qml:161
msgctxt "@tooltip of temperature input"
msgid "The temperature to pre-heat the bed to."
msgstr "Température jusqu'à laquelle préchauffer le plateau."
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/HeatedBedBox.qml:360
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/HeatedBedBox.qml:361
msgctxt "@tooltip of pre-heat"
msgid "Heat the bed in advance before printing. You can continue adjusting your print while it is heating, and you won't have to wait for the bed to heat up when you're ready to print."
msgstr "Préchauffez le plateau avant l'impression. Vous pouvez continuer à ajuster votre impression pendant qu'il chauffe, et vous n'aurez pas à attendre que le plateau chauffe lorsque vous serez prêt à lancer l'impression."
@@ -3702,16 +3946,11 @@ msgctxt "@label:category menu label"
msgid "Material"
msgstr "Matériau"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/MaterialMenu.qml:37
+#: /home/ruben/Projects/Cura/resources/qml/Menus/MaterialMenu.qml:42
msgctxt "@label:category menu label"
msgid "Favorites"
msgstr "Favoris"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/MaterialMenu.qml:61
-msgctxt "@label:category menu label"
-msgid "Generic"
-msgstr "Générique"
-
#: /home/ruben/Projects/Cura/resources/qml/Menus/PrinterMenu.qml:25
msgctxt "@label:category menu label"
msgid "Network enabled printers"
@@ -3722,17 +3961,62 @@ msgctxt "@label:category menu label"
msgid "Local printers"
msgstr "Imprimantes locales"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/ViewMenu.qml:12
-msgctxt "@title:menu menubar:toplevel"
-msgid "&View"
-msgstr "&Visualisation"
+#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:15
+msgctxt "@title:menu menubar:settings"
+msgid "&Printer"
+msgstr "Im&primante"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/ViewMenu.qml:39
+#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:32
+msgctxt "@title:menu"
+msgid "&Material"
+msgstr "&Matériau"
+
+#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:41
+msgctxt "@action:inmenu"
+msgid "Set as Active Extruder"
+msgstr "Définir comme extrudeur actif"
+
+#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:47
+msgctxt "@action:inmenu"
+msgid "Enable Extruder"
+msgstr "Activer l'extrudeuse"
+
+#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:54
+msgctxt "@action:inmenu"
+msgid "Disable Extruder"
+msgstr "Désactiver l'extrudeuse"
+
+#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:68
+msgctxt "@title:menu"
+msgid "&Build plate"
+msgstr "Plateau"
+
+#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:71
+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:54
+#: /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"
@@ -3742,16 +4026,31 @@ msgctxt "@action:inmenu"
msgid "Visible Settings"
msgstr "Paramètres visibles"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingVisibilityPresetsMenu.qml:43
+#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingVisibilityPresetsMenu.qml:42
msgctxt "@action:inmenu"
msgid "Show All Settings"
msgstr "Afficher tous les paramètres"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingVisibilityPresetsMenu.qml:54
+#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingVisibilityPresetsMenu.qml:53
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
+msgctxt "@title:menu menubar:file"
+msgid "&Save..."
+msgstr "Enregi&strer..."
+
+#: /home/ruben/Projects/Cura/resources/qml/Menus/FileMenu.qml:53
+msgctxt "@title:menu menubar:file"
+msgid "&Export..."
+msgstr "&Exporter..."
+
+#: /home/ruben/Projects/Cura/resources/qml/Menus/FileMenu.qml:64
+msgctxt "@action:inmenu menubar:file"
+msgid "Export Selection..."
+msgstr "Exporter la sélection..."
+
#: /home/ruben/Projects/Cura/resources/qml/Menus/ContextMenu.qml:27
msgctxt "@label"
msgid "Print Selected Model With:"
@@ -3771,634 +4070,509 @@ msgctxt "@label"
msgid "Number of Copies"
msgstr "Nombre de copies"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/ConfigurationListView.qml:33
-msgctxt "@label:header configurations"
-msgid "Available configurations"
-msgstr "Configurations disponibles"
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/AutoConfiguration.qml:18
+msgctxt "@header"
+msgid "Configurations"
+msgstr "Configurations"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/PrintCoreConfiguration.qml:28
-msgctxt "@label:extruder label"
-msgid "Extruder"
-msgstr "Extrudeuse"
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/ConfigurationMenu.qml:110
+msgctxt "@label"
+msgid "Select configuration"
+msgstr "Sélectionner la configuration"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/SyncButton.qml:16
-msgctxt "@label:extruder label"
-msgid "Yes"
-msgstr "Oui"
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/ConfigurationMenu.qml:221
+msgctxt "@label"
+msgid "Configurations"
+msgstr "Configurations"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/SyncButton.qml:16
-msgctxt "@label:extruder label"
-msgid "No"
-msgstr "Non"
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/ConfigurationListView.qml:57
+msgctxt "@label"
+msgid "Loading available configurations from the printer..."
+msgstr "Chargement des configurations disponibles à partir de l'imprimante..."
-#: /home/ruben/Projects/Cura/resources/qml/Menus/RecentFilesMenu.qml:13
+#: /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 "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 "Personnalisé"
+
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/CustomConfiguration.qml:61
+msgctxt "@label"
+msgid "Printer"
+msgstr "Imprimante"
+
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/CustomConfiguration.qml:213
+msgctxt "@label"
+msgid "Enabled"
+msgstr "Activé"
+
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/CustomConfiguration.qml:250
+msgctxt "@label"
+msgid "Material"
+msgstr "Matériau"
+
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/CustomConfiguration.qml:375
+msgctxt "@label"
+msgid "Use glue for better adhesion with this material combination."
+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 "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 "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/PrepareSidebar.qml:150
-msgctxt "@label:listbox"
-msgid "Print Setup"
-msgstr "Configuration de l'impression"
-
-#: /home/ruben/Projects/Cura/resources/qml/PrepareSidebar.qml:150
-msgctxt "@label:listbox"
-msgid ""
-"Print Setup disabled\n"
-"G-code files cannot be modified"
-msgstr ""
-"Configuration de l'impression désactivée\n"
-"Les fichiers G-Code ne peuvent pas être modifiés"
-
-#: /home/ruben/Projects/Cura/resources/qml/PrepareSidebar.qml:359
-msgctxt "@tooltip"
-msgid "Time specification"
-msgstr "Spécification de temps"
-
-#: /home/ruben/Projects/Cura/resources/qml/PrepareSidebar.qml:577
-msgctxt "@tooltip"
-msgid "Recommended Print Setup
Print with the recommended settings for the selected printer, material and quality."
-msgstr "Configuration de l'impression recommandée
Imprimer avec les paramètres recommandés pour l'imprimante, le matériau et la qualité sélectionnés."
-
-#: /home/ruben/Projects/Cura/resources/qml/PrepareSidebar.qml:582
-msgctxt "@tooltip"
-msgid "Custom Print Setup
Print with finegrained control over every last bit of the slicing process."
-msgstr "Configuration de l'impression personnalisée
Imprimer avec un contrôle fin de chaque élément du processus de découpe."
-
-#: /home/ruben/Projects/Cura/resources/qml/PrintMonitor.qml:106
+#: /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:114
+#: /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:122
+#: /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:130
+#: /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/Actions.qml:78
+#: /home/ruben/Projects/Cura/resources/qml/ViewsSelector.qml:50
+msgctxt "@label"
+msgid "View type"
+msgstr "Type d'affichage"
+
+#: /home/ruben/Projects/Cura/resources/qml/ObjectSelector.qml:59
+msgctxt "@label"
+msgid "Object list"
+msgstr "Liste d'objets"
+
+#: /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 "Compte Ultimaker"
+
+#: /home/ruben/Projects/Cura/resources/qml/Account/UserOperations.qml:42
+msgctxt "@button"
+msgid "Sign out"
+msgstr "Déconnexion"
+
+#: /home/ruben/Projects/Cura/resources/qml/Account/AccountWidget.qml:24
+msgctxt "@action:button"
+msgid "Sign in"
+msgstr "Se connecter"
+
+#: /home/ruben/Projects/Cura/resources/qml/Account/GeneralOperations.qml:40
+msgctxt "@label"
+msgid "The next generation 3D printing workflow"
+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 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 "Créer un compte"
+
+#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/OutputProcessWidget.qml:59
+msgctxt "@label"
+msgid "No time estimation available"
+msgstr "Aucune estimation de la durée n'est disponible"
+
+#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/OutputProcessWidget.qml:77
+msgctxt "@label"
+msgid "No cost estimation available"
+msgstr "Aucune estimation des coûts n'est disponible"
+
+#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/OutputProcessWidget.qml:127
+msgctxt "@button"
+msgid "Preview"
+msgstr "Aperçu"
+
+#: /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:67
+msgctxt "@label:PrintjobStatus"
+msgid "Unable to slice"
+msgstr "Impossible de découper"
+
+#: /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 "Découper"
+
+#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/SliceProcessWidget.qml:104
+msgctxt "@label"
+msgid "Start the slicing process"
+msgstr "Démarrer le processus de découpe"
+
+#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/SliceProcessWidget.qml:118
+msgctxt "@button"
+msgid "Cancel"
+msgstr "Annuler"
+
+#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/PrintJobInformation.qml:31
+msgctxt "@label"
+msgid "Time estimation"
+msgstr "Estimation de durée"
+
+#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/PrintJobInformation.qml:114
+msgctxt "@label"
+msgid "Material estimation"
+msgstr "Estimation du matériau"
+
+#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/PrintJobInformation.qml:164
+msgctxt "@label m for meter"
+msgid "%1m"
+msgstr "%1m"
+
+#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/PrintJobInformation.qml:165
+msgctxt "@label g for grams"
+msgid "%1g"
+msgstr "%1g"
+
+#: /home/ruben/Projects/Cura/resources/qml/PrinterSelector/MachineSelectorList.qml:19
+msgctxt "@label"
+msgid "Connected printers"
+msgstr "Imprimantes connectées"
+
+#: /home/ruben/Projects/Cura/resources/qml/PrinterSelector/MachineSelectorList.qml:19
+msgctxt "@label"
+msgid "Preset printers"
+msgstr "Imprimantes préréglées"
+
+#: /home/ruben/Projects/Cura/resources/qml/PrinterSelector/MachineSelector.qml:166
+msgctxt "@button"
+msgid "Add printer"
+msgstr "Ajouter une imprimante"
+
+#: /home/ruben/Projects/Cura/resources/qml/PrinterSelector/MachineSelector.qml:182
+msgctxt "@button"
+msgid "Manage printers"
+msgstr "Gérer les imprimantes"
+
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:81
+msgctxt "@action:inmenu"
+msgid "Show Online Troubleshooting Guide"
+msgstr "Afficher le guide de dépannage en ligne"
+
+#: /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:85
+#: /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:95
+#: /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:105
+#: /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:113
+#: /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:120
+#: /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:127
+#: /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:134
+#: /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:141
+#: /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:148
+#: /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:155
+#: /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:161
+#: /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:168
+#: /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:176
+#: /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:184
+#: /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:196
+#: /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:202
+#: /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:209
+#: /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:217
+#: /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:225
+#: /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:232
+#: /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:242
+#: /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:251
+#: /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:260
+#: /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:268
+#: /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:274
+#: /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:294
+#: /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:304
+#: /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:314
+#: /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:321
+#: /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:331
+#: /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:341
+#: /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:350
+#: /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:357
+#: /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:365
+#: /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:372
+#: /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:379
+#: /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:386
+#: /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:394
+#: /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:401
-msgctxt "@action:inmenu menubar:help"
-msgid "Show Engine &Log..."
-msgstr "Afficher le &journal du moteur..."
-
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:409
+#: /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:423
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:441
msgctxt "@action:menu"
-msgid "Browse packages..."
-msgstr "Parcourir les paquets..."
+msgid "&Marketplace"
+msgstr "&Marché en ligne"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:430
-msgctxt "@action:inmenu menubar:view"
-msgid "Expand/Collapse Sidebar"
-msgstr "Déplier / replier la barre latérale"
-
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:27
-msgctxt "@label:PrintjobStatus"
-msgid "Please load a 3D model"
-msgstr "Veuillez charger un modèle 3D"
-
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:37
-msgctxt "@label:PrintjobStatus"
-msgid "Ready to slice"
-msgstr "Prêt à découper"
-
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:39
-msgctxt "@label:PrintjobStatus"
-msgid "Slicing..."
-msgstr "Découpe en cours..."
-
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:41
-msgctxt "@label:PrintjobStatus %1 is target operation"
-msgid "Ready to %1"
-msgstr "Prêt à %1"
-
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:43
-msgctxt "@label:PrintjobStatus"
-msgid "Unable to Slice"
-msgstr "Impossible de découper"
-
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:45
-msgctxt "@label:PrintjobStatus"
-msgid "Slicing unavailable"
-msgstr "Découpe indisponible"
-
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:172
-msgctxt "@info:tooltip"
-msgid "Slice current printjob"
-msgstr "Découper la tâche d'impression en cours"
-
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:172
-msgctxt "@info:tooltip"
-msgid "Cancel slicing process"
-msgstr "Annuler le processus de découpe"
-
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:184
-msgctxt "@label:Printjob"
-msgid "Prepare"
-msgstr "Préparer"
-
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:184
-msgctxt "@label:Printjob"
-msgid "Cancel"
-msgstr "Annuler"
-
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:320
-msgctxt "@info:tooltip"
-msgid "Select the active output device"
-msgstr "Sélectionner le périphérique de sortie actif"
-
-#: /home/ruben/Projects/Cura/resources/qml/OpenFilesIncludingProjectsDialog.qml:19
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:760
-msgctxt "@title:window"
-msgid "Open file(s)"
-msgstr "Ouvrir le(s) fichier(s)"
-
-#: /home/ruben/Projects/Cura/resources/qml/OpenFilesIncludingProjectsDialog.qml:64
-msgctxt "@text:window"
-msgid "We have found one or more project file(s) within the files you have selected. You can open only one project file at a time. We suggest to only import models from those files. Would you like to proceed?"
-msgstr "Nous avons trouvé au moins un fichier de projet parmi les fichiers que vous avez sélectionnés. Vous ne pouvez ouvrir qu'un seul fichier de projet à la fois. Nous vous conseillons de n'importer que les modèles de ces fichiers. Souhaitez-vous continuer ?"
-
-#: /home/ruben/Projects/Cura/resources/qml/OpenFilesIncludingProjectsDialog.qml:99
-msgctxt "@action:button"
-msgid "Import all as models"
-msgstr "Importer tout comme modèles"
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:19
+#: /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:104
-msgctxt "@title:menu menubar:toplevel"
-msgid "&File"
-msgstr "&Fichier"
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:120
-msgctxt "@title:menu menubar:file"
-msgid "&Save..."
-msgstr "Enregi&strer..."
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:141
-msgctxt "@title:menu menubar:file"
-msgid "&Export..."
-msgstr "&Exporter..."
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:151
-msgctxt "@action:inmenu menubar:file"
-msgid "Export Selection..."
-msgstr "Exporter la sélection..."
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:168
-msgctxt "@title:menu menubar:toplevel"
-msgid "&Edit"
-msgstr "&Modifier"
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:185
-msgctxt "@title:menu"
-msgid "&View"
-msgstr "&Visualisation"
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:190
-msgctxt "@title:menu"
-msgid "&Settings"
-msgstr "&Paramètres"
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:192
-msgctxt "@title:menu menubar:settings"
-msgid "&Printer"
-msgstr "Im&primante"
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:201
-msgctxt "@title:menu"
-msgid "&Material"
-msgstr "&Matériau"
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:210
-msgctxt "@action:inmenu"
-msgid "Set as Active Extruder"
-msgstr "Définir comme extrudeur actif"
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:216
-#: /home/ruben/Projects/Cura/resources/qml/SidebarHeader.qml:188
-msgctxt "@action:inmenu"
-msgid "Enable Extruder"
-msgstr "Activer l'extrudeuse"
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:223
-#: /home/ruben/Projects/Cura/resources/qml/SidebarHeader.qml:194
-msgctxt "@action:inmenu"
-msgid "Disable Extruder"
-msgstr "Désactiver l'extrudeuse"
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:235
-msgctxt "@title:menu"
-msgid "&Build plate"
-msgstr "Plateau"
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:236
-msgctxt "@title:settings"
-msgid "&Profile"
-msgstr "&Profil"
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:246
-msgctxt "@title:menu menubar:toplevel"
-msgid "E&xtensions"
-msgstr "E&xtensions"
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:280
-msgctxt "@title:menu menubar:toplevel"
-msgid "&Toolbox"
-msgstr "&Boîte à outils"
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:287
-msgctxt "@title:menu menubar:toplevel"
-msgid "P&references"
-msgstr "P&références"
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:295
-msgctxt "@title:menu menubar:toplevel"
-msgid "&Help"
-msgstr "&Aide"
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:341
+#: /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:370
-msgctxt "@action:button"
-msgid "Open File"
-msgstr "Ouvrir un fichier"
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:540
+#: /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:586
-msgctxt "@title:window"
-msgid "New project"
-msgstr "Nouveau projet"
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:587
-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."
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:715
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:539
msgctxt "@title:window"
msgid "Closing Cura"
msgstr "Fermeture de Cura"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:716
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:728
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:540
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:552
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:861
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:590
+#: /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:691
msgctxt "@window:title"
msgid "Install Package"
msgstr "Installer le paquet"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:868
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:699
msgctxt "@title:window"
msgid "Open File(s)"
msgstr "Ouvrir le(s) fichier(s)"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:871
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:702
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/WorkspaceSummaryDialog.qml:14
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:805
msgctxt "@title:window"
-msgid "Save Project"
-msgstr "Enregistrer le projet"
+msgid "Add Printer"
+msgstr "Ajouter une imprimante"
-#: /home/ruben/Projects/Cura/resources/qml/WorkspaceSummaryDialog.qml:120
-msgctxt "@action:label"
-msgid ""
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/WorkspaceSummaryDialog.qml:137
-msgctxt "@action:label"
-msgid "Build plate"
-msgstr "Plateau"
-
-#: /home/ruben/Projects/Cura/resources/qml/WorkspaceSummaryDialog.qml:169
-msgctxt "@action:label"
-msgid "Extruder %1"
-msgstr "Extrudeuse %1"
-
-#: /home/ruben/Projects/Cura/resources/qml/WorkspaceSummaryDialog.qml:179
-msgctxt "@action:label"
-msgid "%1 & material"
-msgstr "%1 & matériau"
-
-#: /home/ruben/Projects/Cura/resources/qml/WorkspaceSummaryDialog.qml:268
-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/WorkspaceSummaryDialog.qml:287
-msgctxt "@action:button"
-msgid "Save"
-msgstr "Enregistrer"
-
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:192
-msgctxt "@label"
-msgid "Layer Height"
-msgstr "Hauteur de la couche"
-
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:277
-msgctxt "@tooltip"
-msgid "This quality profile is not available for you 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é"
-
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:450
-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/SidebarSimple.qml:467
-msgctxt "@label"
-msgid "Print Speed"
-msgstr "Vitesse d’impression"
-
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:479
-msgctxt "@label"
-msgid "Slower"
-msgstr "Ralentir"
-
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:490
-msgctxt "@label"
-msgid "Faster"
-msgstr "Accélérer"
-
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:518
-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/SidebarSimple.qml:541
-msgctxt "@label"
-msgid "Infill"
-msgstr "Remplissage"
-
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:777
-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/SidebarSimple.qml:789
-msgctxt "@label"
-msgid "Enable gradual"
-msgstr "Permettre le remplissage graduel"
-
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:856
-msgctxt "@label"
-msgid "Generate Support"
-msgstr "Générer les supports"
-
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:890
-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/SidebarSimple.qml:962
-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/SidebarSimple.qml:985
-msgctxt "@label"
-msgid "Build Plate Adhesion"
-msgstr "Adhérence au plateau"
-
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:1040
-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/SidebarSimple.qml:1080
-msgctxt "@label"
-msgid "Need help improving your prints? Read the Ultimaker Troubleshooting Guides"
-msgstr "Besoin d'aide pour améliorer vos impressions ? Lisez les Guides de dépannage Ultimaker"
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:813
+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"
@@ -4407,75 +4581,483 @@ msgid_plural "Print Selected Models with %1"
msgstr[0] "Imprimer le modèle sélectionné avec %1"
msgstr[1] "Imprimer les modèles sélectionnés avec %1"
-#: /home/ruben/Projects/Cura/resources/qml/AskOpenAsProjectOrModelsDialog.qml:20
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/DiscardOrKeepProfileChangesDialog.qml:15
+msgctxt "@title:window"
+msgid "Discard or Keep changes"
+msgstr "Annuler ou conserver les modifications"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/DiscardOrKeepProfileChangesDialog.qml:57
+msgctxt "@text:window"
+msgid ""
+"You have customized some profile settings.\n"
+"Would you like to keep or discard those settings?"
+msgstr ""
+"Vous avez personnalisé certains paramètres du profil.\n"
+"Souhaitez-vous conserver ces changements, ou les annuler ?"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/DiscardOrKeepProfileChangesDialog.qml:110
+msgctxt "@title:column"
+msgid "Profile settings"
+msgstr "Paramètres du profil"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/DiscardOrKeepProfileChangesDialog.qml:117
+msgctxt "@title:column"
+msgid "Default"
+msgstr "Par défaut"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/DiscardOrKeepProfileChangesDialog.qml:124
+msgctxt "@title:column"
+msgid "Customized"
+msgstr "Personnalisé"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/DiscardOrKeepProfileChangesDialog.qml:158
+msgctxt "@option:discardOrKeep"
+msgid "Discard and never ask again"
+msgstr "Annuler et ne plus me demander"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/DiscardOrKeepProfileChangesDialog.qml:159
+msgctxt "@option:discardOrKeep"
+msgid "Keep and never ask again"
+msgstr "Conserver et ne plus me demander"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/DiscardOrKeepProfileChangesDialog.qml:196
+msgctxt "@action:button"
+msgid "Discard"
+msgstr "Annuler"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/DiscardOrKeepProfileChangesDialog.qml:209
+msgctxt "@action:button"
+msgid "Keep"
+msgstr "Conserver"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/DiscardOrKeepProfileChangesDialog.qml:222
+msgctxt "@action:button"
+msgid "Create New Profile"
+msgstr "Créer un nouveau profil"
+
+#: /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
+msgctxt "@label"
+msgid "version: %1"
+msgstr "version : %1"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:71
+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
+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 ""
+"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
+msgctxt "@label"
+msgid "Graphical user interface"
+msgstr "Interface utilisateur graphique"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:135
+msgctxt "@label"
+msgid "Application framework"
+msgstr "Cadre d'application"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:136
+msgctxt "@label"
+msgid "G-code generator"
+msgstr "Générateur G-Code"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:137
+msgctxt "@label"
+msgid "Interprocess communication library"
+msgstr "Bibliothèque de communication interprocess"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:139
+msgctxt "@label"
+msgid "Programming language"
+msgstr "Langage de programmation"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:140
+msgctxt "@label"
+msgid "GUI framework"
+msgstr "Cadre IUG"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:141
+msgctxt "@label"
+msgid "GUI framework bindings"
+msgstr "Liens cadre IUG"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:142
+msgctxt "@label"
+msgid "C/C++ Binding library"
+msgstr "Bibliothèque C/C++ Binding"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:143
+msgctxt "@label"
+msgid "Data interchange format"
+msgstr "Format d'échange de données"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:144
+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
+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
+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
+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
+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
+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
+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
+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
+msgctxt "@label"
+msgid "Serial communication library"
+msgstr "Bibliothèque de communication série"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:153
+msgctxt "@label"
+msgid "ZeroConf discovery library"
+msgstr "Bibliothèque de découverte ZeroConf"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:154
+msgctxt "@label"
+msgid "Polygon clipping library"
+msgstr "Bibliothèque de découpe polygone"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:155
+msgctxt "@Label"
+msgid "Python HTTP library"
+msgstr "Bibliothèque Python HTTP"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:157
+msgctxt "@label"
+msgid "Font"
+msgstr "Police"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:158
+msgctxt "@label"
+msgid "SVG icons"
+msgstr "Icônes SVG"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:159
+msgctxt "@label"
+msgid "Linux cross-distribution application deployment"
+msgstr "Déploiement d'applications sur multiples distributions Linux"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/OpenFilesIncludingProjectsDialog.qml:64
+msgctxt "@text:window"
+msgid "We have found one or more project file(s) within the files you have selected. You can open only one project file at a time. We suggest to only import models from those files. Would you like to proceed?"
+msgstr "Nous avons trouvé au moins un fichier de projet parmi les fichiers que vous avez sélectionnés. Vous ne pouvez ouvrir qu'un seul fichier de projet à la fois. Nous vous conseillons de n'importer que les modèles de ces fichiers. Souhaitez-vous continuer ?"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/OpenFilesIncludingProjectsDialog.qml:99
+msgctxt "@action:button"
+msgid "Import all as models"
+msgstr "Importer tout comme modèles"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:15
+msgctxt "@title:window"
+msgid "Save Project"
+msgstr "Enregistrer le projet"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:149
+msgctxt "@action:label"
+msgid "Build plate"
+msgstr "Plateau"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:183
+msgctxt "@action:label"
+msgid "Extruder %1"
+msgstr "Extrudeuse %1"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:198
+msgctxt "@action:label"
+msgid "%1 & material"
+msgstr "%1 & matériau"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:200
+msgctxt "@action:label"
+msgid "Material"
+msgstr "Matériau"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:272
+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:291
+msgctxt "@action:button"
+msgid "Save"
+msgstr "Enregistrer"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AskOpenAsProjectOrModelsDialog.qml:20
msgctxt "@title:window"
msgid "Open project file"
msgstr "Ouvrir un fichier de projet"
-#: /home/ruben/Projects/Cura/resources/qml/AskOpenAsProjectOrModelsDialog.qml:93
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AskOpenAsProjectOrModelsDialog.qml:93
msgctxt "@text:window"
msgid "This is a Cura project file. Would you like to open it as a project or import the models from it?"
msgstr "Ceci est un fichier de projet Cura. Souhaitez-vous l'ouvrir comme projet ou en importer les modèles ?"
-#: /home/ruben/Projects/Cura/resources/qml/AskOpenAsProjectOrModelsDialog.qml:103
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AskOpenAsProjectOrModelsDialog.qml:103
msgctxt "@text:window"
msgid "Remember my choice"
msgstr "Se souvenir de mon choix"
-#: /home/ruben/Projects/Cura/resources/qml/AskOpenAsProjectOrModelsDialog.qml:122
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AskOpenAsProjectOrModelsDialog.qml:122
msgctxt "@action:button"
msgid "Open as project"
msgstr "Ouvrir comme projet"
-#: /home/ruben/Projects/Cura/resources/qml/AskOpenAsProjectOrModelsDialog.qml:131
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AskOpenAsProjectOrModelsDialog.qml:131
msgctxt "@action:button"
msgid "Import models"
msgstr "Importer les modèles"
-#: /home/ruben/Projects/Cura/resources/qml/EngineLog.qml:15
-msgctxt "@title:window"
-msgid "Engine Log"
-msgstr "Journal du moteur"
-
-#: /home/ruben/Projects/Cura/resources/qml/SidebarHeader.qml:70
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/DropDownWidget.qml:93
msgctxt "@label"
-msgid "Printer type"
-msgstr "Type d'imprimante"
+msgid "Empty"
+msgstr "Vide"
-#: /home/ruben/Projects/Cura/resources/qml/SidebarHeader.qml:376
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddNetworkOrLocalPrinterContent.qml:24
msgctxt "@label"
-msgid "Material"
-msgstr "Matériau"
+msgid "Add a printer"
+msgstr "Ajouter une imprimante"
-#: /home/ruben/Projects/Cura/resources/qml/SidebarHeader.qml:543
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddNetworkOrLocalPrinterContent.qml:39
msgctxt "@label"
-msgid "Use glue with this material combination"
-msgstr "Utiliser de la colle avec cette combinaison de matériaux"
+msgid "Add a networked printer"
+msgstr "Ajouter une imprimante en réseau"
-#: /home/ruben/Projects/Cura/resources/qml/SidebarHeader.qml:575
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddNetworkOrLocalPrinterContent.qml:81
msgctxt "@label"
-msgid "Check compatibility"
-msgstr "Vérifier la compatibilité"
+msgid "Add a non-networked printer"
+msgstr "Ajouter une imprimante hors réseau"
-#: /home/ruben/Projects/Cura/resources/qml/SidebarHeader.qml:593
-msgctxt "@tooltip"
-msgid "Click to check the material compatibility on Ultimaker.com."
-msgstr "Cliquez ici pour vérifier la compatibilité des matériaux sur Ultimaker.com."
+#: /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/ObjectsList.qml:211
-msgctxt "@option:check"
-msgid "See only current build plate"
-msgstr "Afficher uniquement le plateau actuel"
+#: /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/ObjectsList.qml:227
-msgctxt "@action:button"
-msgid "Arrange to all build plates"
-msgstr "Réorganiser sur tous les plateaux"
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddPrinterByIpContent.qml:158
+msgctxt "@button"
+msgid "Add"
+msgstr "Ajouter"
-#: /home/ruben/Projects/Cura/resources/qml/ObjectsList.qml:247
-msgctxt "@action:button"
-msgid "Arrange current build plate"
-msgstr "Réorganiser le plateau actuel"
+#: /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:207
+msgctxt "@label"
+msgid "Printer name"
+msgstr "Nom de l'imprimante"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddLocalPrinterScrollView.qml:220
+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"
#: MachineSettingsAction/plugin.json
msgctxt "description"
@@ -4547,26 +5129,36 @@ msgctxt "name"
msgid "God Mode"
msgstr "Mode God"
-#: ChangeLogPlugin/plugin.json
+#: FirmwareUpdater/plugin.json
msgctxt "description"
-msgid "Shows changes since latest checked version."
-msgstr "Affiche les changements depuis la dernière version."
+msgid "Provides a machine actions for updating firmware."
+msgstr "Fournit à une machine des actions permettant la mise à jour du firmware."
-#: ChangeLogPlugin/plugin.json
+#: FirmwareUpdater/plugin.json
msgctxt "name"
-msgid "Changelog"
-msgstr "Récapitulatif des changements"
+msgid "Firmware Updater"
+msgstr "Programme de mise à jour du firmware"
#: ProfileFlattener/plugin.json
msgctxt "description"
-msgid "Create a flattend quality changes profile."
+msgid "Create a flattened quality changes profile."
msgstr "Créer un profil de changements de qualité aplati."
#: ProfileFlattener/plugin.json
msgctxt "name"
-msgid "Profile flatener"
+msgid "Profile Flattener"
msgstr "Aplatisseur de profil"
+#: 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."
@@ -4577,26 +5169,6 @@ msgctxt "name"
msgid "USB printing"
msgstr "Impression par USB"
-#: UserAgreement/plugin.json
-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."
-
-#: UserAgreement/plugin.json
-msgctxt "name"
-msgid "UserAgreement"
-msgstr "UserAgreement"
-
-#: X3GWriter/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)."
-
-#: X3GWriter/plugin.json
-msgctxt "name"
-msgid "X3GWriter"
-msgstr "X3GWriter"
-
#: GCodeGzWriter/plugin.json
msgctxt "description"
msgid "Writes g-code to a compressed archive."
@@ -4647,6 +5219,16 @@ msgctxt "name"
msgid "UM3 Network Connection"
msgstr "Connexion au réseau UM3"
+#: SettingsGuide/plugin.json
+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."
+
+#: SettingsGuide/plugin.json
+msgctxt "name"
+msgid "Settings Guide"
+msgstr "Guide des paramètres"
+
#: MonitorStage/plugin.json
msgctxt "description"
msgid "Provides a monitor stage in Cura."
@@ -4707,6 +5289,16 @@ 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."
@@ -4787,6 +5379,16 @@ 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."
@@ -4797,6 +5399,16 @@ 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."
@@ -4807,6 +5419,16 @@ 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."
@@ -4897,6 +5519,16 @@ 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."
@@ -4927,6 +5559,16 @@ 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.)."
@@ -4947,6 +5589,733 @@ msgctxt "name"
msgid "Cura Profile Reader"
msgstr "Lecteur de profil Cura"
+#~ 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"
+
+#~ msgctxt "@info:status"
+#~ msgid "Nothing to slice because none of the models fit the build volume. Please scale or rotate models to fit."
+#~ msgstr "Rien à couper car aucun des modèles ne convient au volume d'impression. Mettez à l'échelle ou faites pivoter les modèles pour les faire correspondre."
+
+#~ msgctxt "@info:status"
+#~ msgid "The selected material is incompatible with the selected machine or configuration."
+#~ msgstr "Le matériau sélectionné est incompatible avec la machine ou la configuration sélectionnée."
+
+#~ msgctxt "@info:title"
+#~ msgid "Incompatible Material"
+#~ msgstr "Matériau incompatible"
+
+#~ msgctxt "@info:status Don't translate the XML tags or !"
+#~ msgid "Failed to import profile from {0}: {1}"
+#~ msgstr "Échec de l'importation du profil depuis le fichier {0} : {1}"
+
+#~ msgctxt "@title"
+#~ msgid "Toolbox"
+#~ msgstr "Boîte à outils"
+
+#~ msgctxt "@label"
+#~ msgid "Not available"
+#~ msgstr "Non disponible"
+
+#~ msgctxt "@label"
+#~ msgid "Unreachable"
+#~ msgstr "Injoignable"
+
+#~ msgctxt "@label"
+#~ msgid "Available"
+#~ msgstr "Disponible"
+
+#~ msgctxt "@label:status"
+#~ msgid "Preparing"
+#~ msgstr "Préparation"
+
+#~ msgctxt "@label:status"
+#~ msgid "Pausing"
+#~ msgstr "Mise en pause"
+
+#~ msgctxt "@label:status"
+#~ msgid "Resuming"
+#~ msgstr "Reprise"
+
+#~ msgctxt "@label"
+#~ msgid "Waiting for: Unavailable printer"
+#~ msgstr "En attente : imprimante non disponible"
+
+#~ msgctxt "@label"
+#~ msgid "Waiting for: First available"
+#~ msgstr "En attente : première imprimante disponible"
+
+#~ msgctxt "@label"
+#~ msgid "Waiting for: "
+#~ msgstr "En attente : "
+
+#~ msgctxt "@label"
+#~ msgid "Configuration change"
+#~ msgstr "Modification des configurations"
+
+#~ msgctxt "@label"
+#~ msgid "The assigned printer, %1, requires the following configuration change(s):"
+#~ msgstr "L'imprimante assignée, %1, nécessite d'apporter la ou les modifications suivantes à la configuration :"
+
+#~ msgctxt "@label"
+#~ msgid "Override"
+#~ msgstr "Remplacer"
+
+#~ msgctxt "@label"
+#~ msgid "Starting a print job with an incompatible configuration could damage your 3D printer. Are you sure you want to override the configuration and print %1?"
+#~ msgstr "Le fait de démarrer un travail d'impression avec une configuration incompatible peut endommager votre imprimante 3D. Êtes-vous sûr de vouloir remplacer la configuration et imprimer %1 ?"
+
+#~ msgctxt "@window:title"
+#~ msgid "Override configuration configuration and start print"
+#~ msgstr "Remplacer la configuration et lancer l'impression"
+
+#~ msgctxt "@label link to connect manager"
+#~ msgid "Manage queue"
+#~ msgstr "Gérer la file d'attente"
+
+#~ msgctxt "@label"
+#~ msgid "Printing"
+#~ msgstr "Impression"
+
+#~ msgctxt "@label link to connect manager"
+#~ msgid "Manage printers"
+#~ msgstr "Gérer les imprimantes"
+
+#~ msgctxt "@action:button"
+#~ msgid "Activate Configuration"
+#~ msgstr "Activer la configuration"
+
+#~ msgctxt "@info:tooltip"
+#~ msgid "Load the configuration of the printer into Cura"
+#~ msgstr "Charger la configuration de l'imprimante dans Cura"
+
+#~ msgctxt "@label"
+#~ msgid "Show Travels"
+#~ msgstr "Afficher les déplacements"
+
+#~ msgctxt "@label"
+#~ msgid "Show Helpers"
+#~ msgstr "Afficher les aides"
+
+#~ msgctxt "@label"
+#~ msgid "Show Shell"
+#~ msgstr "Afficher la coque"
+
+#~ msgctxt "@label"
+#~ msgid "Show Infill"
+#~ msgstr "Afficher le remplissage"
+
+#~ msgctxt "@text:window"
+#~ msgid "I don't want to send these data"
+#~ msgstr "Je ne veux pas envoyer ces données"
+
+#~ msgctxt "@text:window"
+#~ msgid "Allow sending these 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 "Printer type:"
+#~ msgstr "Type d'imprimante :"
+
+#~ msgctxt "@label"
+#~ msgid "Connection:"
+#~ msgstr "Connexion :"
+
+#~ msgctxt "@label"
+#~ msgid "State:"
+#~ msgstr "État :"
+
+#~ msgctxt "@label:MonitorStatus"
+#~ msgid "Waiting for a printjob"
+#~ msgstr "En attente d'une tâche d'impression"
+
+#~ msgctxt "@label:MonitorStatus"
+#~ msgid "Waiting for someone to clear the build plate"
+#~ msgstr "En attente du dégagement du plateau"
+
+#~ msgctxt "@label:MonitorStatus"
+#~ msgid "Aborting print..."
+#~ msgstr "Abandon de l'impression..."
+
+#~ msgctxt "@label"
+#~ msgid "Protected profiles"
+#~ msgstr "Profils protégés"
+
+#~ msgctxt "@label"
+#~ msgid "Printer Name:"
+#~ msgstr "Nom de l'imprimante :"
+
+#~ msgctxt "@label"
+#~ msgid "Profile:"
+#~ msgstr "Profil :"
+
+#~ msgctxt "@label:textbox"
+#~ msgid "Search..."
+#~ msgstr "Rechercher..."
+
+#~ msgctxt "@action:inmenu"
+#~ msgid "Collapse All"
+#~ msgstr "Réduire tout"
+
+#~ msgctxt "@action:inmenu"
+#~ msgid "Expand All"
+#~ msgstr "Développer tout"
+
+#~ msgctxt "@label:header configurations"
+#~ msgid "Available configurations"
+#~ msgstr "Configurations disponibles"
+
+#~ msgctxt "@label:extruder label"
+#~ msgid "Extruder"
+#~ msgstr "Extrudeuse"
+
+#~ msgctxt "@label:extruder label"
+#~ msgid "Yes"
+#~ msgstr "Oui"
+
+#~ msgctxt "@label:extruder label"
+#~ msgid "No"
+#~ msgstr "Non"
+
+#~ msgctxt "@label:listbox"
+#~ msgid "Print Setup"
+#~ msgstr "Configuration de l'impression"
+
+#~ msgctxt "@label:listbox"
+#~ msgid ""
+#~ "Print Setup disabled\n"
+#~ "G-code files cannot be modified"
+#~ msgstr ""
+#~ "Configuration de l'impression désactivée\n"
+#~ "Les fichiers G-Code ne peuvent pas être modifiés"
+
+#~ msgctxt "@label Hours and minutes"
+#~ msgid "00h 00min"
+#~ msgstr "00h 00min"
+
+#~ msgctxt "@tooltip"
+#~ msgid "Time specification"
+#~ msgstr "Spécification de temps"
+
+#~ msgctxt "@label"
+#~ msgid "Cost specification"
+#~ msgstr "Spécification de coût"
+
+#~ msgctxt "@label"
+#~ msgid "Total:"
+#~ msgstr "Total :"
+
+#~ msgctxt "@tooltip"
+#~ msgid "Recommended Print Setup
Print with the recommended settings for the selected printer, material and quality."
+#~ msgstr "Configuration de l'impression recommandée
Imprimer avec les paramètres recommandés pour l'imprimante, le matériau et la qualité sélectionnés."
+
+#~ msgctxt "@tooltip"
+#~ msgid "Custom Print Setup
Print with finegrained control over every last bit of the slicing process."
+#~ msgstr "Configuration de l'impression personnalisée
Imprimer avec un contrôle fin de chaque élément du processus de découpe."
+
+#~ msgctxt "@action:inmenu menubar:help"
+#~ msgid "Show Engine &Log..."
+#~ msgstr "Afficher le &journal du moteur..."
+
+#~ msgctxt "@action:menu"
+#~ msgid "Browse packages..."
+#~ msgstr "Parcourir les paquets..."
+
+#~ msgctxt "@action:inmenu menubar:view"
+#~ msgid "Expand/Collapse Sidebar"
+#~ msgstr "Déplier / replier la barre latérale"
+
+#~ msgctxt "@label:PrintjobStatus"
+#~ msgid "Please load a 3D model"
+#~ msgstr "Veuillez charger un modèle 3D"
+
+#~ msgctxt "@label:PrintjobStatus"
+#~ msgid "Ready to slice"
+#~ msgstr "Prêt à découper"
+
+#~ msgctxt "@label:PrintjobStatus %1 is target operation"
+#~ msgid "Ready to %1"
+#~ msgstr "Prêt à %1"
+
+#~ msgctxt "@label:PrintjobStatus"
+#~ msgid "Slicing unavailable"
+#~ msgstr "Découpe indisponible"
+
+#~ msgctxt "@info:tooltip"
+#~ msgid "Slice current printjob"
+#~ msgstr "Découper la tâche d'impression en cours"
+
+#~ msgctxt "@info:tooltip"
+#~ msgid "Cancel slicing process"
+#~ msgstr "Annuler le processus de découpe"
+
+#~ msgctxt "@label:Printjob"
+#~ msgid "Prepare"
+#~ msgstr "Préparer"
+
+#~ msgctxt "@label:Printjob"
+#~ msgid "Cancel"
+#~ msgstr "Annuler"
+
+#~ msgctxt "@info:tooltip"
+#~ msgid "Select the active output device"
+#~ msgstr "Sélectionner le périphérique de sortie actif"
+
+#~ msgctxt "@title:menu"
+#~ msgid "&View"
+#~ msgstr "&Visualisation"
+
+#~ msgctxt "@title:menu"
+#~ msgid "&Settings"
+#~ msgstr "&Paramètres"
+
+#~ msgctxt "@title:menu menubar:toplevel"
+#~ msgid "&Toolbox"
+#~ msgstr "&Boîte à outils"
+
+#~ msgctxt "@action:button"
+#~ msgid "Open File"
+#~ msgstr "Ouvrir un fichier"
+
+#~ msgctxt "@tooltip"
+#~ msgid "This quality profile is not available for you 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"
+#~ msgid "Print Speed"
+#~ msgstr "Vitesse d’impression"
+
+#~ msgctxt "@label"
+#~ msgid "Slower"
+#~ msgstr "Ralentir"
+
+#~ msgctxt "@label"
+#~ msgid "Faster"
+#~ msgstr "Accélérer"
+
+#~ msgctxt "@label"
+#~ msgid "Enable gradual"
+#~ msgstr "Permettre le remplissage graduel"
+
+#~ msgctxt "@label"
+#~ msgid "Generate Support"
+#~ msgstr "Générer les supports"
+
+#~ msgctxt "@label"
+#~ msgid "Build Plate Adhesion"
+#~ msgstr "Adhérence au plateau"
+
+#~ msgctxt "@label"
+#~ msgid "Need help improving your prints? Read the Ultimaker Troubleshooting Guides"
+#~ msgstr "Besoin d'aide pour améliorer vos impressions ? Lisez les Guides de dépannage Ultimaker"
+
+#~ msgctxt "@title:window"
+#~ msgid "Engine Log"
+#~ msgstr "Journal du moteur"
+
+#~ msgctxt "@label"
+#~ msgid "Printer type"
+#~ msgstr "Type d'imprimante"
+
+#~ msgctxt "@label"
+#~ msgid "Use glue with this material combination"
+#~ msgstr "Utiliser de la colle avec cette combinaison de matériaux"
+
+#~ msgctxt "@label"
+#~ msgid "Check compatibility"
+#~ msgstr "Vérifier la compatibilité"
+
+#~ msgctxt "@tooltip"
+#~ 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 "Shows changes since latest checked version."
+#~ msgstr "Affiche les changements depuis la dernière version."
+
+#~ msgctxt "name"
+#~ msgid "Changelog"
+#~ msgstr "Récapitulatif des changements"
+
+#~ msgctxt "description"
+#~ msgid "Create a flattend quality changes profile."
+#~ msgstr "Créer un profil de changements de qualité aplati."
+
+#~ msgctxt "name"
+#~ msgid "Profile flatener"
+#~ msgstr "Aplatisseur de profil"
+
+#~ 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."
+
+#~ msgctxt "name"
+#~ msgid "UserAgreement"
+#~ msgstr "UserAgreement"
+
+#~ msgctxt "@warning:status"
+#~ msgid "Please generate G-code before saving."
+#~ msgstr "Veuillez générer le G-Code avant d'enregistrer."
+
+#~ msgctxt "@action"
+#~ msgid "Upgrade Firmware"
+#~ msgstr "Mise à niveau du firmware"
+
+#~ msgctxt "@label unknown material"
+#~ msgid "Unknown"
+#~ msgstr "Inconnu"
+
+#~ msgctxt "@info:status Don't translate the XML tags or !"
+#~ msgid "No custom profile to import in file {0}"
+#~ msgstr "Aucun profil personnalisé à importer dans le fichier {0}"
+
+#~ msgctxt "@info:status Don't translate the XML tags or !"
+#~ msgid "This profile {0} contains incorrect data, could not import it."
+#~ msgstr "Le profil {0} contient des données incorrectes ; échec de l'importation."
+
+#~ msgctxt "@info:status Don't translate the XML tags or !"
+#~ 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 "@title:window"
+#~ msgid "Confirm uninstall "
+#~ msgstr "Confirmer la désinstallation "
+
+#~ msgctxt "@label Print estimates: m for meters, g for grams, %4 is currency and %3 is print cost"
+#~ msgid "%1m / ~ %2g / ~ %4 %3"
+#~ msgstr "%1m / ~ %2g / ~ %4 %3"
+
+#~ msgctxt "@label Print estimates: m for meters, g for grams"
+#~ msgid "%1m / ~ %2g"
+#~ msgstr "%1m / ~ %2g"
+
+#~ msgctxt "@title"
+#~ msgid "Upgrade Firmware"
+#~ msgstr "Mise à niveau du firmware"
+
#~ msgctxt "@action:button"
#~ msgid "Print with Doodle3D WiFi-Box"
#~ msgstr "Imprimer avec Doodle3D WiFi-Box"
@@ -5039,10 +6408,6 @@ msgstr "Lecteur de profil Cura"
#~ msgid "Lost connection with the printer"
#~ msgstr "Connexion avec l'imprimante perdue"
-#~ msgctxt "@label:status"
-#~ msgid "Unavailable"
-#~ msgstr "Indisponible"
-
#~ msgctxt "@label:status"
#~ msgid "Unknown"
#~ msgstr "Inconnu"
diff --git a/resources/i18n/fr_FR/fdmextruder.def.json.po b/resources/i18n/fr_FR/fdmextruder.def.json.po
index b2b54fbced..da14c42d89 100644
--- a/resources/i18n/fr_FR/fdmextruder.def.json.po
+++ b/resources/i18n/fr_FR/fdmextruder.def.json.po
@@ -1,14 +1,14 @@
# Cura
-# Copyright (C) 2018 Ultimaker
+# Copyright (C) 2019 Ultimaker B.V.
# This file is distributed under the same license as the Cura package.
-# Ruben Dulek , 2018.
+# Ruben Dulek , 2019.
#
msgid ""
msgstr ""
-"Project-Id-Version: Cura 3.5\n"
-"Report-Msgid-Bugs-To: r.dulek@ultimaker.com"
-"POT-Creation-Date: 2018-09-19 17:07+0000\n"
-"PO-Revision-Date: 2018-09-28 14:25+0100\n"
+"Project-Id-Version: Cura 4.2\n"
+"Report-Msgid-Bugs-To: r.dulek@ultimaker.com\n"
+"POT-Creation-Date: 2019-07-16 14:38+0000\n"
+"PO-Revision-Date: 2019-03-13 14:00+0200\n"
"Last-Translator: Bothof \n"
"Language-Team: French\n"
"Language: fr_FR\n"
@@ -83,8 +83,8 @@ msgstr "Extrudeuse G-Code de démarrage"
#: fdmextruder.def.json
msgctxt "machine_extruder_start_code description"
-msgid "Start g-code to execute whenever turning the extruder on."
-msgstr "G-Code de démarrage à exécuter à chaque mise en marche de l'extrudeuse."
+msgid "Start g-code to execute when switching to this extruder."
+msgstr "Démarrer le G-Code à exécuter lors du passage à cette extrudeuse."
#: fdmextruder.def.json
msgctxt "machine_extruder_start_pos_abs label"
@@ -123,8 +123,8 @@ msgstr "Extrudeuse G-Code de fin"
#: fdmextruder.def.json
msgctxt "machine_extruder_end_code description"
-msgid "End g-code to execute whenever turning the extruder off."
-msgstr "G-Code de fin à exécuter à chaque arrêt de l'extrudeuse."
+msgid "End g-code to execute when switching away from this extruder."
+msgstr "Fin du G-Code à exécuter lors de l'abandon de l'extrudeuse."
#: fdmextruder.def.json
msgctxt "machine_extruder_end_pos_abs label"
@@ -166,6 +166,16 @@ msgctxt "extruder_prime_pos_z description"
msgid "The Z coordinate of the position where the nozzle primes at the start of printing."
msgstr "Les coordonnées Z de la position à laquelle la buse s'amorce au début de l'impression."
+#: fdmextruder.def.json
+msgctxt "machine_extruder_cooling_fan_number label"
+msgid "Extruder Print Cooling Fan"
+msgstr "Ventilateur de refroidissement d'impression de l'extrudeuse"
+
+#: fdmextruder.def.json
+msgctxt "machine_extruder_cooling_fan_number description"
+msgid "The number of the print cooling fan associated with this extruder. Only change this from the default value of 0 when you have a different print cooling fan for each extruder."
+msgstr "Numéro du ventilateur de refroidissement d'impression associé à cette extrudeuse. Ne modifiez cette valeur par rapport à la valeur par défaut 0 que si vous utilisez un ventilateur de refroidissement d'impression différent pour chaque extrudeuse."
+
#: fdmextruder.def.json
msgctxt "platform_adhesion label"
msgid "Build Plate Adhesion"
@@ -215,3 +225,11 @@ msgstr "Diamètre"
msgctxt "material_diameter description"
msgid "Adjusts the diameter of the filament used. Match this value with the diameter of the used filament."
msgstr "Ajuste le diamètre du filament utilisé. Faites correspondre cette valeur au diamètre du filament utilisé."
+
+#~ msgctxt "machine_extruder_start_code description"
+#~ msgid "Start g-code to execute whenever turning the extruder on."
+#~ msgstr "G-Code de démarrage à exécuter à chaque mise en marche de l'extrudeuse."
+
+#~ msgctxt "machine_extruder_end_code description"
+#~ msgid "End g-code to execute whenever turning the extruder off."
+#~ msgstr "G-Code de fin à exécuter à chaque arrêt de l'extrudeuse."
diff --git a/resources/i18n/fr_FR/fdmprinter.def.json.po b/resources/i18n/fr_FR/fdmprinter.def.json.po
index b76aa532cb..85b73e6bce 100644
--- a/resources/i18n/fr_FR/fdmprinter.def.json.po
+++ b/resources/i18n/fr_FR/fdmprinter.def.json.po
@@ -1,21 +1,21 @@
# Cura
-# Copyright (C) 2018 Ultimaker
+# Copyright (C) 2019 Ultimaker B.V.
# This file is distributed under the same license as the Cura package.
-# Ruben Dulek , 2018.
+# Ruben Dulek , 2019.
#
msgid ""
msgstr ""
-"Project-Id-Version: Cura 3.5\n"
-"Report-Msgid-Bugs-To: r.dulek@ultimaker.comPOT-Creation-Date: 2018-09-19 17:07+0000\n"
-"PO-Revision-Date: 2018-09-28 15:00+0200\n"
-"Last-Translator: Bothof \n"
-"Language-Team: French\n"
+"Project-Id-Version: Cura 4.2\n"
+"Report-Msgid-Bugs-To: r.dulek@ultimaker.com\n"
+"POT-Creation-Date: 2019-07-16 14:38+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"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 2.0.6\n"
-"POT-Creation-Date: \n"
#: fdmprinter.def.json
msgctxt "machine_settings label"
@@ -237,7 +237,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 +247,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 +257,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 +267,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 +277,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 +307,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 +317,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 +337,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 +402,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 +422,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 +432,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 +442,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 +472,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
@@ -1077,7 +1077,7 @@ msgstr "Relier les polygones supérieurs / inférieurs"
#: fdmprinter.def.json
msgctxt "connect_skin_polygons description"
-msgid "Connect top/bottom skin paths where they run next to each other. For the concentric pattern enabling this setting greatly reduces the travel time, but because the connections can happend midway over infill this feature can reduce the top surface quality."
+msgid "Connect top/bottom skin paths where they run next to each other. For the concentric pattern enabling this setting greatly reduces the travel time, but because the connections can happen midway over infill this feature can reduce the top surface quality."
msgstr "Relier les voies de couche extérieure supérieures / inférieures lorsqu'elles sont côte à côte. Pour le motif concentrique, ce paramètre réduit considérablement le temps de parcours, mais comme les liens peuvent se trouver à mi-chemin sur le remplissage, cette fonctionnalité peut réduire la qualité de la surface supérieure."
#: fdmprinter.def.json
@@ -1297,8 +1297,11 @@ 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 +1323,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 +1340,15 @@ 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"
@@ -1497,8 +1507,8 @@ msgstr "Motif de remplissage"
#: fdmprinter.def.json
msgctxt "infill_pattern description"
-msgid "The pattern of the infill material of the print. The line and zig zag infill swap direction on alternate layers, reducing material cost. The grid, triangle, tri-hexagon, cubic, octet, quarter cubic, cross and concentric patterns are fully printed every layer. Cubic, quarter cubic and octet infill change with every layer to provide a more equal distribution of strength over each direction."
-msgstr "Motif du matériau de remplissage de l'impression. La ligne et le remplissage en zigzag changent de sens à chaque alternance de couche, réduisant ainsi les coûts matériels. Les motifs en grille, en triangle, trihexagonaux, cubiques, octaédriques, quart cubiques et concentriques sont entièrement imprimés sur chaque couche. Les remplissages cubique, quart cubique et octaédrique changent à chaque couche afin d'offrir une répartition plus égale de la solidité dans chaque direction."
+msgid "The pattern of the infill material of the print. The line and zig zag infill swap direction on alternate layers, reducing material cost. The grid, triangle, tri-hexagon, cubic, octet, quarter cubic, cross and concentric patterns are fully printed every layer. Gyroid, cubic, quarter cubic and octet infill change with every layer to provide a more equal distribution of strength over each direction."
+msgstr "Motif du matériau de remplissage de l'impression. La ligne et le remplissage en zigzag changent de sens à chaque alternance de couche, réduisant ainsi les coûts matériels. Les motifs en grille, en triangle, trihexagonaux, cubiques, octaédriques, quart cubiques et concentriques sont entièrement imprimés sur chaque couche. Les remplissages gyroïde, cubique, quart cubique et octaédrique changent à chaque couche afin d'offrir une répartition plus égale de la solidité dans chaque direction."
#: fdmprinter.def.json
msgctxt "infill_pattern option grid"
@@ -1560,6 +1570,11 @@ msgctxt "infill_pattern option cross_3d"
msgid "Cross 3D"
msgstr "Entrecroisé 3D"
+#: fdmprinter.def.json
+msgctxt "infill_pattern option gyroid"
+msgid "Gyroid"
+msgstr "Gyroïde"
+
#: fdmprinter.def.json
msgctxt "zig_zaggify_infill label"
msgid "Connect Infill Lines"
@@ -1671,8 +1686,8 @@ msgstr "Pourcentage de chevauchement de la couche extérieure"
#: fdmprinter.def.json
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."
+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"
@@ -1681,8 +1696,8 @@ msgstr "Chevauchement de la couche extérieure"
#: fdmprinter.def.json
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 "Le degré de chevauchement entre la couche extérieure et les parois. Un léger chevauchement permet de lier fermement les parois à la couche externe."
+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_wipe_dist label"
@@ -1864,6 +1879,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"
@@ -1974,6 +1999,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"
@@ -1984,6 +2089,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"
@@ -2101,8 +2326,9 @@ 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"
@@ -2121,8 +2347,8 @@ msgstr "Distance de rétraction de changement de buse"
#: fdmprinter.def.json
msgctxt "switch_extruder_retraction_amount description"
-msgid "The amount of retraction: Set at 0 for no retraction at all. This should generally be the same as the length of the heat zone."
-msgstr "La quantité de rétraction : définir à 0 pour aucune rétraction. Cette valeur doit généralement être égale à la longueur de la zone chauffée."
+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 "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"
@@ -2154,6 +2380,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"
@@ -2345,14 +2581,15 @@ 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"
@@ -2781,8 +3018,8 @@ 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 and also to only comb within the infill. Note that the 'Within Infill' option behaves exactly like the 'Not in Skin' option in earlier Cura releases."
-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 extérieure supérieure / inférieure et aussi de n'effectuer les détours que dans le remplissage. Notez que l'option « À l'intérieur du remplissage » se comporte exactement comme l'option « Pas dans la couche extérieure » dans les versions précédentes de Cura."
+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 "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"
@@ -2924,6 +3161,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"
@@ -3194,6 +3441,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"
@@ -3264,6 +3516,36 @@ 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."
+#: fdmprinter.def.json
+msgctxt "support_brim_enable label"
+msgid "Enable Support Brim"
+msgstr "Activer la bordure du support"
+
+#: fdmprinter.def.json
+msgctxt "support_brim_enable description"
+msgid "Generate a brim within the support infill regions of the first layer. This brim is printed underneath the support, not around it. Enabling this setting increases the adhesion of support to the build plate."
+msgstr "Générer un bord à l'intérieur des zones de remplissage du support de la première couche. Cette bordure est imprimée sous le support et non autour de celui-ci, ce qui augmente l'adhérence du support au plateau."
+
+#: fdmprinter.def.json
+msgctxt "support_brim_width label"
+msgid "Support Brim Width"
+msgstr "Largeur de la bordure du support"
+
+#: fdmprinter.def.json
+msgctxt "support_brim_width description"
+msgid "The width of the brim to print underneath the support. A larger brim enhances adhesion to the build plate, at the cost of some extra material."
+msgstr "Largeur de la bordure à imprimer sous le support. Une plus grande bordure améliore l'adhérence au plateau, mais demande un peu de matériau supplémentaire."
+
+#: fdmprinter.def.json
+msgctxt "support_brim_line_count label"
+msgid "Support Brim Line Count"
+msgstr "Nombre de lignes de la bordure du support"
+
+#: fdmprinter.def.json
+msgctxt "support_brim_line_count description"
+msgid "The number of lines used for the support brim. More brim lines enhance adhesion to the build plate, at the cost of some extra material."
+msgstr "Nombre de lignes utilisées pour la bordure du support. L'augmentation du nombre de lignes de bordure améliore l'adhérence au plateau, mais demande un peu de matériau supplémentaire."
+
#: fdmprinter.def.json
msgctxt "support_z_distance label"
msgid "Support Z Distance"
@@ -3361,8 +3643,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"
@@ -3404,6 +3686,16 @@ msgctxt "gradual_support_infill_step_height description"
msgid "The height of support infill of a given density before switching to half the density."
msgstr "La hauteur de remplissage de support d'une densité donnée avant de passer à la moitié de la densité."
+#: fdmprinter.def.json
+msgctxt "minimum_support_area label"
+msgid "Minimum Support Area"
+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 "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"
msgid "Enable Support Interface"
@@ -3629,6 +3921,66 @@ msgctxt "support_bottom_pattern option zigzag"
msgid "Zig Zag"
msgstr "Zig Zag"
+#: fdmprinter.def.json
+msgctxt "minimum_interface_area label"
+msgid "Minimum Support Interface Area"
+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 "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."
+
+#: fdmprinter.def.json
+msgctxt "minimum_roof_area label"
+msgid "Minimum Support Roof Area"
+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 "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."
+
+#: fdmprinter.def.json
+msgctxt "minimum_bottom_area label"
+msgid "Minimum Support Floor Area"
+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 "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."
+
+#: fdmprinter.def.json
+msgctxt "support_interface_offset label"
+msgid "Support Interface Horizontal Expansion"
+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 "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 "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 "Quantité de décalage appliqué aux plafonds du support."
+
+#: fdmprinter.def.json
+msgctxt "support_bottom_offset label"
+msgid "Support Floor Horizontal Expansion"
+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 "Quantité de décalage appliqué aux bas du support."
+
#: fdmprinter.def.json
msgctxt "support_fan_enable label"
msgid "Fan Speed Override"
@@ -3670,14 +4022,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"
@@ -3833,6 +4185,16 @@ msgctxt "brim_line_count description"
msgid "The number of lines used for a brim. More brim lines enhance adhesion to the build plate, but also reduces the effective print area."
msgstr "Le nombre de lignes utilisées pour une bordure. Un plus grand nombre de lignes de bordure renforce l'adhérence au plateau mais réduit également la zone d'impression réelle."
+#: fdmprinter.def.json
+msgctxt "brim_replaces_support label"
+msgid "Brim Replaces Support"
+msgstr "La bordure remplace le support"
+
+#: fdmprinter.def.json
+msgctxt "brim_replaces_support description"
+msgid "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."
+msgstr "Appliquer la bordure à imprimer autour du modèle même si cet espace aurait autrement dû être occupé par le support, en remplaçant certaines régions de la première couche de support par des régions de la bordure."
+
#: fdmprinter.def.json
msgctxt "brim_outside_only label"
msgid "Brim Only on Outside"
@@ -4163,16 +4525,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"
@@ -4213,16 +4565,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"
@@ -4233,6 +4575,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"
@@ -4515,8 +4867,9 @@ 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"
@@ -4748,6 +5101,16 @@ 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."
+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."
+
#: fdmprinter.def.json
msgctxt "support_skip_some_zags label"
msgid "Break Up Support In Chunks"
@@ -5005,8 +5368,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"
@@ -5349,7 +5712,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
@@ -5359,7 +5722,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
@@ -5369,7 +5732,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
@@ -5379,7 +5742,7 @@ 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"
+msgid "Adaptive Layers Threshold"
msgstr "Limite des couches adaptatives"
#: fdmprinter.def.json
@@ -5597,6 +5960,156 @@ 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 "command_line_settings label"
msgid "Command Line Settings"
@@ -5657,6 +6170,162 @@ 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 "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."
+
+#~ 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 "Le degré de chevauchement entre la couche extérieure et les parois. Un léger chevauchement permet de lier fermement les parois à la couche externe."
+
+#~ msgctxt "switch_extruder_retraction_amount description"
+#~ msgid "The amount of retraction: Set at 0 for no retraction at all. This should generally be the same as the length of the heat zone."
+#~ msgstr "La quantité de rétraction : définir à 0 pour aucune rétraction. Cette valeur doit généralement être égale à la longueur de la zone chauffée."
+
+#~ 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 and also to only comb within the infill. Note that the 'Within Infill' option behaves exactly like the 'Not in Skin' option in earlier Cura releases."
+#~ 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 extérieure supérieure / inférieure et aussi de n'effectuer les détours que dans le remplissage. Notez que l'option « À l'intérieur du remplissage » se comporte exactement comme l'option « Pas dans la couche extérieure » dans les versions précédentes de Cura."
+
+#~ msgctxt "connect_skin_polygons description"
+#~ msgid "Connect top/bottom skin paths where they run next to each other. For the concentric pattern enabling this setting greatly reduces the travel time, but because the connections can happend midway over infill this feature can reduce the top surface quality."
+#~ msgstr "Relier les voies de couche extérieure supérieures / inférieures lorsqu'elles sont côte à côte. Pour le motif concentrique, ce paramètre réduit considérablement le temps de parcours, mais comme les liens peuvent se trouver à mi-chemin sur le remplissage, cette fonctionnalité peut réduire la qualité de la surface supérieure."
+
+#~ msgctxt "infill_pattern description"
+#~ msgid "The pattern of the infill material of the print. The line and zig zag infill swap direction on alternate layers, reducing material cost. The grid, triangle, tri-hexagon, cubic, octet, quarter cubic, cross and concentric patterns are fully printed every layer. Cubic, quarter cubic and octet infill change with every layer to provide a more equal distribution of strength over each direction."
+#~ msgstr "Motif du matériau de remplissage de l'impression. La ligne et le remplissage en zigzag changent de sens à chaque alternance de couche, réduisant ainsi les coûts matériels. Les motifs en grille, en triangle, trihexagonaux, cubiques, octaédriques, quart cubiques et concentriques sont entièrement imprimés sur chaque couche. Les remplissages cubique, quart cubique et octaédrique changent à chaque couche afin d'offrir une répartition plus égale de la solidité dans chaque direction."
+
#~ msgctxt "infill_pattern option concentric_3d"
#~ msgid "Concentric 3D"
#~ msgstr "Concentrique 3D"
diff --git a/resources/i18n/it_IT/cura.po b/resources/i18n/it_IT/cura.po
index 7ce106e07c..07a73aa191 100644
--- a/resources/i18n/it_IT/cura.po
+++ b/resources/i18n/it_IT/cura.po
@@ -1,24 +1,24 @@
# Cura
-# Copyright (C) 2018 Ultimaker
+# Copyright (C) 2019 Ultimaker B.V.
# This file is distributed under the same license as the Cura package.
-# Ruben Dulek , 2018.
+# Ruben Dulek , 2019.
#
msgid ""
msgstr ""
-"Project-Id-Version: Cura 3.5\n"
+"Project-Id-Version: Cura 4.2\n"
"Report-Msgid-Bugs-To: r.dulek@ultimaker.com\n"
-"POT-Creation-Date: 2018-09-19 17:07+0200\n"
-"PO-Revision-Date: 2018-09-28 15:01+0200\n"
-"Last-Translator: Bothof \n"
-"Language-Team: Italian\n"
+"POT-Creation-Date: 2019-07-16 14:38+0200\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:27
msgctxt "@action"
msgid "Machine Settings"
msgstr "Impostazioni macchina"
@@ -48,15 +48,15 @@ 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
msgctxt "@warning:status"
-msgid "Please generate G-code before saving."
-msgstr "Generare il codice G prima di salvare."
+msgid "Please prepare G-code before exporting."
+msgstr "Preparare il codice G prima dell’esportazione."
-#: /home/ruben/Projects/Cura/plugins/ModelChecker/ModelChecker.py:30
+#: /home/ruben/Projects/Cura/plugins/ModelChecker/ModelChecker.py:31
msgctxt "@info:title"
msgid "3D Model Assistant"
msgstr "Assistente modello 3D"
-#: /home/ruben/Projects/Cura/plugins/ModelChecker/ModelChecker.py:80
+#: /home/ruben/Projects/Cura/plugins/ModelChecker/ModelChecker.py:90
#, python-brace-format
msgctxt "@info:status"
msgid ""
@@ -70,10 +70,10 @@ msgstr ""
"
Scopri come garantire la migliore qualità ed affidabilità di stampa.
"
-#: /home/ruben/Projects/Cura/plugins/ChangeLogPlugin/ChangeLog.py:32
-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"
@@ -85,37 +85,36 @@ msgctxt "@info:status"
msgid "Profile has been flattened & activated."
msgstr "Il profilo è stato appiattito e attivato."
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:40
+#: /home/ruben/Projects/Cura/plugins/AMFReader/__init__.py:15
+msgctxt "@item:inlistbox"
+msgid "AMF File"
+msgstr "File AMF"
+
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:37
msgctxt "@item:inmenu"
msgid "USB printing"
msgstr "Stampa USB"
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:41
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:38
msgctxt "@action:button Preceded by 'Ready to'."
msgid "Print via USB"
msgstr "Stampa tramite USB"
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:42
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:39
msgctxt "@info:tooltip"
msgid "Print via USB"
msgstr "Stampa tramite USB"
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:83
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:75
msgctxt "@info:status"
msgid "Connected via USB"
msgstr "Connesso tramite USB"
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:103
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:100
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/X3GWriter/build/GPX-prefix/src/GPX/slicerplugins/cura15.06/X3gWriter/__init__.py:16
msgctxt "X3g Writer Plugin Description"
msgid "Writes X3g to files"
@@ -126,6 +125,11 @@ msgctxt "X3g Writer File Description"
msgid "X3g File"
msgstr "File X3g"
+#: /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/GCodeGzWriter/__init__.py:17
#: /home/ruben/Projects/Cura/plugins/GCodeGzReader/__init__.py:17
msgctxt "@item:inlistbox"
@@ -137,7 +141,8 @@ msgctxt "@error:not supported"
msgid "GCodeGzWriter does not support text mode."
msgstr "GCodeGzWriter non supporta la modalità di testo."
-#: /home/ruben/Projects/Cura/plugins/UFPWriter/__init__.py:38
+#: /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"
@@ -159,7 +164,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/ClusterUM3OutputDevice.py:131
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/MeshFormatHandler.py:106
msgctxt "@info:status"
msgid "There are no file formats available to write with!"
msgstr "Non ci sono formati di file disponibili per la scrittura!"
@@ -196,9 +201,10 @@ 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/cura/Settings/CuraContainerRegistry.py:133
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:140
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1567
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py:188
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:134
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:141
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1622
msgctxt "@info:title"
msgid "Error"
msgstr "Errore"
@@ -227,8 +233,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/CuraApplication.py:1557
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1651
+#: /home/ruben/Projects/Cura/cura/OAuth2/AuthorizationService.py:197
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1612
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1712
msgctxt "@info:title"
msgid "Warning"
msgstr "Avvertenza"
@@ -255,276 +262,387 @@ 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:86
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:75
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:93
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:87
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:76
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:94
msgctxt "@properties:tooltip"
msgid "Print over network"
msgstr "Stampa sulla rete"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:88
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:95
msgctxt "@info:status"
msgid "Connected over the network."
msgstr "Collegato alla rete."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:91
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:98
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
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:100
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
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:105
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
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:108
msgctxt "@info:title"
msgid "Authentication status"
msgstr "Stato di autenticazione"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:103
-msgctxt "@info:status"
-msgid ""
-msgstr ""
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:104
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:110
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:114
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:116
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:120
msgctxt "@info:title"
msgid "Authentication Status"
msgstr "Stato di autenticazione"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:105
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:111
+#: /home/ruben/Projects/Cura/cura/OAuth2/AuthorizationService.py:198
msgctxt "@action:button"
msgid "Retry"
msgstr "Riprova"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:106
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:112
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:109
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:115
msgctxt "@info:status"
msgid "Access to the printer accepted"
msgstr "Accesso alla stampante accettato"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:113
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:119
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:115
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/UM3InfoComponents.qml:29
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/UM3InfoComponents.qml:73
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:121
+#: /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:117
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/UM3InfoComponents.qml:28
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/UM3InfoComponents.qml:72
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:123
+#: /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:202
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:208
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:204
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:210
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:210
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:232
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:216
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:238
msgctxt "@window:title"
msgid "Mismatched configuration"
msgstr "Mancata corrispondenza della configurazione"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:224
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:230
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:226
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:232
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:253
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:197
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:259
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:176
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:181
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:260
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:216
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:232
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:266
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:194
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:211
msgctxt "@info:status"
msgid "Sending data to printer"
msgstr "Invio dati alla stampante in corso"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:261
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:217
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:233
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:267
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:196
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:213
msgctxt "@info:title"
msgid "Sending Data"
msgstr "Invio dati"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:262
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:234
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxProgressButton.qml:18
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxConfirmUninstallResetDialog.qml:80
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:378
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintWindow.qml:92
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/MoreInfoWindow.qml:143
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:268
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:214
+#: /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:410
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintWindow.qml:20
+#: /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:391
-#: /home/ruben/Projects/Cura/resources/qml/OpenFilesIncludingProjectsDialog.qml:87
-#: /home/ruben/Projects/Cura/resources/qml/WorkspaceSummaryDialog.qml:279
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/OpenFilesIncludingProjectsDialog.qml:87
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:283
msgctxt "@action:button"
msgid "Cancel"
msgstr "Annulla"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:325
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:331
#, 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:331
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:337
#, 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:354
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:360
#, 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:363
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:369
#, 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:549
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:555
msgctxt "@window:title"
msgid "Sync with your printer"
msgstr "Sincronizzazione con la stampante"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:551
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:557
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:553
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/LegacyUM3OutputDevice.py:559
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:89
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:96
msgctxt "@info:status"
msgid "Connected over the network"
msgstr "Collegato alla rete"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:310
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:289
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:370
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:312
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:291
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:371
msgctxt "@info:title"
msgid "Data Sent"
msgstr "Dati inviati"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:313
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:292
msgctxt "@action:button"
msgid "View in Monitor"
msgstr "Visualizzazione in Controlla"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:420
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:411
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:318
#, python-brace-format
msgctxt "@info:status"
msgid "Printer '{printer_name}' has finished printing '{job_name}'."
msgstr "La stampante '{printer_name}' ha finito di stampare '{job_name}'."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:422
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:413
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:322
#, 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:423
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:414
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:316
msgctxt "@info:status"
msgid "Print finished"
msgstr "Stampa finita"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/DiscoverUM3Action.py:26
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:595
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:629
+msgctxt "@label:material"
+msgid "Empty"
+msgstr "Vuoto"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:596
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py:630
+msgctxt "@label:material"
+msgid "Unknown"
+msgstr "Sconosciuto"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:169
+msgctxt "@action:button"
+msgid "Print via Cloud"
+msgstr "Stampa tramite Cloud"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:170
+msgctxt "@properties:tooltip"
+msgid "Print via Cloud"
+msgstr "Stampa tramite Cloud"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:171
+msgctxt "@info:status"
+msgid "Connected via Cloud"
+msgstr "Collegato tramite Cloud"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:182
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:359
+msgctxt "@info:title"
+msgid "Cloud error"
+msgstr "Errore cloud"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:199
+msgctxt "@info:status"
+msgid "Could not export print job."
+msgstr "Impossibile esportare il processo di stampa."
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py:358
+msgctxt "@info:text"
+msgid "Could not upload the data to the printer."
+msgstr "Impossibile caricare i dati sulla stampante."
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/Utils.py:51
+msgctxt "@info:status"
+msgid "tomorrow"
+msgstr "domani"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/Utils.py:54
+msgctxt "@info:status"
+msgid "today"
+msgstr "oggi"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py:187
+msgctxt "@info:description"
+msgid "There was an error connecting to the cloud."
+msgstr "Si è verificato un errore di collegamento al cloud."
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudProgressMessage.py:14
+msgctxt "@info:status"
+msgid "Sending Print Job"
+msgstr "Invio di un processo di stampa"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/Cloud/CloudProgressMessage.py:15
+msgctxt "@info:status"
+msgid "Uploading via Ultimaker Cloud"
+msgstr "Caricamento tramite Ultimaker Cloud"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py:621
+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/UM3OutputDevicePlugin.py:627
+msgctxt "@info:status Ultimaker Cloud is a brand name and shouldn't be translated."
+msgid "Connect to Ultimaker Cloud"
+msgstr "Collegato a Ultimaker Cloud"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py:628
+msgctxt "@action"
+msgid "Don't ask me again for this printer."
+msgstr "Non chiedere nuovamente per questa stampante."
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py:631
+msgctxt "@action"
+msgid "Get started"
+msgstr "Per iniziare"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py:637
+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."
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py:643
+msgctxt "@info:status"
+msgid "Connected!"
+msgstr "Collegato!"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py:645
+msgctxt "@action"
+msgid "Review your connection"
+msgstr "Controlla collegamento"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/src/DiscoverUM3Action.py:30
msgctxt "@action"
msgid "Connect via Network"
msgstr "Collega tramite rete"
-#: /home/ruben/Projects/Cura/plugins/MonitorStage/__init__.py:12
+#: /home/ruben/Projects/Cura/plugins/MonitorStage/__init__.py:14
msgctxt "@item:inmenu"
msgid "Monitor"
msgstr "Controlla"
-#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py:68
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py:118
+msgctxt "@info"
+msgid "Could not access update information."
+msgstr "Non è possibile accedere alle informazioni di aggiornamento."
+
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerMessage.py:17
#, python-brace-format
msgctxt "@info Don't translate {machine_name}, since it gets replaced by a printer name!"
msgid "New features are available for your {machine_name}! It is recommended to update the firmware on your printer."
msgstr "Sono disponibili nuove funzioni per la {machine_name}! Si consiglia di aggiornare il firmware sulla stampante."
-#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py:72
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerMessage.py:21
#, python-format
msgctxt "@info:title The %s gets replaced with the printer name."
msgid "New %s firmware available"
msgstr "Nuovo firmware %s disponibile"
-#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py:75
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerMessage.py:27
msgctxt "@action:button"
msgid "How to update"
msgstr "Modalità di aggiornamento"
-#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py:91
-msgctxt "@info"
-msgid "Could not access update information."
-msgstr "Non è possibile accedere alle informazioni di aggiornamento."
-
-#: /home/ruben/Projects/Cura/plugins/SimulationView/__init__.py:14
+#: /home/ruben/Projects/Cura/plugins/SimulationView/__init__.py:15
msgctxt "@item:inlistbox"
msgid "Layer view"
msgstr "Visualizzazione strato"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.py:102
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.py:114
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:103
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.py:115
msgctxt "@info:title"
msgid "Simulation View"
msgstr "Vista simulazione"
-#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.py:28
+#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.py:35
+msgctxt "@item:inmenu"
+msgid "Post Processing"
+msgstr "Post-elaborazione"
+
+#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.py:36
+msgctxt "@item:inmenu"
msgid "Modify G-Code"
-msgstr "Modifica G-code"
+msgstr "Modifica codice G"
#: /home/ruben/Projects/Cura/plugins/SupportEraser/__init__.py:12
msgctxt "@label"
@@ -536,36 +654,6 @@ 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:43
-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:46
-msgctxt "@info:title"
-msgid "Collecting Data"
-msgstr "Acquisizione dati"
-
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/SliceInfo.py:48
-msgctxt "@action:button"
-msgid "More info"
-msgstr "Per saperne di più"
-
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/SliceInfo.py:49
-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:51
-msgctxt "@action:button"
-msgid "Allow"
-msgstr "Consenti"
-
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/SliceInfo.py:52
-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"
@@ -596,56 +684,56 @@ msgctxt "@item:inlistbox"
msgid "GIF Image"
msgstr "Immagine GIF"
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:333
+#: /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:333
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:364
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:388
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:397
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:406
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:415
+#: /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:363
+#: /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:387
+#: /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:396
+#: /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:405
+#: /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:414
+#: /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. Please scale or rotate models to fit."
-msgstr "Nulla da sezionare in quanto nessuno dei modelli corrisponde al volume di stampa. Ridimensionare o ruotare i modelli secondo necessità."
+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 "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:49
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py:242
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py:50
+#: /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:242
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py:256
msgctxt "@info:title"
msgid "Information"
msgstr "Informazioni"
@@ -661,13 +749,11 @@ msgid "Configure Per Model Settings"
msgstr "Configura impostazioni per modello"
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.py:175
-#: /home/ruben/Projects/Cura/resources/qml/PrepareSidebar.qml:576
msgctxt "@title:tab"
msgid "Recommended"
msgstr "Consigliata"
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.py:177
-#: /home/ruben/Projects/Cura/resources/qml/PrepareSidebar.qml:581
msgctxt "@title:tab"
msgid "Custom"
msgstr "Personalizzata"
@@ -678,19 +764,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:711
+#: /home/ruben/Projects/Cura/plugins/3MFReader/ThreeMFWorkspaceReader.py:191
+#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:775
msgctxt "@label"
msgid "Nozzle"
msgstr "Ugello"
-#: /home/ruben/Projects/Cura/plugins/3MFReader/ThreeMFWorkspaceReader.py:468
+#: /home/ruben/Projects/Cura/plugins/3MFReader/ThreeMFWorkspaceReader.py:474
#, 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:471
+#: /home/ruben/Projects/Cura/plugins/3MFReader/ThreeMFWorkspaceReader.py:477
msgctxt "@info:title"
msgid "Open Project File"
msgstr "Apri file progetto"
@@ -705,22 +791,65 @@ msgctxt "@item:inlistbox"
msgid "G File"
msgstr "File G"
-#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:317
+#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:328
msgctxt "@info:status"
msgid "Parsing G-code"
msgstr "Parsing codice G"
-#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:319
-#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:466
+#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:330
+#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:483
msgctxt "@info:title"
msgid "G-code Details"
msgstr "Dettagli codice G"
-#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:464
+#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:481
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."
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/DrivePluginExtension.py:64
+msgctxt "@item:inmenu"
+msgid "Manage backups"
+msgstr "Gestione backup"
+
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/DrivePluginExtension.py:107
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/DrivePluginExtension.py:113
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/DriveApiService.py:55
+#: /home/ruben/Projects/Cura/cura/Backups/Backup.py:104
+msgctxt "@info:title"
+msgid "Backup"
+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 "Si è verificato un errore nell’elenco dei backup."
+
+#: /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 "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 "Backup"
+
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/UploadBackupJob.py:27
+msgctxt "@info:backup_status"
+msgid "Uploading your backup..."
+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 "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 "Caricamento backup completato."
+
#: /home/ruben/Projects/Cura/plugins/CuraProfileWriter/__init__.py:14
#: /home/ruben/Projects/Cura/plugins/CuraProfileReader/__init__.py:14
msgctxt "@item:inlistbox"
@@ -732,7 +861,7 @@ msgctxt "@item:inmenu"
msgid "Profile Assistant"
msgstr "Assistente profilo"
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/__init__.py:17
+#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/__init__.py:18
msgctxt "@item:inlistbox"
msgid "Profile Assistant"
msgstr "Assistente profilo"
@@ -752,231 +881,266 @@ msgctxt "@error:zip"
msgid "Error writing 3mf file."
msgstr "Errore scrittura file 3MF."
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UM2UpgradeSelection.py:17
+#: /home/ruben/Projects/Cura/plugins/PreviewStage/__init__.py:13
+msgctxt "@item:inmenu"
+msgid "Preview"
+msgstr "Anteprima"
+
+#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UM2UpgradeSelection.py:19
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOUpgradeSelection.py:18
msgctxt "@action"
msgid "Select upgrades"
msgstr "Seleziona aggiornamenti"
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UpgradeFirmwareMachineAction.py:12
-msgctxt "@action"
-msgid "Upgrade Firmware"
-msgstr "Aggiorna firmware"
-
-#: /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:98
-msgctxt "@tooltip"
-msgid "Outer Wall"
-msgstr "Parete esterna"
+#: /home/ruben/Projects/Cura/cura/API/Account.py:82
+msgctxt "@info:title"
+msgid "Login failed"
+msgstr "Login non riuscito"
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:99
-msgctxt "@tooltip"
-msgid "Inner Walls"
-msgstr "Pareti interne"
+#: /home/ruben/Projects/Cura/cura/Settings/cura_empty_instance_containers.py:33
+msgctxt "@info:not supported profile"
+msgid "Not supported"
+msgstr "Non supportato"
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:100
-msgctxt "@tooltip"
-msgid "Skin"
-msgstr "Rivestimento esterno"
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:101
-msgctxt "@tooltip"
-msgid "Infill"
-msgstr "Riempimento"
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:102
-msgctxt "@tooltip"
-msgid "Support Infill"
-msgstr "Riempimento del supporto"
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:103
-msgctxt "@tooltip"
-msgid "Support Interface"
-msgstr "Interfaccia supporto"
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:104
-msgctxt "@tooltip"
-msgid "Support"
-msgstr "Supporto"
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:105
-msgctxt "@tooltip"
-msgid "Skirt"
-msgstr "Skirt"
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:106
-msgctxt "@tooltip"
-msgid "Travel"
-msgstr "Spostamenti"
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:107
-msgctxt "@tooltip"
-msgid "Retractions"
-msgstr "Retrazioni"
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:108
-msgctxt "@tooltip"
-msgid "Other"
-msgstr "Altro"
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:229
-msgctxt "@label unknown material"
-msgid "Unknown"
-msgstr "Sconosciuto"
-
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:314
-#, python-brace-format
-msgctxt "@label"
-msgid "Pre-sliced file {0}"
-msgstr "File pre-sezionato {0}"
-
-#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:186
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:121
+#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:203
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:122
msgctxt "@title:window"
msgid "File Already Exists"
msgstr "Il file esiste già"
-#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:187
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:122
+#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:204
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:123
#, 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/ExtrudersModel.py:212
-msgctxt "@menuitem"
-msgid "Not overridden"
-msgstr "Non sottoposto a override"
-
-#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:120
+#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:427
+#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:430
msgctxt "@info:status"
-msgid "The selected material is incompatible with the selected machine or configuration."
-msgstr "Il materiale selezionato è incompatibile con la macchina o la configurazione selezionata."
+msgid "Invalid file URL:"
+msgstr "File URL non valido:"
-#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:121
-msgctxt "@info:title"
-msgid "Incompatible Material"
-msgstr "Materiale incompatibile"
+#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:925
+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:863
-#, 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:865
+#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:927
msgctxt "@info:title"
msgid "Settings updated"
msgstr "Impostazioni aggiornate"
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:131
+#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:1481
+msgctxt "@info:title"
+msgid "Extruder(s) Disabled"
+msgstr "Estrusore disabilitato"
+
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:132
#, 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:139
#, 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:144
#, 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:145
msgctxt "@info:title"
msgid "Export succeeded"
msgstr "Esportazione riuscita"
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:170
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:194
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:313
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:172
#, python-brace-format
-msgctxt "@info:status Don't translate the XML tags or !"
-msgid "Failed to import profile from {0}: {1}"
-msgstr "Impossibile importare il profilo da {0}: {1}"
+msgctxt "@info:status Don't translate the XML tags !"
+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:176
#, python-brace-format
-msgctxt "@info:status Don't translate the XML tags or !"
+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:192
+#, 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:218
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:228
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:196
#, python-brace-format
-msgctxt "@info:status Don't translate the XML tags or !"
+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:220
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:230
+#, 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:243
+#, 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:315
#, python-brace-format
msgctxt "@info:status Don't translate the XML tags or !"
-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 importarlo."
+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:318
#, 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:321
#, 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:324
#, 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:359
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:375
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:389
#, 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:59
+#: /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:306
+#, python-brace-format
+msgctxt "@label"
+msgid "Pre-sliced file {0}"
+msgstr "File pre-sezionato {0}"
+
+#: /home/ruben/Projects/Cura/cura/UI/WelcomePagesModel.py:56
+#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/ProfileCreatorTabControls.qml:62
+msgctxt "@action:button"
+msgid "Next"
+msgstr "Avanti"
+
+#: /home/ruben/Projects/Cura/cura/UI/ObjectsModel.py:61
#, 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/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:124
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:168
+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:91
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:48
+msgctxt "@action:button"
+msgid "Add"
+msgstr "Aggiungi"
+
+#: /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:109
#, python-brace-format
@@ -989,45 +1153,79 @@ msgctxt "@item:inlistbox"
msgid "All Files (*)"
msgstr "Tutti i file (*)"
-#: /home/ruben/Projects/Cura/cura/Machines/MaterialManager.py:609
+#: /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
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:269
+msgctxt "@label"
+msgid "Unknown"
+msgstr "Sconosciuto"
+
+#: /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/Machines/MaterialManager.py:689
msgctxt "@label"
msgid "Custom Material"
msgstr "Materiale personalizzato"
-#: /home/ruben/Projects/Cura/cura/Machines/MaterialManager.py:610
+#: /home/ruben/Projects/Cura/cura/Machines/MaterialManager.py:690
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/ConfigurationMenu.qml:203
msgctxt "@label"
msgid "Custom"
msgstr "Personalizzata"
-#: /home/ruben/Projects/Cura/cura/BuildVolume.py:81
+#: /home/ruben/Projects/Cura/cura/BuildVolume.py:89
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:91
msgctxt "@info:title"
msgid "Build Volume"
msgstr "Volume di stampa"
-#: /home/ruben/Projects/Cura/cura/Backups/Backup.py:97
+#: /home/ruben/Projects/Cura/cura/Backups/Backup.py:99
msgctxt "@info:backup_failed"
msgid "Could not create archive from user data directory: {}"
msgstr "Impossibile creare un archivio dalla directory dei dati utente: {}"
-#: /home/ruben/Projects/Cura/cura/Backups/Backup.py:102
-msgctxt "@info:title"
-msgid "Backup"
-msgstr "Backup"
-
-#: /home/ruben/Projects/Cura/cura/Backups/Backup.py:112
+#: /home/ruben/Projects/Cura/cura/Backups/Backup.py:114
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:122
+#: /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/AuthorizationHelpers.py:79
+msgctxt "@message"
+msgid "Could not read response."
+msgstr "Impossibile leggere la risposta."
+
+#: /home/ruben/Projects/Cura/cura/OAuth2/AuthorizationService.py:197
+msgctxt "@info"
+msgid "Unable to reach the Ultimaker account server."
+msgstr "Impossibile raggiungere il server account Ultimaker."
+
+#: /home/ruben/Projects/Cura/cura/OAuth2/AuthorizationRequestHandler.py:66
+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:73
+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:27
msgctxt "@info:status"
@@ -1035,42 +1233,46 @@ msgid "Multiplying and placing objects"
msgstr "Moltiplicazione e collocazione degli oggetti"
#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:28
+msgctxt "@info:title"
+msgid "Placing Objects"
+msgstr "Sistemazione oggetti"
+
+#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:100
+#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsJob.py:103
+#: /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
msgctxt "@info:title"
msgid "Placing Object"
msgstr "Sistemazione oggetto"
-#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:100
-#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsJob.py:96
-#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsAllBuildPlatesJob.py:150
-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/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:97
-#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsAllBuildPlatesJob.py:151
+#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsJob.py:104
+#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsAllBuildPlatesJob.py:150
msgctxt "@info:title"
msgid "Can't Find Location"
msgstr "Impossibile individuare posizione"
-#: /home/ruben/Projects/Cura/cura/CrashHandler.py:87
+#: /home/ruben/Projects/Cura/cura/CrashHandler.py:83
msgctxt "@title:window"
msgid "Cura can't start"
msgstr "Impossibile avviare Cura"
-#: /home/ruben/Projects/Cura/cura/CrashHandler.py:93
+#: /home/ruben/Projects/Cura/cura/CrashHandler.py:89
msgctxt "@label crash message"
msgid ""
"
Oops, Ultimaker Cura has encountered something that doesn't seem right.
\n"
@@ -1085,32 +1287,32 @@ msgstr ""
"
Si prega di inviare questo Rapporto su crash per correggere il problema.
\n"
" "
-#: /home/ruben/Projects/Cura/cura/CrashHandler.py:102
+#: /home/ruben/Projects/Cura/cura/CrashHandler.py:98
msgctxt "@action:button"
msgid "Send crash report to Ultimaker"
msgstr "Inviare il rapporto su crash a Ultimaker"
-#: /home/ruben/Projects/Cura/cura/CrashHandler.py:105
+#: /home/ruben/Projects/Cura/cura/CrashHandler.py:101
msgctxt "@action:button"
msgid "Show detailed crash report"
msgstr "Mostra il rapporto su crash dettagliato"
-#: /home/ruben/Projects/Cura/cura/CrashHandler.py:109
+#: /home/ruben/Projects/Cura/cura/CrashHandler.py:105
msgctxt "@action:button"
msgid "Show configuration folder"
msgstr "Mostra cartella di configurazione"
-#: /home/ruben/Projects/Cura/cura/CrashHandler.py:120
+#: /home/ruben/Projects/Cura/cura/CrashHandler.py:116
msgctxt "@action:button"
msgid "Backup and Reset Configuration"
msgstr "Backup e reset configurazione"
-#: /home/ruben/Projects/Cura/cura/CrashHandler.py:149
+#: /home/ruben/Projects/Cura/cura/CrashHandler.py:145
msgctxt "@title:window"
msgid "Crash Report"
msgstr "Rapporto su crash"
-#: /home/ruben/Projects/Cura/cura/CrashHandler.py:169
+#: /home/ruben/Projects/Cura/cura/CrashHandler.py:165
msgctxt "@label crash message"
msgid ""
"
A fatal error has occurred in Cura. Please send us this Crash Report to fix the problem
\n"
@@ -1121,311 +1323,275 @@ msgstr ""
"
Usare il pulsante “Invia report\" per inviare automaticamente una segnalazione errore ai nostri server
"
-#: /home/ruben/Projects/Cura/cura/CrashHandler.py:222
+#: /home/ruben/Projects/Cura/cura/CrashHandler.py:218
msgctxt "@title:groupbox"
msgid "Error traceback"
msgstr "Analisi errori"
-#: /home/ruben/Projects/Cura/cura/CrashHandler.py:303
+#: /home/ruben/Projects/Cura/cura/CrashHandler.py:299
msgctxt "@title:groupbox"
msgid "Logs"
msgstr "Registri"
-#: /home/ruben/Projects/Cura/cura/CrashHandler.py:326
+#: /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:345
+#: /home/ruben/Projects/Cura/cura/CrashHandler.py:342
msgctxt "@action:button"
msgid "Send report"
msgstr "Invia report"
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:454
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:504
msgctxt "@info:progress"
msgid "Loading machines..."
msgstr "Caricamento macchine in corso..."
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:748
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:819
msgctxt "@info:progress"
msgid "Setting up scene..."
msgstr "Impostazione scena in corso..."
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:784
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:854
msgctxt "@info:progress"
msgid "Loading interface..."
msgstr "Caricamento interfaccia in corso..."
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:997
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1133
#, 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:1556
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1611
#, 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:1566
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1621
#, 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:1650
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1711
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:61
-msgctxt "@title"
-msgid "Machine Settings"
-msgstr "Impostazioni macchina"
-
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:80
-msgctxt "@title:tab"
-msgid "Printer"
-msgstr "Stampante"
-
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:99
-msgctxt "@label"
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:58
+msgctxt "@title:label"
msgid "Printer Settings"
msgstr "Impostazioni della stampante"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:110
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:72
msgctxt "@label"
msgid "X (Width)"
msgstr "X (Larghezza)"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:111
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:121
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:131
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:237
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:386
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:402
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:420
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:432
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:857
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:76
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:90
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:104
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:194
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:213
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:232
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:253
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:272
+#: /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:120
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:86
msgctxt "@label"
msgid "Y (Depth)"
msgstr "Y (Profondità)"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:130
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:100
msgctxt "@label"
msgid "Z (Height)"
msgstr "Z (Altezza)"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:142
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:114
msgctxt "@label"
msgid "Build plate shape"
msgstr "Forma del piano di stampa"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:151
-msgctxt "@option:check"
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:127
+msgctxt "@label"
msgid "Origin at center"
msgstr "Origine al centro"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:159
-msgctxt "@option:check"
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:139
+msgctxt "@label"
msgid "Heated bed"
msgstr "Piano riscaldato"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:170
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:151
msgctxt "@label"
msgid "G-code flavor"
msgstr "Versione codice G"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:183
-msgctxt "@label"
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:176
+msgctxt "@title:label"
msgid "Printhead Settings"
msgstr "Impostazioni della testina di stampa"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:193
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:190
msgctxt "@label"
msgid "X min"
msgstr "X min"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:194
-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:203
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:209
msgctxt "@label"
msgid "Y min"
msgstr "Y min"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:204
-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:213
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:228
msgctxt "@label"
msgid "X max"
msgstr "X max"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:214
-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:223
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:249
msgctxt "@label"
msgid "Y max"
msgstr "Y max"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:224
-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:236
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:268
msgctxt "@label"
-msgid "Gantry height"
+msgid "Gantry Height"
msgstr "Altezza gantry"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:238
-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:257
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:282
msgctxt "@label"
msgid "Number of Extruders"
msgstr "Numero di estrusori"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:313
-msgctxt "@label"
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:341
+msgctxt "@title:label"
msgid "Start G-code"
msgstr "Codice G avvio"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:323
-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:332
-msgctxt "@label"
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsPrinterTab.qml:355
+msgctxt "@title:label"
msgid "End G-code"
msgstr "Codice G fine"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:342
-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:373
-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:385
+#: /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:401
+#: /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:403
-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:419
+#: /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:431
+#: /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/MachineSettingsExtruderTab.qml:162
+msgctxt "@title:label"
msgid "Extruder Start G-code"
msgstr "Codice G avvio estrusore"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:470
-msgctxt "@label"
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsExtruderTab.qml:176
+msgctxt "@title:label"
msgid "Extruder End G-code"
msgstr "Codice G fine estrusore"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxProgressButton.qml:17
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxProgressButton.qml:18
msgctxt "@action:button"
msgid "Install"
msgstr "Installazione"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxProgressButton.qml:19
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxProgressButton.qml:20
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailTileActions.qml:46
msgctxt "@action:button"
msgid "Installed"
msgstr "Installa"
@@ -1435,68 +1601,82 @@ msgctxt "@info"
msgid "Could not connect to the Cura Package database. Please check your connection."
msgstr "Impossibile connettersi al database pacchetto Cura. Verificare la connessione."
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/SmallRatingWidget.qml:27
+msgctxt "@label"
+msgid "ratings"
+msgstr "valori"
+
#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledPage.qml:38
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxHeader.qml:26
+#: /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:75
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:66
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:544
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledPage.qml:70
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxHeader.qml:44
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:80
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:417
msgctxt "@title:tab"
msgid "Materials"
msgstr "Materiali"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml:80
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml:91
+msgctxt "@label"
+msgid "Your rating"
+msgstr "I tuoi valori"
+
+#: /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:86
+#: /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:92
+#: /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:98
+#: /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:117
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailPage.qml:159
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:255
-msgctxt "@label"
-msgid "Unknown"
-msgstr "Sconosciuto"
+#: /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 "Log in deve essere installato o aggiornato"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxDetailTileActions.qml:44
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml:30
+#: /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:45
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml:31
+#: /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:46
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml:32
+#: /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"
msgstr "Aggiornamento eseguito"
#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/Toolbox.qml:13
msgctxt "@title"
-msgid "Toolbox"
-msgstr "Casella degli strumenti"
+msgid "Marketplace"
+msgstr "Mercato"
#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxBackColumn.qml:25
msgctxt "@action:button"
@@ -1505,8 +1685,8 @@ msgstr "Indietro"
#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxConfirmUninstallResetDialog.qml:20
msgctxt "@title:window"
-msgid "Confirm uninstall "
-msgstr "Conferma disinstalla "
+msgid "Confirm uninstall"
+msgstr "Conferma disinstalla"
#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxConfirmUninstallResetDialog.qml:50
msgctxt "@text:window"
@@ -1523,17 +1703,27 @@ msgctxt "@text:window"
msgid "Profiles"
msgstr "Profili"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxConfirmUninstallResetDialog.qml:89
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxConfirmUninstallResetDialog.qml:90
msgctxt "@action:button"
msgid "Confirm"
msgstr "Conferma"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxFooter.qml:17
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/RatingWidget.qml:54
+msgctxt "@label"
+msgid "You need to login first before you can rate"
+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 "Prima della valutazione è necessario installare il pacchetto"
+
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxFooter.qml:19
msgctxt "@info"
msgid "You will need to restart Cura before changes in packages have effect."
msgstr "Riavviare Cura per rendere effettive le modifiche apportate ai pacchetti."
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxFooter.qml:34
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxFooter.qml:45
msgctxt "@info:button"
msgid "Quit Cura"
msgstr "Esci da Cura"
@@ -1553,22 +1743,27 @@ msgctxt "@label"
msgid "Generic Materials"
msgstr "Materiali generici"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxHeader.qml:54
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxHeader.qml:59
msgctxt "@title:tab"
msgid "Installed"
msgstr "Installa"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml:19
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml:22
msgctxt "@label"
msgid "Will install upon restarting"
msgstr "L'installazione sarà eseguita al riavvio"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml:51
+#: /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 "Log in deve essere aggiornato"
+
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml:71
msgctxt "@action:button"
msgid "Downgrade"
msgstr "Downgrade"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml:51
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxInstalledTileActions.qml:71
msgctxt "@action:button"
msgid "Uninstall"
msgstr "Disinstalla"
@@ -1589,12 +1784,12 @@ msgstr ""
"È necessario accettare questa licenza per poter installare il plugin.\n"
"Accetti i termini sotto riportati?"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxLicenseDialog.qml:54
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxLicenseDialog.qml:55
msgctxt "@action:button"
msgid "Accept"
msgstr "Accetto"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxLicenseDialog.qml:65
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxLicenseDialog.qml:66
msgctxt "@action:button"
msgid "Decline"
msgstr "Non accetto"
@@ -1604,22 +1799,42 @@ msgctxt "@label"
msgid "Featured"
msgstr "In primo piano"
-#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:31
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:66
msgctxt "@label"
msgid "Compatibility"
msgstr "Compatibilità"
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:203
+msgctxt "@action:label"
+msgid "Technical Data Sheet"
+msgstr "Scheda dati tecnici"
+
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:212
+msgctxt "@action:label"
+msgid "Safety Data Sheet"
+msgstr "Scheda dati di sicurezza"
+
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:221
+msgctxt "@action:label"
+msgid "Printing Guidelines"
+msgstr "Linee guida di stampa"
+
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxCompatibilityChart.qml:230
+msgctxt "@action:label"
+msgid "Website"
+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:88
+#: /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:94
+#: /home/ruben/Projects/Cura/plugins/Toolbox/resources/qml/ToolboxAuthorPage.qml:98
msgctxt "@label"
msgid "Email"
msgstr "E-mail"
@@ -1629,422 +1844,594 @@ 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
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:31
+msgctxt "@title"
+msgid "Update Firmware"
+msgstr "Aggiornamento firmware"
+
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:39
msgctxt "@label"
-msgid "Changelog"
-msgstr "Registro modifiche"
+msgid "Firmware is the piece of software running directly on your 3D printer. This firmware controls the step motors, regulates the temperature and ultimately makes your printer work."
+msgstr "Il firmware è la parte di software eseguita direttamente sulla stampante 3D. Questo firmware controlla i motori passo-passo, regola la temperatura e, in ultima analisi, consente il funzionamento della stampante."
-#: /home/ruben/Projects/Cura/plugins/ChangeLogPlugin/ChangeLog.qml:37
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/FirmwareUpdateWindow.qml:84
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/UM3InfoComponents.qml:56
-#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.qml:464
-#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:508
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:121
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:148
-#: /home/ruben/Projects/Cura/resources/qml/EngineLog.qml:38
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:46
+msgctxt "@label"
+msgid "The firmware shipping with new printers works, but new versions tend to have more features and improvements."
+msgstr "Il firmware inviato a corredo delle nuove stampanti funziona, tuttavia le nuove versioni tendono ad avere più funzioni ed ottimizzazioni."
+
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:58
msgctxt "@action:button"
-msgid "Close"
-msgstr "Chiudi"
+msgid "Automatically upgrade Firmware"
+msgstr "Aggiorna automaticamente il firmware"
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/FirmwareUpdateWindow.qml:22
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:69
+msgctxt "@action:button"
+msgid "Upload custom Firmware"
+msgstr "Carica il firmware personalizzato"
+
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:83
+msgctxt "@label"
+msgid "Firmware can not be updated because there is no connection with the printer."
+msgstr "Impossibile aggiornare il firmware: nessun collegamento con la stampante."
+
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:91
+msgctxt "@label"
+msgid "Firmware can not be updated because the connection with the printer does not support upgrading firmware."
+msgstr "Impossibile aggiornare il firmware: il collegamento con la stampante non supporta l’aggiornamento del firmware."
+
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:98
+msgctxt "@title:window"
+msgid "Select custom firmware"
+msgstr "Seleziona il firmware personalizzato"
+
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:119
msgctxt "@title:window"
msgid "Firmware Update"
msgstr "Aggiornamento del firmware"
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/FirmwareUpdateWindow.qml:42
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:143
msgctxt "@label"
msgid "Updating firmware."
msgstr "Aggiornamento firmware."
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/FirmwareUpdateWindow.qml:44
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:145
msgctxt "@label"
msgid "Firmware update completed."
msgstr "Aggiornamento del firmware completato."
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/FirmwareUpdateWindow.qml:46
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:147
msgctxt "@label"
msgid "Firmware update failed due to an unknown error."
msgstr "Aggiornamento firmware non riuscito a causa di un errore sconosciuto."
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/FirmwareUpdateWindow.qml:48
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:149
msgctxt "@label"
msgid "Firmware update failed due to an communication error."
msgstr "Aggiornamento firmware non riuscito a causa di un errore di comunicazione."
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/FirmwareUpdateWindow.qml:50
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:151
msgctxt "@label"
msgid "Firmware update failed due to an input/output error."
msgstr "Aggiornamento firmware non riuscito a causa di un errore di input/output."
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/FirmwareUpdateWindow.qml:52
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdater/FirmwareUpdaterMachineAction.qml:153
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:144
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobCard.qml:181
+#: /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/DiscoverUM3Action.qml:43
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:208
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobCard.qml:249
+msgctxt "@info"
+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
+msgctxt "@info"
+msgid "The webcam is not available because you are monitoring a cloud printer."
+msgstr "La webcam non è disponibile perché si sta controllando una stampante cloud."
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:300
+msgctxt "@label:status"
+msgid "Loading..."
+msgstr "Caricamento in corso..."
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:304
+msgctxt "@label:status"
+msgid "Unavailable"
+msgstr "Non disponibile"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:308
+msgctxt "@label:status"
+msgid "Unreachable"
+msgstr "Non raggiungibile"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:312
+msgctxt "@label:status"
+msgid "Idle"
+msgstr "Ferma"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:353
+msgctxt "@label"
+msgid "Untitled"
+msgstr "Senza titolo"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:374
+msgctxt "@label"
+msgid "Anonymous"
+msgstr "Anonimo"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:401
+msgctxt "@label:status"
+msgid "Requires configuration changes"
+msgstr "Richiede modifiche di configurazione"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrinterCard.qml:439
+msgctxt "@action:button"
+msgid "Details"
+msgstr "Dettagli"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobCard.qml:130
+msgctxt "@label"
+msgid "Unavailable printer"
+msgstr "Stampante non disponibile"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobCard.qml:132
+msgctxt "@label"
+msgid "First available"
+msgstr "Primo disponibile"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml:31
+msgctxt "@label"
+msgid "Queued"
+msgstr "Coda di stampa"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml:67
+msgctxt "@label link to connect manager"
+msgid "Manage in browser"
+msgstr "Gestisci nel browser"
+
+#: /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:116
+msgctxt "@label"
+msgid "Print jobs"
+msgstr "Processi di stampa"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml:132
+msgctxt "@label"
+msgid "Total print time"
+msgstr "Tempo di stampa totale"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorQueue.qml:148
+msgctxt "@label"
+msgid "Waiting for"
+msgstr "In attesa"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:50
msgctxt "@window:title"
msgid "Existing Connection"
msgstr "Collegamento esistente"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:45
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:52
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:62
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:69
msgctxt "@title:window"
msgid "Connect to Networked Printer"
msgstr "Collega alla stampante in rete"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:72
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:81
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:82
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:42
-msgctxt "@action:button"
-msgid "Add"
-msgstr "Aggiungi"
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:81
+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:92
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:101
msgctxt "@action:button"
msgid "Edit"
msgstr "Modifica"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:103
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:128
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:48
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:117
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:112
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:146
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:55
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:121
msgctxt "@action:button"
msgid "Remove"
msgstr "Rimuovi"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:111
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:120
msgctxt "@action:button"
msgid "Refresh"
msgstr "Aggiorna"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:204
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:215
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:231
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:244
+#: /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:268
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:283
+#: /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:280
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:297
+#: /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:302
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:321
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:306
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:325
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:316
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:336
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:321
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/UM3InfoComponents.qml:39
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:341
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/UM3InfoComponents.qml:74
msgctxt "@action:button"
msgid "Connect"
msgstr "Collega"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:335
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:354
+msgctxt "@title:window"
+msgid "Invalid IP address"
+msgstr "Indirizzo IP non valido"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:355
+#: /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:366
msgctxt "@title:window"
msgid "Printer Address"
msgstr "Indirizzo stampante"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:358
-msgctxt "@alabel"
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:389
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddPrinterByIpContent.qml:102
+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."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:387
-#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/MoreInfoWindow.qml:132
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml:419
+#: /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/PrintWindow.qml:34
-msgctxt "@title:window"
-msgid "Print over network"
-msgstr "Stampa sulla rete"
+#: /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/PrintWindow.qml:65
-msgctxt "@label"
-msgid "Printer selection"
-msgstr "Selezione stampante"
+#: /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/PrintWindow.qml:105
+#: /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 "Preparazione in corso..."
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:88
+msgctxt "@label:status"
+msgid "Aborting..."
+msgstr "Interr. in corso..."
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorPrintJobProgressBar.qml:92
+msgctxt "@label:status"
+msgid "Pausing..."
+msgstr "Messa in pausa..."
+
+#: /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:96
+msgctxt "@label:status"
+msgid "Resuming..."
+msgstr "Ripresa in corso..."
+
+#: /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:100
+msgctxt "@label:status"
+msgid "Finishes %1 at %2"
+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/PrintJobInfoBlock.qml:142
-msgctxt "@label"
-msgid "Waiting for: Unavailable printer"
-msgstr "In attesa: stampante non disponibile"
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintWindow.qml:47
+msgctxt "@title:window"
+msgid "Print over network"
+msgstr "Stampa sulla rete"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintJobInfoBlock.qml:144
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintWindow.qml:79
msgctxt "@label"
-msgid "Waiting for: First available"
-msgstr "In attesa della prima disponibile"
+msgid "Printer selection"
+msgstr "Selezione stampante"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintJobInfoBlock.qml:148
-msgctxt "@label"
-msgid "Waiting for: "
-msgstr "In attesa: "
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintJobInfoBlock.qml:213
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:54
msgctxt "@label"
msgid "Move to top"
msgstr "Sposta in alto"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintJobInfoBlock.qml:234
-msgctxt "@window:title"
-msgid "Move print job to top"
-msgstr "Sposta il processo di stampa in alto"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintJobInfoBlock.qml:236
-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?"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintJobInfoBlock.qml:245
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:70
msgctxt "@label"
msgid "Delete"
msgstr "Cancella"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintJobInfoBlock.qml:264
-msgctxt "@window:title"
-msgid "Delete print job"
-msgstr "Cancella processo di stampa"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/PrintJobInfoBlock.qml:266
-msgctxt "@label %1 is the name of a print job."
-msgid "Are you sure you want to delete %1?"
-msgstr "Sei sicuro di voler cancellare %1?"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/ClusterMonitorItem.qml:32
-msgctxt "@label link to connect manager"
-msgid "Manage queue"
-msgstr "Gestione coda di stampa"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/ClusterMonitorItem.qml:54
-msgctxt "@label"
-msgid "Queued"
-msgstr "Coda di stampa"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/ClusterControlItem.qml:44
-msgctxt "@label"
-msgid "Printing"
-msgstr "Stampa in corso"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/ClusterControlItem.qml:54
-msgctxt "@label link to connect manager"
-msgid "Manage printers"
-msgstr "Gestione stampanti"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/ClusterControlItem.qml:212
-msgctxt "@label"
-msgid "Not available"
-msgstr "Non disponibile"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/ClusterControlItem.qml:215
-msgctxt "@label"
-msgid "Unreachable"
-msgstr "Non raggiungibile"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/ClusterControlItem.qml:221
-msgctxt "@label"
-msgid "Available"
-msgstr "Disponibile"
-
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/ClusterControlItem.qml:416
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:100
#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:289
msgctxt "@label"
msgid "Resume"
msgstr "Riprendi"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/ClusterControlItem.qml:416
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:102
+msgctxt "@label"
+msgid "Pausing..."
+msgstr "Messa in pausa..."
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:104
+msgctxt "@label"
+msgid "Resuming..."
+msgstr "Ripresa in corso..."
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:106
#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:284
#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:293
msgctxt "@label"
msgid "Pause"
msgstr "Pausa"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/ClusterControlItem.qml:444
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:124
+msgctxt "@label"
+msgid "Aborting..."
+msgstr "Interr. in corso..."
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:124
msgctxt "@label"
msgid "Abort"
msgstr "Interrompi"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/ClusterControlItem.qml:464
+#: /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?"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:144
+msgctxt "@window:title"
+msgid "Move print job to top"
+msgstr "Sposta il processo di stampa in alto"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:153
+msgctxt "@label %1 is the name of a print job."
+msgid "Are you sure you want to delete %1?"
+msgstr "Sei sicuro di voler cancellare %1?"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:154
+msgctxt "@window:title"
+msgid "Delete print job"
+msgstr "Cancella processo di stampa"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:163
+msgctxt "@label %1 is the name of a print job."
+msgid "Are you sure you want to abort %1?"
+msgstr "Sei sicuro di voler interrompere %1?"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorContextMenu.qml:164
#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:335
msgctxt "@window:title"
msgid "Abort print"
msgstr "Interrompi la stampa"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/ClusterControlItem.qml:466
-msgctxt "@label %1 is the name of a print job."
-msgid "Are you sure you want to abort %1?"
-msgstr "Sei sicuro di voler interrompere %1?"
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:20
+msgctxt "@title:window"
+msgid "Configuration Changes"
+msgstr "Modifiche configurazione"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/ClusterControlItem.qml:665
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/ClusterControlItem.qml:673
-msgctxt "@label:status"
-msgid "Aborted"
-msgstr "Interrotto"
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/MonitorConfigOverrideDialog.qml:27
+msgctxt "@action:button"
+msgid "Override"
+msgstr "Override"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/ClusterControlItem.qml:667
-msgctxt "@label:status"
-msgid "Finished"
-msgstr "Terminato"
+#: /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] "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/ClusterControlItem.qml:670
-msgctxt "@label:status"
-msgid "Preparing"
-msgstr "Preparazione in corso"
+#: /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/ClusterControlItem.qml:675
-msgctxt "@label:status"
-msgid "Pausing"
-msgstr "Messa in pausa"
+#: /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/ClusterControlItem.qml:677
-msgctxt "@label:status"
-msgid "Paused"
-msgstr "In pausa"
+#: /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/ClusterControlItem.qml:679
-msgctxt "@label:status"
-msgid "Resuming"
-msgstr "Ripresa"
+#: /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/ClusterControlItem.qml:681
-msgctxt "@label:status"
-msgid "Action required"
-msgstr "Richiede un'azione"
+#: /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/UM3InfoComponents.qml:38
+#: /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 "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: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/UM3NetworkPrinting/resources/qml/UM3InfoComponents.qml:117
-msgctxt "@info:tooltip"
-msgid "Load the configuration of the printer into Cura"
-msgstr "Carica la configurazione della stampante in Cura"
+#: /home/ruben/Projects/Cura/plugins/SettingsGuide/resources/qml/SettingsGuide.qml:16
+msgctxt "@title"
+msgid "Cura Settings Guide"
+msgstr "Guida alle impostazioni Cura"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/resources/qml/UM3InfoComponents.qml:118
-msgctxt "@action:button"
-msgid "Activate Configuration"
-msgstr "Attiva la configurazione"
+#: /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.\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/SimulationView/SimulationView.qml:130
+#: /home/ruben/Projects/Cura/plugins/MonitorStage/MonitorMain.qml:117
+msgctxt "@info"
+msgid "Please connect your printer to the network."
+msgstr "Collegare la stampante alla rete."
+
+#: /home/ruben/Projects/Cura/plugins/MonitorStage/MonitorMain.qml:156
+msgctxt "@label link to technical assistance"
+msgid "View user manuals online"
+msgstr "Visualizza i manuali utente online"
+
+#: /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/SimulationView.qml:145
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:107
msgctxt "@label:listbox"
msgid "Material Color"
msgstr "Colore materiale"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:149
+#: /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/SimulationView.qml:153
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:115
msgctxt "@label:listbox"
msgid "Feedrate"
msgstr "Velocità"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:157
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:119
msgctxt "@label:listbox"
msgid "Layer thickness"
msgstr "Spessore strato"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:198
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:156
msgctxt "@label"
msgid "Compatibility Mode"
msgstr "Modalità di compatibilità"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:284
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:230
msgctxt "@label"
-msgid "Show Travels"
-msgstr "Mostra spostamenti"
+msgid "Travels"
+msgstr "Spostamenti"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:290
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:236
msgctxt "@label"
-msgid "Show Helpers"
-msgstr "Mostra helper"
+msgid "Helpers"
+msgstr "Helper"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:296
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:242
msgctxt "@label"
-msgid "Show Shell"
-msgstr "Mostra guscio"
+msgid "Shell"
+msgstr "Guscio"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:302
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:248
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedInfillDensitySelector.qml:65
msgctxt "@label"
-msgid "Show Infill"
-msgstr "Mostra riempimento"
+msgid "Infill"
+msgstr "Riempimento"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:355
+#: /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/SimulationView.qml:366
+#: /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/SimulationView.qml:379
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:322
msgctxt "@label"
msgid "Top / Bottom"
msgstr "Superiore / Inferiore"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:383
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:326
msgctxt "@label"
msgid "Inner Wall"
msgstr "Parete interna"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:448
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:384
msgctxt "@label"
msgid "min"
msgstr "min."
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:500
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationViewMenuComponent.qml:433
msgctxt "@label"
msgid "max"
msgstr "max."
@@ -2059,40 +2446,40 @@ msgctxt "@label"
msgid "Post Processing Scripts"
msgstr "Script di post-elaborazione"
-#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.qml:225
+#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.qml:233
msgctxt "@action"
msgid "Add a script"
msgstr "Aggiungi uno script"
-#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.qml:271
+#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.qml:279
msgctxt "@label"
msgid "Settings"
msgstr "Impostazioni"
-#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.qml:474
+#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.qml:493
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 these data"
-msgstr "Non voglio inviare questi dati"
+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 these data to Ultimaker and help us improve Cura"
-msgstr "Il consenso all'invio di questi dati ad Ultimaker ci aiuta ad ottimizzare Cura"
+msgid "Allow sending anonymous data"
+msgstr "Consenti l'invio di dati anonimi"
#: /home/ruben/Projects/Cura/plugins/ImageReader/ConfigUI.qml:19
msgctxt "@title:window"
@@ -2141,19 +2528,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."
@@ -2194,18 +2581,18 @@ 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:341
+#: /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:383
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:388
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/resources/qml/Preferences/SettingVisibilityPage.qml:98
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/SettingVisibilityPage.qml:94
msgctxt "@label:textbox"
msgid "Filter..."
msgstr "Filtro..."
@@ -2232,13 +2619,13 @@ msgid "Create new"
msgstr "Crea nuovo"
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:70
-#: /home/ruben/Projects/Cura/resources/qml/WorkspaceSummaryDialog.qml:72
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:73
msgctxt "@action:title"
msgid "Summary - Cura Project"
msgstr "Riepilogo - Progetto Cura"
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:92
-#: /home/ruben/Projects/Cura/resources/qml/WorkspaceSummaryDialog.qml:96
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:97
msgctxt "@action:label"
msgid "Printer settings"
msgstr "Impostazioni della stampante"
@@ -2255,18 +2642,19 @@ msgid "Update"
msgstr "Aggiorna"
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:143
-#: /home/ruben/Projects/Cura/resources/qml/WorkspaceSummaryDialog.qml:105
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:106
msgctxt "@action:label"
msgid "Type"
msgstr "Tipo"
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:159
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:121
msgctxt "@action:label"
msgid "Printer Group"
msgstr "Gruppo stampanti"
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:180
-#: /home/ruben/Projects/Cura/resources/qml/WorkspaceSummaryDialog.qml:196
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:226
msgctxt "@action:label"
msgid "Profile settings"
msgstr "Impostazioni profilo"
@@ -2278,19 +2666,20 @@ 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/resources/qml/WorkspaceSummaryDialog.qml:220
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:121
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:250
msgctxt "@action:label"
msgid "Name"
msgstr "Nome"
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:231
-#: /home/ruben/Projects/Cura/resources/qml/WorkspaceSummaryDialog.qml:204
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:234
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/WorkspaceSummaryDialog.qml:209
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:239
msgctxt "@action:label"
msgid "%1 override"
msgid_plural "%1 overrides"
@@ -2320,7 +2709,6 @@ 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/resources/qml/WorkspaceSummaryDialog.qml:237
msgctxt "@action:label"
msgid "Setting visibility"
msgstr "Impostazione visibilità"
@@ -2331,13 +2719,11 @@ msgid "Mode"
msgstr "Modalità"
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:352
-#: /home/ruben/Projects/Cura/resources/qml/WorkspaceSummaryDialog.qml:246
msgctxt "@action:label"
msgid "Visible settings:"
msgstr "Impostazioni visibili:"
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:357
-#: /home/ruben/Projects/Cura/resources/qml/WorkspaceSummaryDialog.qml:251
msgctxt "@action:label"
msgid "%1 out of %2"
msgstr "%1 su %2"
@@ -2352,256 +2738,191 @@ msgctxt "@action:button"
msgid "Open"
msgstr "Apri"
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/ProfileCreatorTabControls.qml:34
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/pages/BackupsPage.qml:28
+msgctxt "@title"
+msgid "My Backups"
+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 "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 "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 "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 "Accedi"
+
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/main.qml:24
+msgctxt "@title:window"
+msgid "Cura Backups"
+msgstr "Backup Cura"
+
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListItemDetails.qml:21
+msgctxt "@backuplist:label"
+msgid "Cura Version"
+msgstr "Versione Cura"
+
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListItemDetails.qml:29
+msgctxt "@backuplist:label"
+msgid "Machines"
+msgstr "Macchine"
+
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListItemDetails.qml:37
+msgctxt "@backuplist:label"
+msgid "Materials"
+msgstr "Materiali"
+
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListItemDetails.qml:45
+msgctxt "@backuplist:label"
+msgid "Profiles"
+msgstr "Profili"
+
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListItemDetails.qml:53
+msgctxt "@backuplist:label"
+msgid "Plugins"
+msgstr "Plugin"
+
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListItem.qml:71
+msgctxt "@button"
+msgid "Restore"
+msgstr "Ripristina"
+
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListItem.qml:99
+msgctxt "@dialog:title"
+msgid "Delete Backup"
+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 "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 "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 "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 "Ulteriori informazioni?"
+
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListFooter.qml:31
+msgctxt "@button"
+msgid "Backup Now"
+msgstr "Esegui backup adesso"
+
+#: /home/ruben/Projects/Cura/plugins/CuraDrive/src/qml/components/BackupListFooter.qml:43
+msgctxt "@checkbox:description"
+msgid "Auto Backup"
+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 "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 "Non supportato"
+
+#: /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:138
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:154
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:152
+#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/ProfileCreatorTabControls.qml:60
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:174
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:159
msgctxt "@action:button"
msgid "Export"
msgstr "Esporta"
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/ProfileCreatorTabControls.qml:140
-msgctxt "@action:button"
-msgid "Next"
-msgstr "Avanti"
-
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/ProfileCreatorPageCategoryView.qml:163
+#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/ProfileCreatorPageCategoryView.qml:209
msgctxt "@label"
msgid "Tip"
msgstr "Suggerimento"
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/CuraPrintProfileCreatorView.qml:80
-#: /home/ruben/Projects/Cura/resources/qml/PrepareSidebar.qml:341
-msgctxt "@label Hours and minutes"
-msgid "00h 00min"
-msgstr "00h 00min"
+#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/ProfileCreatorMaterialMenu.qml:20
+#: /home/ruben/Projects/Cura/resources/qml/Menus/MaterialMenu.qml:66
+msgctxt "@label:category menu label"
+msgid "Generic"
+msgstr "Generale"
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/CuraPrintProfileCreatorView.qml:142
-#: /home/ruben/Projects/Cura/resources/qml/PrepareSidebar.qml:441
-msgctxt "@label"
-msgid "Cost specification"
-msgstr "Indicazione di costo"
-
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/CuraPrintProfileCreatorView.qml:147
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/CuraPrintProfileCreatorView.qml:156
-#: /home/ruben/Projects/Cura/resources/qml/PrepareSidebar.qml:446
-#: /home/ruben/Projects/Cura/resources/qml/PrepareSidebar.qml:455
-msgctxt "@label m for meter"
-msgid "%1m"
-msgstr "%1m"
-
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/CuraPrintProfileCreatorView.qml:148
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/CuraPrintProfileCreatorView.qml:157
-#: /home/ruben/Projects/Cura/resources/qml/PrepareSidebar.qml:447
-#: /home/ruben/Projects/Cura/resources/qml/PrepareSidebar.qml:456
-msgctxt "@label g for grams"
-msgid "%1g"
-msgstr "%1g"
-
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/CuraPrintProfileCreatorView.qml:155
-#: /home/ruben/Projects/Cura/resources/qml/PrepareSidebar.qml:454
-msgctxt "@label"
-msgid "Total:"
-msgstr "Totale:"
-
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/CuraPrintProfileCreatorView.qml:205
-msgctxt "@label Print estimates: m for meters, g for grams, %4 is currency and %3 is print cost"
-msgid "%1m / ~ %2g / ~ %4 %3"
-msgstr "%1m / ~ %2g / ~ %4 %3"
-
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/CuraPrintProfileCreatorView.qml:210
-msgctxt "@label Print estimates: m for meters, g for grams"
-msgid "%1m / ~ %2g"
-msgstr "%1m / ~ %2g"
-
-#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/components/ProfileCreatorPage.qml:143
+#: /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:26
+#: /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
+#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UM2UpgradeSelectionMachineAction.qml:30
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
+#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UM2UpgradeSelectionMachineAction.qml:44
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/UpgradeFirmwareMachineAction.qml:30
-msgctxt "@title"
-msgid "Upgrade Firmware"
-msgstr "Aggiorna firmware"
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UpgradeFirmwareMachineAction.qml:41
-msgctxt "@label"
-msgid "Firmware is the piece of software running directly on your 3D printer. This firmware controls the step motors, regulates the temperature and ultimately makes your printer work."
-msgstr "Il firmware è la parte di software eseguita direttamente sulla stampante 3D. Questo firmware controlla i motori passo-passo, regola la temperatura e, in ultima analisi, consente il funzionamento della stampante."
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UpgradeFirmwareMachineAction.qml:51
-msgctxt "@label"
-msgid "The firmware shipping with new printers works, but new versions tend to have more features and improvements."
-msgstr "Il firmware inviato a corredo delle nuove stampanti funziona, tuttavia le nuove versioni tendono ad avere più funzioni ed ottimizzazioni."
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UpgradeFirmwareMachineAction.qml:65
-msgctxt "@action:button"
-msgid "Automatically upgrade Firmware"
-msgstr "Aggiorna automaticamente il firmware"
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UpgradeFirmwareMachineAction.qml:75
-msgctxt "@action:button"
-msgid "Upload custom Firmware"
-msgstr "Carica il firmware personalizzato"
-
-#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UpgradeFirmwareMachineAction.qml:87
-msgctxt "@title:window"
-msgid "Select custom firmware"
-msgstr "Seleziona il firmware personalizzato"
-
-#: /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"
@@ -2613,7 +2934,6 @@ msgid "Printer does not accept commands"
msgstr "La stampante non accetta comandi"
#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:133
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:197
msgctxt "@label:MonitorStatus"
msgid "In maintenance. Please check the printer"
msgstr "In manutenzione. Controllare la stampante"
@@ -2624,19 +2944,16 @@ msgid "Lost connection with the printer"
msgstr "Persa connessione con la stampante"
#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:146
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:187
msgctxt "@label:MonitorStatus"
msgid "Printing..."
msgstr "Stampa in corso..."
#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:149
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:189
msgctxt "@label:MonitorStatus"
msgid "Paused"
msgstr "In pausa"
#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:152
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:191
msgctxt "@label:MonitorStatus"
msgid "Preparing..."
msgstr "Preparazione in corso..."
@@ -2656,229 +2973,170 @@ 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/DiscardOrKeepProfileChangesDialog.qml:15
-msgctxt "@title:window"
-msgid "Discard or Keep changes"
-msgstr "Elimina o mantieni modifiche"
-
-#: /home/ruben/Projects/Cura/resources/qml/DiscardOrKeepProfileChangesDialog.qml:57
-msgctxt "@text:window"
-msgid ""
-"You have customized some profile settings.\n"
-"Would you like to keep or discard those settings?"
-msgstr ""
-"Sono state personalizzate alcune impostazioni del profilo.\n"
-"Mantenere o eliminare tali impostazioni?"
-
-#: /home/ruben/Projects/Cura/resources/qml/DiscardOrKeepProfileChangesDialog.qml:110
-msgctxt "@title:column"
-msgid "Profile settings"
-msgstr "Impostazioni profilo"
-
-#: /home/ruben/Projects/Cura/resources/qml/DiscardOrKeepProfileChangesDialog.qml:117
-msgctxt "@title:column"
-msgid "Default"
-msgstr "Valore predefinito"
-
-#: /home/ruben/Projects/Cura/resources/qml/DiscardOrKeepProfileChangesDialog.qml:124
-msgctxt "@title:column"
-msgid "Customized"
-msgstr "Valore personalizzato"
-
-#: /home/ruben/Projects/Cura/resources/qml/DiscardOrKeepProfileChangesDialog.qml:157
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:639
-msgctxt "@option:discardOrKeep"
-msgid "Always ask me this"
-msgstr "Chiedi sempre"
-
-#: /home/ruben/Projects/Cura/resources/qml/DiscardOrKeepProfileChangesDialog.qml:158
-msgctxt "@option:discardOrKeep"
-msgid "Discard and never ask again"
-msgstr "Elimina e non chiedere nuovamente"
-
-#: /home/ruben/Projects/Cura/resources/qml/DiscardOrKeepProfileChangesDialog.qml:159
-msgctxt "@option:discardOrKeep"
-msgid "Keep and never ask again"
-msgstr "Mantieni e non chiedere nuovamente"
-
-#: /home/ruben/Projects/Cura/resources/qml/DiscardOrKeepProfileChangesDialog.qml:196
-msgctxt "@action:button"
-msgid "Discard"
-msgstr "Elimina"
-
-#: /home/ruben/Projects/Cura/resources/qml/DiscardOrKeepProfileChangesDialog.qml:209
-msgctxt "@action:button"
-msgid "Keep"
-msgstr "Mantieni"
-
-#: /home/ruben/Projects/Cura/resources/qml/DiscardOrKeepProfileChangesDialog.qml:222
-msgctxt "@action:button"
-msgid "Create New Profile"
-msgstr "Crea nuovo profilo"
-
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:71
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsView.qml:73
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:102
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:103
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:127
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:137
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:147
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:157
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:207
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:209
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:224
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:258
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:275
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:293
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:302
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:316
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:323
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:334
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:347
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/Preferences/Materials/MaterialsView.qml:373
+#: /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:35
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:72
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:99
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:40
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:73
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:117
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:131
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:160
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:148
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:223
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:239
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:287
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:253
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:240
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:290
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:254
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:304
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:312
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:313
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:317
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:335
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/Materials/MaterialsPage.qml:343
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:347
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:353
msgctxt "@info:status Don't translate the XML tag !"
msgid "Successfully exported material to %1"
msgstr "Materiale esportato correttamente su %1"
@@ -2888,649 +3146,536 @@ msgctxt "@title:tab"
msgid "Setting Visibility"
msgstr "Impostazione visibilità"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/SettingVisibilityPage.qml:50
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/SettingVisibilityPage.qml:46
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:48
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:61
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:68
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:75
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:83
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:537
+#: /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:141
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:130
msgctxt "@label"
msgid "Interface"
msgstr "Interfaccia"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:152
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:141
msgctxt "@label"
msgid "Language:"
msgstr "Lingua:"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:220
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:208
msgctxt "@label"
msgid "Currency:"
msgstr "Valuta:"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:234
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:221
msgctxt "@label"
msgid "Theme:"
msgstr "Tema:"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:294
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:277
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:311
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:294
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:319
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:302
msgctxt "@option:check"
msgid "Slice automatically"
msgstr "Seziona automaticamente"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:333
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:316
msgctxt "@label"
msgid "Viewport behavior"
msgstr "Comportamento del riquadro di visualizzazione"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:341
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:324
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:350
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:333
msgctxt "@option:check"
msgid "Display overhang"
msgstr "Visualizza sbalzo"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:357
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:341
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:362
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:346
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:371
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:356
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:376
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:361
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:386
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:371
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:391
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:371
+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."
+
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:376
msgctxt "@action:button"
msgid "Zoom toward mouse direction"
msgstr "Zoom verso la direzione del mouse"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:401
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:402
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:406
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:407
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:415
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:416
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:420
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:421
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:432
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:433
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:441
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:442
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:449
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:450
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:454
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:455
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:470
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:465
+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:472
+msgctxt "@window:text"
+msgid "Camera rendering: "
+msgstr "Rendering fotocamera: "
+
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:483
+msgid "Perspective"
+msgstr "Prospettiva"
+
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:484
+msgid "Orthogonal"
+msgstr "Ortogonale"
+
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:515
msgctxt "@label"
msgid "Opening and saving files"
msgstr "Apertura e salvataggio file"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:477
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:522
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:482
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:527
msgctxt "@option:check"
msgid "Scale large models"
msgstr "Ridimensiona i modelli troppo grandi"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:492
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:537
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:497
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:542
msgctxt "@option:check"
msgid "Scale extremely small models"
msgstr "Ridimensiona i modelli eccessivamente piccoli"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:507
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:552
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:512
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:557
msgctxt "@option:check"
msgid "Select models when loaded"
msgstr "Selezionare i modelli dopo il caricamento"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:522
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:567
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:527
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:572
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:537
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:582
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:541
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:586
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:551
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:596
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:559
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:604
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:573
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:618
msgctxt "@option:openProject"
msgid "Always ask me this"
msgstr "Chiedi sempre"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:574
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:619
msgctxt "@option:openProject"
msgid "Always open as a project"
msgstr "Apri sempre come progetto"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:575
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:620
msgctxt "@option:openProject"
msgid "Always import models"
msgstr "Importa sempre i modelli"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:611
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:656
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:620
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:665
msgctxt "@label"
msgid "Profiles"
msgstr "Profili"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:625
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:670
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:640
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:684
+#: /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:685
msgctxt "@option:discardOrKeep"
msgid "Always discard changed settings"
msgstr "Elimina sempre le impostazioni modificate"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:641
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:686
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:675
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:720
msgctxt "@label"
msgid "Privacy"
msgstr "Privacy"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:683
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:727
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:688
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:732
msgctxt "@option:check"
msgid "Check for updates on start"
msgstr "Controlla aggiornamenti all’avvio"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:699
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:742
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:704
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:747
msgctxt "@option:check"
msgid "Send (anonymous) print information"
msgstr "Invia informazioni di stampa (anonime)"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:713
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:756
msgctxt "@action:button"
msgid "More information"
msgstr "Ulteriori informazioni"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:731
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:774
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/PrintSetupSelectorHeader.qml:27
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ProfileMenu.qml:23
msgctxt "@label"
msgid "Experimental"
msgstr "Sperimentale"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:738
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:781
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:743
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:786
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:542
+#: /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:55
-#: /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:134
msgctxt "@action:button"
msgid "Rename"
msgstr "Rinomina"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:147
-msgctxt "@label"
-msgid "Printer type:"
-msgstr "Tipo di stampante:"
-
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:156
-msgctxt "@label"
-msgid "Connection:"
-msgstr "Collegamento:"
-
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:162
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/OutputDeviceHeader.qml:47
-msgctxt "@info:status"
-msgid "The printer is not connected."
-msgstr "La stampante non è collegata."
-
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:168
-msgctxt "@label"
-msgid "State:"
-msgstr "Stato:"
-
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:181
-msgctxt "@label:MonitorStatus"
-msgid "Waiting for a printjob"
-msgstr "In attesa di un processo di stampa"
-
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:193
-msgctxt "@label:MonitorStatus"
-msgid "Waiting for someone to clear the build plate"
-msgstr "In attesa di qualcuno che cancelli il piano di stampa"
-
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:199
-msgctxt "@label:MonitorStatus"
-msgid "Aborting print..."
-msgstr "Interruzione stampa in corso..."
-
#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:36
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:546
+#: /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:89
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:105
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:181
msgctxt "@title:window"
msgid "Create Profile"
msgstr "Crea profilo"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:225
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:183
+msgctxt "@info"
+msgid "Please provide a name for this profile."
+msgstr "Indica un nome per questo profilo."
+
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:239
msgctxt "@title:window"
msgid "Duplicate Profile"
msgstr "Duplica profilo"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:256
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:270
msgctxt "@title:window"
msgid "Rename Profile"
msgstr "Rinomina profilo"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:269
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:283
msgctxt "@title:window"
msgid "Import Profile"
msgstr "Importa profilo"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:295
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:309
msgctxt "@title:window"
msgid "Export Profile"
msgstr "Esporta profilo"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:350
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:364
msgctxt "@label %1 is printer name"
msgid "Printer: %1"
msgstr "Stampante: %1"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:403
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:420
msgctxt "@label"
-msgid "Protected profiles"
-msgstr "Profili protetti"
+msgid "Default profiles"
+msgstr "Profili predefiniti"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:403
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:420
msgctxt "@label"
msgid "Custom profiles"
msgstr "Profili personalizzati"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:480
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:500
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:487
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:507
msgctxt "@action:button"
msgid "Discard current changes"
msgstr "Elimina le modifiche correnti"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:504
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:524
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:511
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:531
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:530
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:550
msgctxt "@title:tab"
msgid "Global Settings"
msgstr "Impostazioni globali"
-#: /home/ruben/Projects/Cura/resources/qml/AddMachineDialog.qml:18
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:946
-msgctxt "@title:window"
-msgid "Add Printer"
-msgstr "Aggiungi stampante"
-
-#: /home/ruben/Projects/Cura/resources/qml/AddMachineDialog.qml:194
-msgctxt "@label"
-msgid "Printer Name:"
-msgstr "Nome stampante:"
-
-#: /home/ruben/Projects/Cura/resources/qml/AddMachineDialog.qml:217
+#: /home/ruben/Projects/Cura/resources/qml/MainWindow/MainWindowHeader.qml:89
msgctxt "@action:button"
-msgid "Add Printer"
-msgstr "Aggiungi stampante"
+msgid "Marketplace"
+msgstr "Mercato"
-#: /home/ruben/Projects/Cura/resources/qml/JobSpecs.qml:84
+#: /home/ruben/Projects/Cura/resources/qml/MainWindow/ApplicationMenu.qml:27
+#: /home/ruben/Projects/Cura/resources/qml/Menus/FileMenu.qml:13
+msgctxt "@title:menu menubar:toplevel"
+msgid "&File"
+msgstr "&File"
+
+#: /home/ruben/Projects/Cura/resources/qml/MainWindow/ApplicationMenu.qml:31
+msgctxt "@title:menu menubar:toplevel"
+msgid "&Edit"
+msgstr "&Modifica"
+
+#: /home/ruben/Projects/Cura/resources/qml/MainWindow/ApplicationMenu.qml:48
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ViewMenu.qml:12
+msgctxt "@title:menu menubar:toplevel"
+msgid "&View"
+msgstr "&Visualizza"
+
+#: /home/ruben/Projects/Cura/resources/qml/MainWindow/ApplicationMenu.qml:50
+#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:13
+msgctxt "@title:menu menubar:toplevel"
+msgid "&Settings"
+msgstr "&Impostazioni"
+
+#: /home/ruben/Projects/Cura/resources/qml/MainWindow/ApplicationMenu.qml:55
+msgctxt "@title:menu menubar:toplevel"
+msgid "E&xtensions"
+msgstr "Es&tensioni"
+
+#: /home/ruben/Projects/Cura/resources/qml/MainWindow/ApplicationMenu.qml:89
+msgctxt "@title:menu menubar:toplevel"
+msgid "P&references"
+msgstr "P&referenze"
+
+#: /home/ruben/Projects/Cura/resources/qml/MainWindow/ApplicationMenu.qml:97
+msgctxt "@title:menu menubar:toplevel"
+msgid "&Help"
+msgstr "&Help"
+
+#: /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: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."
+
+#: /home/ruben/Projects/Cura/resources/qml/JobSpecs.qml:88
msgctxt "@text Print job name"
msgid "Untitled"
msgstr "Senza titolo"
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:15
-msgctxt "@title:window"
-msgid "About Cura"
-msgstr "Informazioni su Cura"
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:43
-msgctxt "@label"
-msgid "version: %1"
-msgstr "versione: %1"
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:56
-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/AboutDialog.qml:69
-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 ""
-"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/AboutDialog.qml:118
-msgctxt "@label"
-msgid "Graphical user interface"
-msgstr "Interfaccia grafica utente"
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:119
-msgctxt "@label"
-msgid "Application framework"
-msgstr "Struttura applicazione"
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:120
-msgctxt "@label"
-msgid "G-code generator"
-msgstr "Generatore codice G"
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:121
-msgctxt "@label"
-msgid "Interprocess communication library"
-msgstr "Libreria di comunicazione intra-processo"
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:123
-msgctxt "@label"
-msgid "Programming language"
-msgstr "Lingua di programmazione"
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:124
-msgctxt "@label"
-msgid "GUI framework"
-msgstr "Struttura GUI"
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:125
-msgctxt "@label"
-msgid "GUI framework bindings"
-msgstr "Vincoli struttura GUI"
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:126
-msgctxt "@label"
-msgid "C/C++ Binding library"
-msgstr "Libreria vincoli C/C++"
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:127
-msgctxt "@label"
-msgid "Data interchange format"
-msgstr "Formato scambio dati"
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:128
-msgctxt "@label"
-msgid "Support library for scientific computing"
-msgstr "Libreria di supporto per calcolo scientifico"
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:129
-msgctxt "@label"
-msgid "Support library for faster math"
-msgstr "Libreria di supporto per calcolo rapido"
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:130
-msgctxt "@label"
-msgid "Support library for handling STL files"
-msgstr "Libreria di supporto per gestione file STL"
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:131
-msgctxt "@label"
-msgid "Support library for handling 3MF files"
-msgstr "Libreria di supporto per gestione file 3MF"
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:132
-msgctxt "@label"
-msgid "Serial communication library"
-msgstr "Libreria di comunicazione seriale"
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:133
-msgctxt "@label"
-msgid "ZeroConf discovery library"
-msgstr "Libreria scoperta ZeroConf"
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:134
-msgctxt "@label"
-msgid "Polygon clipping library"
-msgstr "Libreria ritaglio poligono"
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:135
-msgctxt "@Label"
-msgid "Python HTTP library"
-msgstr "Libreria Python HTTP"
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:137
-msgctxt "@label"
-msgid "Font"
-msgstr "Font"
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:138
-msgctxt "@label"
-msgid "SVG icons"
-msgstr "Icone SVG"
-
-#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:139
-msgctxt "@label"
-msgid "Linux cross-distribution application deployment"
-msgstr "Apertura applicazione distribuzione incrociata Linux"
-
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:42
-msgctxt "@label"
-msgid "Profile:"
-msgstr "Profilo:"
-
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:103
-msgctxt "@tooltip"
-msgid ""
-"Some setting/override values are different from the values stored in the profile.\n"
-"\n"
-"Click to open the profile manager."
-msgstr ""
-"Alcuni valori di impostazione/esclusione sono diversi dai valori memorizzati nel profilo.\n"
-"\n"
-"Fare clic per aprire la gestione profili."
-
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:199
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:68
msgctxt "@label:textbox"
-msgid "Search..."
-msgstr "Ricerca..."
+msgid "search settings"
+msgstr "impostazioni ricerca"
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:544
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:466
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:553
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:475
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:590
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:512
msgctxt "@action:menu"
msgid "Hide this setting"
msgstr "Nascondi questa impostazione"
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:608
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:525
msgctxt "@action:menu"
msgid "Don't show this setting"
msgstr "Nascondi questa impostazione"
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:612
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:529
msgctxt "@action:menu"
msgid "Keep this setting visible"
msgstr "Mantieni visibile questa impostazione"
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:636
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:416
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:548
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:434
msgctxt "@action:menu"
msgid "Configure setting visibility..."
msgstr "Configura visibilità delle impostazioni..."
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:643
-msgctxt "@action:inmenu"
-msgid "Collapse All"
-msgstr "Comprimi tutto"
-
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:648
-msgctxt "@action:inmenu"
-msgid "Expand All"
-msgstr "Espandi tutto"
-
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingCategory.qml:249
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingCategory.qml:237
msgctxt "@label"
msgid ""
"Some hidden settings use values different from their normal calculated value.\n"
@@ -3541,27 +3686,32 @@ msgstr ""
"\n"
"Fare clic per rendere visibili queste impostazioni."
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:61
+#: /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:66
+#: /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:154
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:186
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:157
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:190
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:188
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:228
msgctxt "@label"
msgid ""
"This setting has a value that is different from the profile.\n"
@@ -3572,7 +3722,7 @@ msgstr ""
"\n"
"Fare clic per ripristinare il valore del profilo."
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:286
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:322
msgctxt "@label"
msgid ""
"This setting is normally calculated, but it currently has an absolute value set.\n"
@@ -3583,116 +3733,210 @@ msgstr ""
"\n"
"Fare clic per ripristinare il valore calcolato."
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ManualPrinterControl.qml:129
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/PrintSetupSelectorContents.qml:144
+msgctxt "@button"
+msgid "Recommended"
+msgstr "Consigliata"
+
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/PrintSetupSelectorContents.qml:158
+msgctxt "@button"
+msgid "Custom"
+msgstr "Personalizzata"
+
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Recommended/RecommendedInfillDensitySelector.qml:193
+msgctxt "@label"
+msgid "Gradual infill"
+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:30
+msgctxt "@label"
+msgid "Support"
+msgstr "Supporto"
+
+#: /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/RecommendedAdhesionSelector.qml:29
+msgctxt "@label"
+msgid "Adhesion"
+msgstr "Adesione"
+
+#: /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
+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 "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."
+
+#: /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 "Inserita"
+
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/PrintSetupSelectorHeader.qml:14
+msgctxt "@label:Should be short"
+msgid "Off"
+msgstr "Disinserita"
+
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Custom/GlobalProfileSelector.qml:27
+msgctxt "@label"
+msgid "Profile"
+msgstr "Profilo"
+
+#: /home/ruben/Projects/Cura/resources/qml/PrintSetupSelector/Custom/GlobalProfileSelector.qml:94
+msgctxt "@tooltip"
+msgid ""
+"Some setting/override values are different from the values stored in the profile.\n"
+"\n"
+"Click to open the profile manager."
+msgstr ""
+"Alcuni valori di impostazione/esclusione sono diversi dai valori memorizzati nel profilo.\n"
+"\n"
+"Fare clic per aprire la gestione profili."
+
+#: /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 "Impostazione di stampa disabilitata. Il file G-code non può essere modificato."
+
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ManualPrinterControl.qml:52
msgctxt "@label"
msgid "Printer control"
msgstr "Comando stampante"
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ManualPrinterControl.qml:144
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ManualPrinterControl.qml:67
msgctxt "@label"
msgid "Jog Position"
msgstr "Posizione Jog"
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ManualPrinterControl.qml:162
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ManualPrinterControl.qml:85
msgctxt "@label"
msgid "X/Y"
msgstr "X/Y"
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ManualPrinterControl.qml:269
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ManualPrinterControl.qml:192
msgctxt "@label"
msgid "Z"
msgstr "Z"
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ManualPrinterControl.qml:334
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ManualPrinterControl.qml:257
msgctxt "@label"
msgid "Jog Distance"
msgstr "Distanza Jog"
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ManualPrinterControl.qml:443
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ManualPrinterControl.qml:301
msgctxt "@label"
msgid "Send G-code"
msgstr "Invia codice G"
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ManualPrinterControl.qml:506
+#: /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:36
-#: /home/ruben/Projects/Cura/resources/qml/SidebarHeader.qml:272
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:38
msgctxt "@label"
msgid "Extruder"
msgstr "Estrusore"
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:66
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:68
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:98
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:100
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:172
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:174
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:336
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/HeatedBedBox.qml:331
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:338
+#: /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:339
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/HeatedBedBox.qml:334
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:341
+#: /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:365
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:367
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:401
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:403
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:433
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:435
msgctxt "@tooltip"
msgid "The material in this extruder."
msgstr "Il materiale di questo estrusore."
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:465
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/ExtruderBox.qml:467
msgctxt "@tooltip"
msgid "The nozzle inserted in this extruder."
msgstr "L’ugello inserito in questo estrusore."
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/HeatedBedBox.qml:25
-#: /home/ruben/Projects/Cura/resources/qml/SidebarHeader.qml:493
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/OutputDeviceHeader.qml:55
+msgctxt "@info:status"
+msgid "The printer is not connected."
+msgstr "La stampante non è collegata."
+
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/HeatedBedBox.qml:26
msgctxt "@label"
msgid "Build plate"
msgstr "Piano di stampa"
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/HeatedBedBox.qml:55
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/HeatedBedBox.qml:56
msgctxt "@tooltip"
msgid "The target temperature of the heated bed. The bed will heat up or cool down towards this temperature. If this is 0, the bed heating is turned off."
msgstr "La temperatura target del piano riscaldato. Il piano verrà riscaldato o raffreddato a questa temperatura. Se è 0, il riscaldamento del piano viene disattivato."
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/HeatedBedBox.qml:87
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/HeatedBedBox.qml:88
msgctxt "@tooltip"
msgid "The current temperature of the heated bed."
msgstr "La temperatura corrente del piano riscaldato."
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/HeatedBedBox.qml:160
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/HeatedBedBox.qml:161
msgctxt "@tooltip of temperature input"
msgid "The temperature to pre-heat the bed to."
msgstr "La temperatura di preriscaldo del piano."
-#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/HeatedBedBox.qml:360
+#: /home/ruben/Projects/Cura/resources/qml/PrinterOutput/HeatedBedBox.qml:361
msgctxt "@tooltip of pre-heat"
msgid "Heat the bed in advance before printing. You can continue adjusting your print while it is heating, and you won't have to wait for the bed to heat up when you're ready to print."
msgstr "Riscalda il piano prima della stampa. È possibile continuare a regolare la stampa durante il riscaldamento e non è necessario attendere il riscaldamento del piano quando si è pronti per la stampa."
@@ -3702,16 +3946,11 @@ msgctxt "@label:category menu label"
msgid "Material"
msgstr "Materiale"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/MaterialMenu.qml:37
+#: /home/ruben/Projects/Cura/resources/qml/Menus/MaterialMenu.qml:42
msgctxt "@label:category menu label"
msgid "Favorites"
msgstr "Preferiti"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/MaterialMenu.qml:61
-msgctxt "@label:category menu label"
-msgid "Generic"
-msgstr "Generale"
-
#: /home/ruben/Projects/Cura/resources/qml/Menus/PrinterMenu.qml:25
msgctxt "@label:category menu label"
msgid "Network enabled printers"
@@ -3722,17 +3961,62 @@ msgctxt "@label:category menu label"
msgid "Local printers"
msgstr "Stampanti locali"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/ViewMenu.qml:12
-msgctxt "@title:menu menubar:toplevel"
-msgid "&View"
-msgstr "&Visualizza"
+#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:15
+msgctxt "@title:menu menubar:settings"
+msgid "&Printer"
+msgstr "S&tampante"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/ViewMenu.qml:39
+#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:32
+msgctxt "@title:menu"
+msgid "&Material"
+msgstr "Ma&teriale"
+
+#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:41
+msgctxt "@action:inmenu"
+msgid "Set as Active Extruder"
+msgstr "Imposta come estrusore attivo"
+
+#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:47
+msgctxt "@action:inmenu"
+msgid "Enable Extruder"
+msgstr "Abilita estrusore"
+
+#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:54
+msgctxt "@action:inmenu"
+msgid "Disable Extruder"
+msgstr "Disabilita estrusore"
+
+#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:68
+msgctxt "@title:menu"
+msgid "&Build plate"
+msgstr "&Piano di stampa"
+
+#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingsMenu.qml:71
+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:54
+#: /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"
@@ -3742,16 +4026,31 @@ msgctxt "@action:inmenu"
msgid "Visible Settings"
msgstr "Impostazioni visibili"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingVisibilityPresetsMenu.qml:43
+#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingVisibilityPresetsMenu.qml:42
msgctxt "@action:inmenu"
msgid "Show All Settings"
msgstr "Mostra tutte le impostazioni"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingVisibilityPresetsMenu.qml:54
+#: /home/ruben/Projects/Cura/resources/qml/Menus/SettingVisibilityPresetsMenu.qml:53
msgctxt "@action:inmenu"
msgid "Manage Setting Visibility..."
msgstr "Gestisci Impostazione visibilità..."
+#: /home/ruben/Projects/Cura/resources/qml/Menus/FileMenu.qml:32
+msgctxt "@title:menu menubar:file"
+msgid "&Save..."
+msgstr "&Salva..."
+
+#: /home/ruben/Projects/Cura/resources/qml/Menus/FileMenu.qml:53
+msgctxt "@title:menu menubar:file"
+msgid "&Export..."
+msgstr "&Esporta..."
+
+#: /home/ruben/Projects/Cura/resources/qml/Menus/FileMenu.qml:64
+msgctxt "@action:inmenu menubar:file"
+msgid "Export Selection..."
+msgstr "Esporta selezione..."
+
#: /home/ruben/Projects/Cura/resources/qml/Menus/ContextMenu.qml:27
msgctxt "@label"
msgid "Print Selected Model With:"
@@ -3771,634 +4070,509 @@ msgctxt "@label"
msgid "Number of Copies"
msgstr "Numero di copie"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/ConfigurationListView.qml:33
-msgctxt "@label:header configurations"
-msgid "Available configurations"
-msgstr "Configurazioni disponibili"
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/AutoConfiguration.qml:18
+msgctxt "@header"
+msgid "Configurations"
+msgstr "Configurazioni"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/PrintCoreConfiguration.qml:28
-msgctxt "@label:extruder label"
-msgid "Extruder"
-msgstr "Estrusore"
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/ConfigurationMenu.qml:110
+msgctxt "@label"
+msgid "Select configuration"
+msgstr "Seleziona configurazione"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/SyncButton.qml:16
-msgctxt "@label:extruder label"
-msgid "Yes"
-msgstr "Sì"
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/ConfigurationMenu.qml:221
+msgctxt "@label"
+msgid "Configurations"
+msgstr "Configurazioni"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/SyncButton.qml:16
-msgctxt "@label:extruder label"
-msgid "No"
-msgstr "No"
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/ConfigurationListView.qml:57
+msgctxt "@label"
+msgid "Loading available configurations from the printer..."
+msgstr "Caricamento in corso configurazioni disponibili dalla stampante..."
-#: /home/ruben/Projects/Cura/resources/qml/Menus/RecentFilesMenu.qml:13
+#: /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 "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 "Personalizzata"
+
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/CustomConfiguration.qml:61
+msgctxt "@label"
+msgid "Printer"
+msgstr "Stampante"
+
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/CustomConfiguration.qml:213
+msgctxt "@label"
+msgid "Enabled"
+msgstr "Abilitato"
+
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/CustomConfiguration.qml:250
+msgctxt "@label"
+msgid "Material"
+msgstr "Materiale"
+
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ConfigurationMenu/CustomConfiguration.qml:375
+msgctxt "@label"
+msgid "Use glue for better adhesion with this material combination."
+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 "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 "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/PrepareSidebar.qml:150
-msgctxt "@label:listbox"
-msgid "Print Setup"
-msgstr "Impostazione di stampa"
-
-#: /home/ruben/Projects/Cura/resources/qml/PrepareSidebar.qml:150
-msgctxt "@label:listbox"
-msgid ""
-"Print Setup disabled\n"
-"G-code files cannot be modified"
-msgstr ""
-"Impostazione di stampa disabilitata\n"
-"I file codice G non possono essere modificati"
-
-#: /home/ruben/Projects/Cura/resources/qml/PrepareSidebar.qml:359
-msgctxt "@tooltip"
-msgid "Time specification"
-msgstr "Indicazioni di tempo"
-
-#: /home/ruben/Projects/Cura/resources/qml/PrepareSidebar.qml:577
-msgctxt "@tooltip"
-msgid "Recommended Print Setup
Print with the recommended settings for the selected printer, material and quality."
-msgstr "Impostazione di stampa consigliata
Stampa con le impostazioni consigliate per la stampante, il materiale e la qualità selezionati."
-
-#: /home/ruben/Projects/Cura/resources/qml/PrepareSidebar.qml:582
-msgctxt "@tooltip"
-msgid "Custom Print Setup
Print with finegrained control over every last bit of the slicing process."
-msgstr "Impostazione di stampa personalizzata
Stampa con il controllo grana fine su ogni sezione finale del processo di sezionamento."
-
-#: /home/ruben/Projects/Cura/resources/qml/PrintMonitor.qml:106
+#: /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:114
+#: /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:122
+#: /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:130
+#: /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/Actions.qml:78
+#: /home/ruben/Projects/Cura/resources/qml/ViewsSelector.qml:50
+msgctxt "@label"
+msgid "View type"
+msgstr "Visualizza tipo"
+
+#: /home/ruben/Projects/Cura/resources/qml/ObjectSelector.qml:59
+msgctxt "@label"
+msgid "Object list"
+msgstr "Elenco oggetti"
+
+#: /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 "Account Ultimaker"
+
+#: /home/ruben/Projects/Cura/resources/qml/Account/UserOperations.qml:42
+msgctxt "@button"
+msgid "Sign out"
+msgstr "Esci"
+
+#: /home/ruben/Projects/Cura/resources/qml/Account/AccountWidget.qml:24
+msgctxt "@action:button"
+msgid "Sign in"
+msgstr "Accedi"
+
+#: /home/ruben/Projects/Cura/resources/qml/Account/GeneralOperations.qml:40
+msgctxt "@label"
+msgid "The next generation 3D printing workflow"
+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 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 "Crea account"
+
+#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/OutputProcessWidget.qml:59
+msgctxt "@label"
+msgid "No time estimation available"
+msgstr "Nessuna stima di tempo disponibile"
+
+#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/OutputProcessWidget.qml:77
+msgctxt "@label"
+msgid "No cost estimation available"
+msgstr "Nessuna stima di costo disponibile"
+
+#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/OutputProcessWidget.qml:127
+msgctxt "@button"
+msgid "Preview"
+msgstr "Anteprima"
+
+#: /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:67
+msgctxt "@label:PrintjobStatus"
+msgid "Unable to slice"
+msgstr "Sezionamento impossibile"
+
+#: /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 "Sezionamento"
+
+#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/SliceProcessWidget.qml:104
+msgctxt "@label"
+msgid "Start the slicing process"
+msgstr "Avvia il processo di sezionamento"
+
+#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/SliceProcessWidget.qml:118
+msgctxt "@button"
+msgid "Cancel"
+msgstr "Annulla"
+
+#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/PrintJobInformation.qml:31
+msgctxt "@label"
+msgid "Time estimation"
+msgstr "Stima del tempo"
+
+#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/PrintJobInformation.qml:114
+msgctxt "@label"
+msgid "Material estimation"
+msgstr "Stima del materiale"
+
+#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/PrintJobInformation.qml:164
+msgctxt "@label m for meter"
+msgid "%1m"
+msgstr "%1m"
+
+#: /home/ruben/Projects/Cura/resources/qml/ActionPanel/PrintJobInformation.qml:165
+msgctxt "@label g for grams"
+msgid "%1g"
+msgstr "%1g"
+
+#: /home/ruben/Projects/Cura/resources/qml/PrinterSelector/MachineSelectorList.qml:19
+msgctxt "@label"
+msgid "Connected printers"
+msgstr "Stampanti collegate"
+
+#: /home/ruben/Projects/Cura/resources/qml/PrinterSelector/MachineSelectorList.qml:19
+msgctxt "@label"
+msgid "Preset printers"
+msgstr "Stampanti preimpostate"
+
+#: /home/ruben/Projects/Cura/resources/qml/PrinterSelector/MachineSelector.qml:166
+msgctxt "@button"
+msgid "Add printer"
+msgstr "Aggiungi stampante"
+
+#: /home/ruben/Projects/Cura/resources/qml/PrinterSelector/MachineSelector.qml:182
+msgctxt "@button"
+msgid "Manage printers"
+msgstr "Gestione stampanti"
+
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:81
+msgctxt "@action:inmenu"
+msgid "Show Online Troubleshooting Guide"
+msgstr "Mostra la Guida ricerca e riparazione dei guasti online"
+
+#: /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:85
+#: /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:95
+#: /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:105
+#: /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:113
+#: /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:120
+#: /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:127
+#: /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:134
+#: /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:141
+#: /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:148
+#: /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:155
+#: /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:161
+#: /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:168
+#: /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:176
+#: /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:184
+#: /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:196
+#: /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:202
+#: /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:209
+#: /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:217
+#: /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:225
+#: /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:232
+#: /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:242
+#: /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:251
+#: /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:260
+#: /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:268
+#: /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:274
+#: /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:294
+#: /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:304
+#: /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:314
+#: /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:321
+#: /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:331
+#: /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:341
+#: /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:350
+#: /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:357
+#: /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:365
+#: /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:372
+#: /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:379
+#: /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:386
+#: /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:394
+#: /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:401
-msgctxt "@action:inmenu menubar:help"
-msgid "Show Engine &Log..."
-msgstr "Mostra &log motore..."
-
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:409
+#: /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:423
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:441
msgctxt "@action:menu"
-msgid "Browse packages..."
-msgstr "Sfoglia i pacchetti..."
+msgid "&Marketplace"
+msgstr "&Mercato"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:430
-msgctxt "@action:inmenu menubar:view"
-msgid "Expand/Collapse Sidebar"
-msgstr "Espandi/Riduci barra laterale"
-
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:27
-msgctxt "@label:PrintjobStatus"
-msgid "Please load a 3D model"
-msgstr "Caricare un modello 3D"
-
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:37
-msgctxt "@label:PrintjobStatus"
-msgid "Ready to slice"
-msgstr "Pronto per il sezionamento"
-
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:39
-msgctxt "@label:PrintjobStatus"
-msgid "Slicing..."
-msgstr "Sezionamento in corso..."
-
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:41
-msgctxt "@label:PrintjobStatus %1 is target operation"
-msgid "Ready to %1"
-msgstr "Pronto a %1"
-
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:43
-msgctxt "@label:PrintjobStatus"
-msgid "Unable to Slice"
-msgstr "Sezionamento impossibile"
-
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:45
-msgctxt "@label:PrintjobStatus"
-msgid "Slicing unavailable"
-msgstr "Sezionamento non disponibile"
-
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:172
-msgctxt "@info:tooltip"
-msgid "Slice current printjob"
-msgstr "Seziona processo di stampa corrente"
-
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:172
-msgctxt "@info:tooltip"
-msgid "Cancel slicing process"
-msgstr "Annulla processo di sezionamento"
-
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:184
-msgctxt "@label:Printjob"
-msgid "Prepare"
-msgstr "Prepara"
-
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:184
-msgctxt "@label:Printjob"
-msgid "Cancel"
-msgstr "Annulla"
-
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:320
-msgctxt "@info:tooltip"
-msgid "Select the active output device"
-msgstr "Seleziona l'unità di uscita attiva"
-
-#: /home/ruben/Projects/Cura/resources/qml/OpenFilesIncludingProjectsDialog.qml:19
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:760
-msgctxt "@title:window"
-msgid "Open file(s)"
-msgstr "Apri file"
-
-#: /home/ruben/Projects/Cura/resources/qml/OpenFilesIncludingProjectsDialog.qml:64
-msgctxt "@text:window"
-msgid "We have found one or more project file(s) within the files you have selected. You can open only one project file at a time. We suggest to only import models from those files. Would you like to proceed?"
-msgstr "Rilevata la presenza di uno o più file progetto tra i file selezionati. È possibile aprire solo un file progetto alla volta. Si suggerisce di importare i modelli solo da tali file. Vuoi procedere?"
-
-#: /home/ruben/Projects/Cura/resources/qml/OpenFilesIncludingProjectsDialog.qml:99
-msgctxt "@action:button"
-msgid "Import all as models"
-msgstr "Importa tutto come modelli"
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:19
+#: /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:104
-msgctxt "@title:menu menubar:toplevel"
-msgid "&File"
-msgstr "&File"
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:120
-msgctxt "@title:menu menubar:file"
-msgid "&Save..."
-msgstr "&Salva..."
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:141
-msgctxt "@title:menu menubar:file"
-msgid "&Export..."
-msgstr "&Esporta..."
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:151
-msgctxt "@action:inmenu menubar:file"
-msgid "Export Selection..."
-msgstr "Esporta selezione..."
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:168
-msgctxt "@title:menu menubar:toplevel"
-msgid "&Edit"
-msgstr "&Modifica"
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:185
-msgctxt "@title:menu"
-msgid "&View"
-msgstr "&Visualizza"
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:190
-msgctxt "@title:menu"
-msgid "&Settings"
-msgstr "&Impostazioni"
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:192
-msgctxt "@title:menu menubar:settings"
-msgid "&Printer"
-msgstr "S&tampante"
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:201
-msgctxt "@title:menu"
-msgid "&Material"
-msgstr "Ma&teriale"
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:210
-msgctxt "@action:inmenu"
-msgid "Set as Active Extruder"
-msgstr "Imposta come estrusore attivo"
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:216
-#: /home/ruben/Projects/Cura/resources/qml/SidebarHeader.qml:188
-msgctxt "@action:inmenu"
-msgid "Enable Extruder"
-msgstr "Abilita estrusore"
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:223
-#: /home/ruben/Projects/Cura/resources/qml/SidebarHeader.qml:194
-msgctxt "@action:inmenu"
-msgid "Disable Extruder"
-msgstr "Disabilita estrusore"
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:235
-msgctxt "@title:menu"
-msgid "&Build plate"
-msgstr "&Piano di stampa"
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:236
-msgctxt "@title:settings"
-msgid "&Profile"
-msgstr "&Profilo"
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:246
-msgctxt "@title:menu menubar:toplevel"
-msgid "E&xtensions"
-msgstr "Es&tensioni"
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:280
-msgctxt "@title:menu menubar:toplevel"
-msgid "&Toolbox"
-msgstr "&Casella degli strumenti"
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:287
-msgctxt "@title:menu menubar:toplevel"
-msgid "P&references"
-msgstr "P&referenze"
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:295
-msgctxt "@title:menu menubar:toplevel"
-msgid "&Help"
-msgstr "&Help"
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:341
+#: /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:370
-msgctxt "@action:button"
-msgid "Open File"
-msgstr "Apri file"
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:540
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:413
msgctxt "@title:tab"
msgid "Settings"
msgstr "Impostazioni"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:586
-msgctxt "@title:window"
-msgid "New project"
-msgstr "Nuovo progetto"
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:587
-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."
-
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:715
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:539
msgctxt "@title:window"
msgid "Closing Cura"
msgstr "Chiusura di Cura"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:716
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:728
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:540
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:552
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:861
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:590
+#: /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:691
msgctxt "@window:title"
msgid "Install Package"
msgstr "Installa il pacchetto"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:868
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:699
msgctxt "@title:window"
msgid "Open File(s)"
msgstr "Apri file"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:871
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:702
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/WorkspaceSummaryDialog.qml:14
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:805
msgctxt "@title:window"
-msgid "Save Project"
-msgstr "Salva progetto"
+msgid "Add Printer"
+msgstr "Aggiungi stampante"
-#: /home/ruben/Projects/Cura/resources/qml/WorkspaceSummaryDialog.qml:120
-msgctxt "@action:label"
-msgid ""
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/WorkspaceSummaryDialog.qml:137
-msgctxt "@action:label"
-msgid "Build plate"
-msgstr "Piano di stampa"
-
-#: /home/ruben/Projects/Cura/resources/qml/WorkspaceSummaryDialog.qml:169
-msgctxt "@action:label"
-msgid "Extruder %1"
-msgstr "Estrusore %1"
-
-#: /home/ruben/Projects/Cura/resources/qml/WorkspaceSummaryDialog.qml:179
-msgctxt "@action:label"
-msgid "%1 & material"
-msgstr "%1 & materiale"
-
-#: /home/ruben/Projects/Cura/resources/qml/WorkspaceSummaryDialog.qml:268
-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/WorkspaceSummaryDialog.qml:287
-msgctxt "@action:button"
-msgid "Save"
-msgstr "Salva"
-
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:192
-msgctxt "@label"
-msgid "Layer Height"
-msgstr "Altezza dello strato"
-
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:277
-msgctxt "@tooltip"
-msgid "This quality profile is not available for you 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à"
-
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:450
-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/SidebarSimple.qml:467
-msgctxt "@label"
-msgid "Print Speed"
-msgstr "Velocità di stampa"
-
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:479
-msgctxt "@label"
-msgid "Slower"
-msgstr "Più lenta"
-
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:490
-msgctxt "@label"
-msgid "Faster"
-msgstr "Più veloce"
-
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:518
-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/SidebarSimple.qml:541
-msgctxt "@label"
-msgid "Infill"
-msgstr "Riempimento"
-
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:777
-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/SidebarSimple.qml:789
-msgctxt "@label"
-msgid "Enable gradual"
-msgstr "Consenti variazione graduale"
-
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:856
-msgctxt "@label"
-msgid "Generate Support"
-msgstr "Generazione supporto"
-
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:890
-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/SidebarSimple.qml:962
-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/SidebarSimple.qml:985
-msgctxt "@label"
-msgid "Build Plate Adhesion"
-msgstr "Adesione piano di stampa"
-
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:1040
-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/SidebarSimple.qml:1080
-msgctxt "@label"
-msgid "Need help improving your prints? Read the Ultimaker Troubleshooting Guides"
-msgstr "Serve aiuto per migliorare le tue stampe? Leggi la Guida alla ricerca e riparazione guasti Ultimaker"
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:813
+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"
@@ -4407,75 +4581,483 @@ msgid_plural "Print Selected Models with %1"
msgstr[0] "Stampa modello selezionato con %1"
msgstr[1] "Stampa modelli selezionati con %1"
-#: /home/ruben/Projects/Cura/resources/qml/AskOpenAsProjectOrModelsDialog.qml:20
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/DiscardOrKeepProfileChangesDialog.qml:15
+msgctxt "@title:window"
+msgid "Discard or Keep changes"
+msgstr "Elimina o mantieni modifiche"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/DiscardOrKeepProfileChangesDialog.qml:57
+msgctxt "@text:window"
+msgid ""
+"You have customized some profile settings.\n"
+"Would you like to keep or discard those settings?"
+msgstr ""
+"Sono state personalizzate alcune impostazioni del profilo.\n"
+"Mantenere o eliminare tali impostazioni?"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/DiscardOrKeepProfileChangesDialog.qml:110
+msgctxt "@title:column"
+msgid "Profile settings"
+msgstr "Impostazioni profilo"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/DiscardOrKeepProfileChangesDialog.qml:117
+msgctxt "@title:column"
+msgid "Default"
+msgstr "Valore predefinito"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/DiscardOrKeepProfileChangesDialog.qml:124
+msgctxt "@title:column"
+msgid "Customized"
+msgstr "Valore personalizzato"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/DiscardOrKeepProfileChangesDialog.qml:158
+msgctxt "@option:discardOrKeep"
+msgid "Discard and never ask again"
+msgstr "Elimina e non chiedere nuovamente"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/DiscardOrKeepProfileChangesDialog.qml:159
+msgctxt "@option:discardOrKeep"
+msgid "Keep and never ask again"
+msgstr "Mantieni e non chiedere nuovamente"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/DiscardOrKeepProfileChangesDialog.qml:196
+msgctxt "@action:button"
+msgid "Discard"
+msgstr "Elimina"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/DiscardOrKeepProfileChangesDialog.qml:209
+msgctxt "@action:button"
+msgid "Keep"
+msgstr "Mantieni"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/DiscardOrKeepProfileChangesDialog.qml:222
+msgctxt "@action:button"
+msgid "Create New Profile"
+msgstr "Crea nuovo profilo"
+
+#: /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
+msgctxt "@label"
+msgid "version: %1"
+msgstr "versione: %1"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:71
+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
+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 ""
+"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
+msgctxt "@label"
+msgid "Graphical user interface"
+msgstr "Interfaccia grafica utente"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:135
+msgctxt "@label"
+msgid "Application framework"
+msgstr "Struttura applicazione"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:136
+msgctxt "@label"
+msgid "G-code generator"
+msgstr "Generatore codice G"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:137
+msgctxt "@label"
+msgid "Interprocess communication library"
+msgstr "Libreria di comunicazione intra-processo"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:139
+msgctxt "@label"
+msgid "Programming language"
+msgstr "Lingua di programmazione"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:140
+msgctxt "@label"
+msgid "GUI framework"
+msgstr "Struttura GUI"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:141
+msgctxt "@label"
+msgid "GUI framework bindings"
+msgstr "Vincoli struttura GUI"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:142
+msgctxt "@label"
+msgid "C/C++ Binding library"
+msgstr "Libreria vincoli C/C++"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:143
+msgctxt "@label"
+msgid "Data interchange format"
+msgstr "Formato scambio dati"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:144
+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
+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
+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
+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
+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
+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
+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
+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
+msgctxt "@label"
+msgid "Serial communication library"
+msgstr "Libreria di comunicazione seriale"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:153
+msgctxt "@label"
+msgid "ZeroConf discovery library"
+msgstr "Libreria scoperta ZeroConf"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:154
+msgctxt "@label"
+msgid "Polygon clipping library"
+msgstr "Libreria ritaglio poligono"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:155
+msgctxt "@Label"
+msgid "Python HTTP library"
+msgstr "Libreria Python HTTP"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:157
+msgctxt "@label"
+msgid "Font"
+msgstr "Font"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:158
+msgctxt "@label"
+msgid "SVG icons"
+msgstr "Icone SVG"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AboutDialog.qml:159
+msgctxt "@label"
+msgid "Linux cross-distribution application deployment"
+msgstr "Apertura applicazione distribuzione incrociata Linux"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/OpenFilesIncludingProjectsDialog.qml:64
+msgctxt "@text:window"
+msgid "We have found one or more project file(s) within the files you have selected. You can open only one project file at a time. We suggest to only import models from those files. Would you like to proceed?"
+msgstr "Rilevata la presenza di uno o più file progetto tra i file selezionati. È possibile aprire solo un file progetto alla volta. Si suggerisce di importare i modelli solo da tali file. Vuoi procedere?"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/OpenFilesIncludingProjectsDialog.qml:99
+msgctxt "@action:button"
+msgid "Import all as models"
+msgstr "Importa tutto come modelli"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:15
+msgctxt "@title:window"
+msgid "Save Project"
+msgstr "Salva progetto"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:149
+msgctxt "@action:label"
+msgid "Build plate"
+msgstr "Piano di stampa"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:183
+msgctxt "@action:label"
+msgid "Extruder %1"
+msgstr "Estrusore %1"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:198
+msgctxt "@action:label"
+msgid "%1 & material"
+msgstr "%1 & materiale"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:200
+msgctxt "@action:label"
+msgid "Material"
+msgstr "Materiale"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/WorkspaceSummaryDialog.qml:272
+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:291
+msgctxt "@action:button"
+msgid "Save"
+msgstr "Salva"
+
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AskOpenAsProjectOrModelsDialog.qml:20
msgctxt "@title:window"
msgid "Open project file"
msgstr "Apri file progetto"
-#: /home/ruben/Projects/Cura/resources/qml/AskOpenAsProjectOrModelsDialog.qml:93
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AskOpenAsProjectOrModelsDialog.qml:93
msgctxt "@text:window"
msgid "This is a Cura project file. Would you like to open it as a project or import the models from it?"
msgstr "Questo è un file progetto Cura. Vuoi aprirlo come progetto o importarne i modelli?"
-#: /home/ruben/Projects/Cura/resources/qml/AskOpenAsProjectOrModelsDialog.qml:103
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AskOpenAsProjectOrModelsDialog.qml:103
msgctxt "@text:window"
msgid "Remember my choice"
msgstr "Ricorda la scelta"
-#: /home/ruben/Projects/Cura/resources/qml/AskOpenAsProjectOrModelsDialog.qml:122
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AskOpenAsProjectOrModelsDialog.qml:122
msgctxt "@action:button"
msgid "Open as project"
msgstr "Apri come progetto"
-#: /home/ruben/Projects/Cura/resources/qml/AskOpenAsProjectOrModelsDialog.qml:131
+#: /home/ruben/Projects/Cura/resources/qml/Dialogs/AskOpenAsProjectOrModelsDialog.qml:131
msgctxt "@action:button"
msgid "Import models"
msgstr "Importa i modelli"
-#: /home/ruben/Projects/Cura/resources/qml/EngineLog.qml:15
-msgctxt "@title:window"
-msgid "Engine Log"
-msgstr "Log motore"
-
-#: /home/ruben/Projects/Cura/resources/qml/SidebarHeader.qml:70
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/DropDownWidget.qml:93
msgctxt "@label"
-msgid "Printer type"
-msgstr "Tipo di stampante"
+msgid "Empty"
+msgstr "Vuoto"
-#: /home/ruben/Projects/Cura/resources/qml/SidebarHeader.qml:376
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddNetworkOrLocalPrinterContent.qml:24
msgctxt "@label"
-msgid "Material"
-msgstr "Materiale"
+msgid "Add a printer"
+msgstr "Aggiungi una stampante"
-#: /home/ruben/Projects/Cura/resources/qml/SidebarHeader.qml:543
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddNetworkOrLocalPrinterContent.qml:39
msgctxt "@label"
-msgid "Use glue with this material combination"
-msgstr "Utilizzare la colla con questa combinazione di materiali"
+msgid "Add a networked printer"
+msgstr "Aggiungi una stampante in rete"
-#: /home/ruben/Projects/Cura/resources/qml/SidebarHeader.qml:575
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddNetworkOrLocalPrinterContent.qml:81
msgctxt "@label"
-msgid "Check compatibility"
-msgstr "Controlla compatibilità"
+msgid "Add a non-networked printer"
+msgstr "Aggiungi una stampante non in rete"
-#: /home/ruben/Projects/Cura/resources/qml/SidebarHeader.qml:593
-msgctxt "@tooltip"
-msgid "Click to check the material compatibility on Ultimaker.com."
-msgstr "Fai clic per verificare la compatibilità del materiale su Ultimaker.com."
+#: /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/ObjectsList.qml:211
-msgctxt "@option:check"
-msgid "See only current build plate"
-msgstr "Vedi solo il piano di stampa corrente"
+#: /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/ObjectsList.qml:227
-msgctxt "@action:button"
-msgid "Arrange to all build plates"
-msgstr "Sistema su tutti i piani di stampa"
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddPrinterByIpContent.qml:158
+msgctxt "@button"
+msgid "Add"
+msgstr "Aggiungi"
-#: /home/ruben/Projects/Cura/resources/qml/ObjectsList.qml:247
-msgctxt "@action:button"
-msgid "Arrange current build plate"
-msgstr "Sistema il piano di stampa corrente"
+#: /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:207
+msgctxt "@label"
+msgid "Printer name"
+msgstr "Nome stampante"
+
+#: /home/ruben/Projects/Cura/resources/qml/WelcomePages/AddLocalPrinterScrollView.qml:220
+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"
#: MachineSettingsAction/plugin.json
msgctxt "description"
@@ -4547,26 +5129,36 @@ msgctxt "name"
msgid "God Mode"
msgstr "Modalità God"
-#: ChangeLogPlugin/plugin.json
+#: FirmwareUpdater/plugin.json
msgctxt "description"
-msgid "Shows changes since latest checked version."
-msgstr "Mostra le modifiche dall'ultima versione selezionata."
+msgid "Provides a machine actions for updating firmware."
+msgstr "Fornisce azioni macchina per l’aggiornamento del firmware."
-#: ChangeLogPlugin/plugin.json
+#: FirmwareUpdater/plugin.json
msgctxt "name"
-msgid "Changelog"
-msgstr "Registro modifiche"
+msgid "Firmware Updater"
+msgstr "Aggiornamento firmware"
#: ProfileFlattener/plugin.json
msgctxt "description"
-msgid "Create a flattend quality changes profile."
-msgstr "Crea un profilo appiattito."
+msgid "Create a flattened quality changes profile."
+msgstr "Crea un profilo appiattito di modifiche di qualità."
#: ProfileFlattener/plugin.json
msgctxt "name"
-msgid "Profile flatener"
+msgid "Profile Flattener"
msgstr "Appiattitore di profilo"
+#: 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."
@@ -4577,26 +5169,6 @@ msgctxt "name"
msgid "USB printing"
msgstr "Stampa USB"
-#: UserAgreement/plugin.json
-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."
-
-#: UserAgreement/plugin.json
-msgctxt "name"
-msgid "UserAgreement"
-msgstr "Contratto di licenza"
-
-#: X3GWriter/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)."
-
-#: X3GWriter/plugin.json
-msgctxt "name"
-msgid "X3GWriter"
-msgstr "X3GWriter"
-
#: GCodeGzWriter/plugin.json
msgctxt "description"
msgid "Writes g-code to a compressed archive."
@@ -4647,6 +5219,16 @@ msgctxt "name"
msgid "UM3 Network Connection"
msgstr "Connessione di rete UM3"
+#: SettingsGuide/plugin.json
+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."
+
+#: SettingsGuide/plugin.json
+msgctxt "name"
+msgid "Settings Guide"
+msgstr "Guida alle impostazioni"
+
#: MonitorStage/plugin.json
msgctxt "description"
msgid "Provides a monitor stage in Cura."
@@ -4707,6 +5289,16 @@ 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."
@@ -4787,6 +5379,16 @@ 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."
@@ -4797,6 +5399,16 @@ 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."
@@ -4807,6 +5419,16 @@ 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."
@@ -4897,6 +5519,16 @@ 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."
@@ -4927,6 +5559,16 @@ 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.)."
@@ -4947,6 +5589,733 @@ msgctxt "name"
msgid "Cura Profile Reader"
msgstr "Lettore profilo Cura"
+#~ 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"
+
+#~ msgctxt "@info:status"
+#~ msgid "Nothing to slice because none of the models fit the build volume. Please scale or rotate models to fit."
+#~ msgstr "Nulla da sezionare in quanto nessuno dei modelli corrisponde al volume di stampa. Ridimensionare o ruotare i modelli secondo necessità."
+
+#~ msgctxt "@info:status"
+#~ msgid "The selected material is incompatible with the selected machine or configuration."
+#~ msgstr "Il materiale selezionato è incompatibile con la macchina o la configurazione selezionata."
+
+#~ msgctxt "@info:title"
+#~ msgid "Incompatible Material"
+#~ msgstr "Materiale incompatibile"
+
+#~ msgctxt "@info:status Don't translate the XML tags or !"
+#~ msgid "Failed to import profile from {0}: {1}"
+#~ msgstr "Impossibile importare il profilo da {0}: {1}"
+
+#~ msgctxt "@title"
+#~ msgid "Toolbox"
+#~ msgstr "Casella degli strumenti"
+
+#~ msgctxt "@label"
+#~ msgid "Not available"
+#~ msgstr "Non disponibile"
+
+#~ msgctxt "@label"
+#~ msgid "Unreachable"
+#~ msgstr "Non raggiungibile"
+
+#~ msgctxt "@label"
+#~ msgid "Available"
+#~ msgstr "Disponibile"
+
+#~ msgctxt "@label:status"
+#~ msgid "Preparing"
+#~ msgstr "Preparazione in corso"
+
+#~ msgctxt "@label:status"
+#~ msgid "Pausing"
+#~ msgstr "Messa in pausa"
+
+#~ msgctxt "@label:status"
+#~ msgid "Resuming"
+#~ msgstr "Ripresa"
+
+#~ msgctxt "@label"
+#~ msgid "Waiting for: Unavailable printer"
+#~ msgstr "In attesa: stampante non disponibile"
+
+#~ msgctxt "@label"
+#~ msgid "Waiting for: First available"
+#~ msgstr "In attesa della prima disponibile"
+
+#~ msgctxt "@label"
+#~ msgid "Waiting for: "
+#~ msgstr "In attesa: "
+
+#~ msgctxt "@label"
+#~ msgid "Configuration change"
+#~ msgstr "Modifica configurazione"
+
+#~ msgctxt "@label"
+#~ msgid "The assigned printer, %1, requires the following configuration change(s):"
+#~ msgstr "La stampante assegnata, %1, richiede le seguenti modifiche di configurazione:"
+
+#~ msgctxt "@label"
+#~ msgid "Override"
+#~ msgstr "Override"
+
+#~ msgctxt "@label"
+#~ msgid "Starting a print job with an incompatible configuration could damage your 3D printer. Are you sure you want to override the configuration and print %1?"
+#~ msgstr "L’avvio di un processo di stampa con una configurazione non compatibile potrebbe danneggiare la stampante 3D. Sei sicuro di voler annullare la configurazione e stampare %1?"
+
+#~ msgctxt "@window:title"
+#~ msgid "Override configuration configuration and start print"
+#~ msgstr "Annullare la configurazione e avviare la stampa"
+
+#~ msgctxt "@label link to connect manager"
+#~ msgid "Manage queue"
+#~ msgstr "Gestione coda di stampa"
+
+#~ msgctxt "@label"
+#~ msgid "Printing"
+#~ msgstr "Stampa in corso"
+
+#~ msgctxt "@label link to connect manager"
+#~ msgid "Manage printers"
+#~ msgstr "Gestione stampanti"
+
+#~ msgctxt "@action:button"
+#~ msgid "Activate Configuration"
+#~ msgstr "Attiva la configurazione"
+
+#~ msgctxt "@info:tooltip"
+#~ msgid "Load the configuration of the printer into Cura"
+#~ msgstr "Carica la configurazione della stampante in Cura"
+
+#~ msgctxt "@label"
+#~ msgid "Show Travels"
+#~ msgstr "Mostra spostamenti"
+
+#~ msgctxt "@label"
+#~ msgid "Show Helpers"
+#~ msgstr "Mostra helper"
+
+#~ msgctxt "@label"
+#~ msgid "Show Shell"
+#~ msgstr "Mostra guscio"
+
+#~ msgctxt "@label"
+#~ msgid "Show Infill"
+#~ msgstr "Mostra riempimento"
+
+#~ msgctxt "@text:window"
+#~ msgid "I don't want to send these data"
+#~ msgstr "Non voglio inviare questi dati"
+
+#~ msgctxt "@text:window"
+#~ msgid "Allow sending these data to Ultimaker and help us improve Cura"
+#~ msgstr "Il consenso all'invio di questi dati ad Ultimaker ci aiuta ad ottimizzare Cura"
+
+#~ msgctxt "@label"
+#~ msgid "Printer type:"
+#~ msgstr "Tipo di stampante:"
+
+#~ msgctxt "@label"
+#~ msgid "Connection:"
+#~ msgstr "Collegamento:"
+
+#~ msgctxt "@label"
+#~ msgid "State:"
+#~ msgstr "Stato:"
+
+#~ msgctxt "@label:MonitorStatus"
+#~ msgid "Waiting for a printjob"
+#~ msgstr "In attesa di un processo di stampa"
+
+#~ msgctxt "@label:MonitorStatus"
+#~ msgid "Waiting for someone to clear the build plate"
+#~ msgstr "In attesa di qualcuno che cancelli il piano di stampa"
+
+#~ msgctxt "@label:MonitorStatus"
+#~ msgid "Aborting print..."
+#~ msgstr "Interruzione stampa in corso..."
+
+#~ msgctxt "@label"
+#~ msgid "Protected profiles"
+#~ msgstr "Profili protetti"
+
+#~ msgctxt "@label"
+#~ msgid "Printer Name:"
+#~ msgstr "Nome stampante:"
+
+#~ msgctxt "@label"
+#~ msgid "Profile:"
+#~ msgstr "Profilo:"
+
+#~ msgctxt "@label:textbox"
+#~ msgid "Search..."
+#~ msgstr "Ricerca..."
+
+#~ msgctxt "@action:inmenu"
+#~ msgid "Collapse All"
+#~ msgstr "Comprimi tutto"
+
+#~ msgctxt "@action:inmenu"
+#~ msgid "Expand All"
+#~ msgstr "Espandi tutto"
+
+#~ msgctxt "@label:header configurations"
+#~ msgid "Available configurations"
+#~ msgstr "Configurazioni disponibili"
+
+#~ msgctxt "@label:extruder label"
+#~ msgid "Extruder"
+#~ msgstr "Estrusore"
+
+#~ msgctxt "@label:extruder label"
+#~ msgid "Yes"
+#~ msgstr "Sì"
+
+#~ msgctxt "@label:extruder label"
+#~ msgid "No"
+#~ msgstr "No"
+
+#~ msgctxt "@label:listbox"
+#~ msgid "Print Setup"
+#~ msgstr "Impostazione di stampa"
+
+#~ msgctxt "@label:listbox"
+#~ msgid ""
+#~ "Print Setup disabled\n"
+#~ "G-code files cannot be modified"
+#~ msgstr ""
+#~ "Impostazione di stampa disabilitata\n"
+#~ "I file codice G non possono essere modificati"
+
+#~ msgctxt "@label Hours and minutes"
+#~ msgid "00h 00min"
+#~ msgstr "00h 00min"
+
+#~ msgctxt "@tooltip"
+#~ msgid "Time specification"
+#~ msgstr "Indicazioni di tempo"
+
+#~ msgctxt "@label"
+#~ msgid "Cost specification"
+#~ msgstr "Indicazione di costo"
+
+#~ msgctxt "@label"
+#~ msgid "Total:"
+#~ msgstr "Totale:"
+
+#~ msgctxt "@tooltip"
+#~ msgid "Recommended Print Setup
Print with the recommended settings for the selected printer, material and quality."
+#~ msgstr "Impostazione di stampa consigliata
Stampa con le impostazioni consigliate per la stampante, il materiale e la qualità selezionati."
+
+#~ msgctxt "@tooltip"
+#~ msgid "Custom Print Setup
Print with finegrained control over every last bit of the slicing process."
+#~ msgstr "Impostazione di stampa personalizzata
Stampa con il controllo grana fine su ogni sezione finale del processo di sezionamento."
+
+#~ msgctxt "@action:inmenu menubar:help"
+#~ msgid "Show Engine &Log..."
+#~ msgstr "Mostra &log motore..."
+
+#~ msgctxt "@action:menu"
+#~ msgid "Browse packages..."
+#~ msgstr "Sfoglia i pacchetti..."
+
+#~ msgctxt "@action:inmenu menubar:view"
+#~ msgid "Expand/Collapse Sidebar"
+#~ msgstr "Espandi/Riduci barra laterale"
+
+#~ msgctxt "@label:PrintjobStatus"
+#~ msgid "Please load a 3D model"
+#~ msgstr "Caricare un modello 3D"
+
+#~ msgctxt "@label:PrintjobStatus"
+#~ msgid "Ready to slice"
+#~ msgstr "Pronto per il sezionamento"
+
+#~ msgctxt "@label:PrintjobStatus %1 is target operation"
+#~ msgid "Ready to %1"
+#~ msgstr "Pronto a %1"
+
+#~ msgctxt "@label:PrintjobStatus"
+#~ msgid "Slicing unavailable"
+#~ msgstr "Sezionamento non disponibile"
+
+#~ msgctxt "@info:tooltip"
+#~ msgid "Slice current printjob"
+#~ msgstr "Seziona processo di stampa corrente"
+
+#~ msgctxt "@info:tooltip"
+#~ msgid "Cancel slicing process"
+#~ msgstr "Annulla processo di sezionamento"
+
+#~ msgctxt "@label:Printjob"
+#~ msgid "Prepare"
+#~ msgstr "Prepara"
+
+#~ msgctxt "@label:Printjob"
+#~ msgid "Cancel"
+#~ msgstr "Annulla"
+
+#~ msgctxt "@info:tooltip"
+#~ msgid "Select the active output device"
+#~ msgstr "Seleziona l'unità di uscita attiva"
+
+#~ msgctxt "@title:menu"
+#~ msgid "&View"
+#~ msgstr "&Visualizza"
+
+#~ msgctxt "@title:menu"
+#~ msgid "&Settings"
+#~ msgstr "&Impostazioni"
+
+#~ msgctxt "@title:menu menubar:toplevel"
+#~ msgid "&Toolbox"
+#~ msgstr "&Casella degli strumenti"
+
+#~ msgctxt "@action:button"
+#~ msgid "Open File"
+#~ msgstr "Apri file"
+
+#~ msgctxt "@tooltip"
+#~ msgid "This quality profile is not available for you 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"
+#~ msgid "Print Speed"
+#~ msgstr "Velocità di stampa"
+
+#~ msgctxt "@label"
+#~ msgid "Slower"
+#~ msgstr "Più lenta"
+
+#~ msgctxt "@label"
+#~ msgid "Faster"
+#~ msgstr "Più veloce"
+
+#~ msgctxt "@label"
+#~ msgid "Enable gradual"
+#~ msgstr "Consenti variazione graduale"
+
+#~ msgctxt "@label"
+#~ msgid "Generate Support"
+#~ msgstr "Generazione supporto"
+
+#~ msgctxt "@label"
+#~ msgid "Build Plate Adhesion"
+#~ msgstr "Adesione piano di stampa"
+
+#~ msgctxt "@label"
+#~ msgid "Need help improving your prints? Read the Ultimaker Troubleshooting Guides"
+#~ msgstr "Serve aiuto per migliorare le tue stampe? Leggi la Guida alla ricerca e riparazione guasti Ultimaker"
+
+#~ msgctxt "@title:window"
+#~ msgid "Engine Log"
+#~ msgstr "Log motore"
+
+#~ msgctxt "@label"
+#~ msgid "Printer type"
+#~ msgstr "Tipo di stampante"
+
+#~ msgctxt "@label"
+#~ msgid "Use glue with this material combination"
+#~ msgstr "Utilizzare la colla con questa combinazione di materiali"
+
+#~ msgctxt "@label"
+#~ msgid "Check compatibility"
+#~ msgstr "Controlla compatibilità"
+
+#~ msgctxt "@tooltip"
+#~ 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 "Shows changes since latest checked version."
+#~ msgstr "Mostra le modifiche dall'ultima versione selezionata."
+
+#~ msgctxt "name"
+#~ msgid "Changelog"
+#~ msgstr "Registro modifiche"
+
+#~ msgctxt "description"
+#~ msgid "Create a flattend quality changes profile."
+#~ msgstr "Crea un profilo appiattito."
+
+#~ msgctxt "name"
+#~ msgid "Profile flatener"
+#~ msgstr "Appiattitore di profilo"
+
+#~ 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."
+
+#~ msgctxt "name"
+#~ msgid "UserAgreement"
+#~ msgstr "Contratto di licenza"
+
+#~ msgctxt "@warning:status"
+#~ msgid "Please generate G-code before saving."
+#~ msgstr "Generare il codice G prima di salvare."
+
+#~ msgctxt "@action"
+#~ msgid "Upgrade Firmware"
+#~ msgstr "Aggiorna firmware"
+
+#~ msgctxt "@label unknown material"
+#~ msgid "Unknown"
+#~ msgstr "Sconosciuto"
+
+#~ msgctxt "@info:status Don't translate the XML tags or !"
+#~ msgid "No custom profile to import in file {0}"
+#~ msgstr "Nessun profilo personalizzato da importare nel file {0}"
+
+#~ msgctxt "@info:status Don't translate the XML tags or !"
+#~ msgid "This profile {0} contains incorrect data, could not import it."
+#~ msgstr "Questo profilo {0} contiene dati errati, impossibile importarlo."
+
+#~ msgctxt "@info:status Don't translate the XML tags or !"
+#~ 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 importarlo."
+
+#~ msgctxt "@title:window"
+#~ msgid "Confirm uninstall "
+#~ msgstr "Conferma disinstalla "
+
+#~ msgctxt "@label Print estimates: m for meters, g for grams, %4 is currency and %3 is print cost"
+#~ msgid "%1m / ~ %2g / ~ %4 %3"
+#~ msgstr "%1m / ~ %2g / ~ %4 %3"
+
+#~ msgctxt "@label Print estimates: m for meters, g for grams"
+#~ msgid "%1m / ~ %2g"
+#~ msgstr "%1m / ~ %2g"
+
+#~ msgctxt "@title"
+#~ msgid "Upgrade Firmware"
+#~ msgstr "Aggiorna firmware"
+
#~ msgctxt "@action:button"
#~ msgid "Print with Doodle3D WiFi-Box"
#~ msgstr "Stampa con Doodle3D WiFi-Box"
@@ -5039,10 +6408,6 @@ msgstr "Lettore profilo Cura"
#~ msgid "Lost connection with the printer"
#~ msgstr "Persa connessione con la stampante"
-#~ msgctxt "@label:status"
-#~ msgid "Unavailable"
-#~ msgstr "Non disponibile"
-
#~ msgctxt "@label:status"
#~ msgid "Unknown"
#~ msgstr "Sconosciuto"
diff --git a/resources/i18n/it_IT/fdmextruder.def.json.po b/resources/i18n/it_IT/fdmextruder.def.json.po
index 3fa62440ea..79562add8e 100644
--- a/resources/i18n/it_IT/fdmextruder.def.json.po
+++ b/resources/i18n/it_IT/fdmextruder.def.json.po
@@ -1,14 +1,14 @@
# Cura
-# Copyright (C) 2018 Ultimaker
+# Copyright (C) 2019 Ultimaker B.V.
# This file is distributed under the same license as the Cura package.
-# Ruben Dulek , 2018.
+# Ruben Dulek , 2019.
#
msgid ""
msgstr ""
-"Project-Id-Version: Cura 3.5\n"
-"Report-Msgid-Bugs-To: r.dulek@ultimaker.com"
-"POT-Creation-Date: 2018-09-19 17:07+0000\n"
-"PO-Revision-Date: 2018-09-28 14:25+0100\n"
+"Project-Id-Version: Cura 4.2\n"
+"Report-Msgid-Bugs-To: r.dulek@ultimaker.com\n"
+"POT-Creation-Date: 2019-07-16 14:38+0000\n"
+"PO-Revision-Date: 2019-03-13 14:00+0200\n"
"Last-Translator: Bothof \n"
"Language-Team: Italian\n"
"Language: it_IT\n"
@@ -83,8 +83,8 @@ msgstr "Codice G avvio estrusore"
#: fdmextruder.def.json
msgctxt "machine_extruder_start_code description"
-msgid "Start g-code to execute whenever turning the extruder on."
-msgstr "Codice G di avvio da eseguire ogniqualvolta si accende l’estrusore."
+msgid "Start g-code to execute when switching to this extruder."
+msgstr "Inizio codice G da eseguire quando si passa a questo estrusore."
#: fdmextruder.def.json
msgctxt "machine_extruder_start_pos_abs label"
@@ -123,8 +123,8 @@ msgstr "Codice G fine estrusore"
#: fdmextruder.def.json
msgctxt "machine_extruder_end_code description"
-msgid "End g-code to execute whenever turning the extruder off."
-msgstr "Codice G di fine da eseguire ogniqualvolta si spegne l’estrusore."
+msgid "End g-code to execute when switching away from this extruder."
+msgstr "Fine codice G da eseguire quando si passa a questo estrusore."
#: fdmextruder.def.json
msgctxt "machine_extruder_end_pos_abs label"
@@ -166,6 +166,16 @@ msgctxt "extruder_prime_pos_z description"
msgid "The Z coordinate of the position where the nozzle primes at the start of printing."
msgstr "Indica la coordinata Z della posizione in cui l’ugello si innesca all’avvio della stampa."
+#: fdmextruder.def.json
+msgctxt "machine_extruder_cooling_fan_number label"
+msgid "Extruder Print Cooling Fan"
+msgstr "Ventola di raffreddamento stampa estrusore"
+
+#: fdmextruder.def.json
+msgctxt "machine_extruder_cooling_fan_number description"
+msgid "The number of the print cooling fan associated with this extruder. Only change this from the default value of 0 when you have a different print cooling fan for each extruder."
+msgstr "Il numero di ventole di raffreddamento stampa abbinate a questo estrusore. Modificarlo dal valore predefinito 0 solo quando si ha una ventola di raffreddamento diversa per ciascun estrusore."
+
#: fdmextruder.def.json
msgctxt "platform_adhesion label"
msgid "Build Plate Adhesion"
@@ -215,3 +225,11 @@ msgstr "Diametro"
msgctxt "material_diameter description"
msgid "Adjusts the diameter of the filament used. Match this value with the diameter of the used filament."
msgstr "Regolare il diametro del filamento utilizzato. Abbinare questo valore al diametro del filamento utilizzato."
+
+#~ msgctxt "machine_extruder_start_code description"
+#~ msgid "Start g-code to execute whenever turning the extruder on."
+#~ msgstr "Codice G di avvio da eseguire ogniqualvolta si accende l’estrusore."
+
+#~ msgctxt "machine_extruder_end_code description"
+#~ msgid "End g-code to execute whenever turning the extruder off."
+#~ msgstr "Codice G di fine da eseguire ogniqualvolta si spegne l’estrusore."
diff --git a/resources/i18n/it_IT/fdmprinter.def.json.po b/resources/i18n/it_IT/fdmprinter.def.json.po
index 135c07b4ab..60adf91c54 100644
--- a/resources/i18n/it_IT/fdmprinter.def.json.po
+++ b/resources/i18n/it_IT/fdmprinter.def.json.po
@@ -1,20 +1,20 @@
# Cura
-# Copyright (C) 2018 Ultimaker
+# Copyright (C) 2019 Ultimaker B.V.
# This file is distributed under the same license as the Cura package.
-# Ruben Dulek , 2018.
+# Ruben Dulek , 2019.
#
msgid ""
msgstr ""
-"Project-Id-Version: Cura 3.5\n"
-"Report-Msgid-Bugs-To: r.dulek@ultimaker.comPOT-Creation-Date: 2018-09-19 17:07+0000\n"
-"PO-Revision-Date: 2018-09-28 15:02+0200\n"
-"Last-Translator: Bothof \n"
-"Language-Team: Italian\n"
+"Project-Id-Version: Cura 4.2\n"
+"Report-Msgid-Bugs-To: r.dulek@ultimaker.com\n"
+"POT-Creation-Date: 2019-07-16 14:38+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"
"Content-Transfer-Encoding: 8bit\n"
-"POT-Creation-Date: \n"
"X-Generator: Poedit 2.0.6\n"
#: fdmprinter.def.json
@@ -237,7 +237,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 +247,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 +257,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 +267,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 +277,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 +307,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 +317,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 +337,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 +402,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 +422,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 +432,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 +442,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 +472,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
@@ -1077,7 +1077,7 @@ msgstr "Collega poligoni superiori/inferiori"
#: fdmprinter.def.json
msgctxt "connect_skin_polygons description"
-msgid "Connect top/bottom skin paths where they run next to each other. For the concentric pattern enabling this setting greatly reduces the travel time, but because the connections can happend midway over infill this feature can reduce the top surface quality."
+msgid "Connect top/bottom skin paths where they run next to each other. For the concentric pattern enabling this setting greatly reduces the travel time, but because the connections can happen midway over infill this feature can reduce the top surface quality."
msgstr "Collega i percorsi del rivestimento esterno superiore/inferiore quando corrono uno accanto all’altro. Per le configurazioni concentriche, l’abilitazione di questa impostazione riduce notevolmente il tempo di spostamento, tuttavia poiché i collegamenti possono aver luogo a metà del riempimento, con questa funzione la qualità della superficie superiore potrebbe risultare inferiore."
#: fdmprinter.def.json
@@ -1297,8 +1297,11 @@ 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 +1323,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 +1340,15 @@ 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"
@@ -1497,8 +1507,8 @@ msgstr "Configurazione di riempimento"
#: fdmprinter.def.json
msgctxt "infill_pattern description"
-msgid "The pattern of the infill material of the print. The line and zig zag infill swap direction on alternate layers, reducing material cost. The grid, triangle, tri-hexagon, cubic, octet, quarter cubic, cross and concentric patterns are fully printed every layer. Cubic, quarter cubic and octet infill change with every layer to provide a more equal distribution of strength over each direction."
-msgstr "Configurazione del materiale di riempimento della stampa. Il riempimento a linea e a zig zag cambia direzione su strati alternati, riducendo il costo del materiale. Le configurazioni a griglia, a triangolo, tri-esagonali, cubiche, ottagonali, a quarto di cubo, incrociate e concentriche sono stampate completamente su ogni strato. Le configurazioni cubiche, a quarto di cubo e ottagonali variano per ciascuno strato per garantire una più uniforme distribuzione della forza in ogni direzione."
+msgid "The pattern of the infill material of the print. The line and zig zag infill swap direction on alternate layers, reducing material cost. The grid, triangle, tri-hexagon, cubic, octet, quarter cubic, cross and concentric patterns are fully printed every layer. Gyroid, cubic, quarter cubic and octet infill change with every layer to provide a more equal distribution of strength over each direction."
+msgstr "Configurazione del materiale di riempimento della stampa. Il riempimento a linea e a zig zag cambia direzione su strati alternati, riducendo il costo del materiale. Le configurazioni a griglia, a triangolo, tri-esagonali, cubiche, ottagonali, a quarto di cubo, incrociate e concentriche sono stampate completamente su ogni strato. Le configurazioni gyroid, cubiche, a quarto di cubo e ottagonali variano per ciascuno strato per garantire una più uniforme distribuzione della forza in ogni direzione."
#: fdmprinter.def.json
msgctxt "infill_pattern option grid"
@@ -1560,6 +1570,11 @@ msgctxt "infill_pattern option cross_3d"
msgid "Cross 3D"
msgstr "Incrociata 3D"
+#: fdmprinter.def.json
+msgctxt "infill_pattern option gyroid"
+msgid "Gyroid"
+msgstr "Gyroid"
+
#: fdmprinter.def.json
msgctxt "zig_zaggify_infill label"
msgid "Connect Infill Lines"
@@ -1671,8 +1686,8 @@ msgstr "Percentuale di sovrapposizione del rivestimento esterno"
#: fdmprinter.def.json
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."
+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"
@@ -1681,8 +1696,8 @@ msgstr "Sovrapposizione del rivestimento esterno"
#: fdmprinter.def.json
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 "Indica la quantità di sovrapposizione tra il rivestimento esterno e le pareti. Una leggera sovrapposizione consente il saldo collegamento delle pareti al rivestimento esterno."
+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_wipe_dist label"
@@ -1864,6 +1879,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"
@@ -1974,6 +1999,87 @@ 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"
@@ -1984,6 +2090,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"
@@ -2101,8 +2327,9 @@ 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."
-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."
+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
msgctxt "material_standby_temperature label"
@@ -2121,8 +2348,8 @@ msgstr "Distanza di retrazione cambio ugello"
#: fdmprinter.def.json
msgctxt "switch_extruder_retraction_amount description"
-msgid "The amount of retraction: Set at 0 for no retraction at all. This should generally be the same as the length of the heat zone."
-msgstr "Indica il valore di retrazione: impostato a 0 per nessuna retrazione. Questo valore generalmente dovrebbe essere lo stesso della lunghezza della zona di riscaldamento."
+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 "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"
@@ -2154,6 +2381,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"
@@ -2345,14 +2582,15 @@ 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"
@@ -2781,8 +3019,8 @@ 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 and also to only comb within the infill. Note that the 'Within Infill' option behaves exactly like the 'Not in Skin' option in earlier Cura releases."
-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 effettuando il combing solo nel riempimento. Si noti che l’opzione ‘Nel riempimento' si comporta esattamente come l’opzione ‘Non nel rivestimento' delle precedenti versioni Cura."
+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 "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"
@@ -2924,6 +3162,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"
@@ -3194,6 +3442,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"
@@ -3264,6 +3517,36 @@ 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."
+#: fdmprinter.def.json
+msgctxt "support_brim_enable label"
+msgid "Enable Support Brim"
+msgstr "Abilitazione brim del supporto"
+
+#: fdmprinter.def.json
+msgctxt "support_brim_enable description"
+msgid "Generate a brim within the support infill regions of the first layer. This brim is printed underneath the support, not around it. Enabling this setting increases the adhesion of support to the build plate."
+msgstr "Genera un brim entro le zone di riempimento del supporto del primo strato. Questo brim viene stampato al di sotto del supporto, non intorno ad esso. L’abilitazione di questa impostazione aumenta l’adesione del supporto al piano di stampa."
+
+#: fdmprinter.def.json
+msgctxt "support_brim_width label"
+msgid "Support Brim Width"
+msgstr "Larghezza del brim del supporto"
+
+#: fdmprinter.def.json
+msgctxt "support_brim_width description"
+msgid "The width of the brim to print underneath the support. A larger brim enhances adhesion to the build plate, at the cost of some extra material."
+msgstr "Corrisponde alla larghezza del brim da stampare al di sotto del supporto. Un brim più largo migliora l’adesione al piano di stampa, ma utilizza una maggiore quantità di materiale."
+
+#: fdmprinter.def.json
+msgctxt "support_brim_line_count label"
+msgid "Support Brim Line Count"
+msgstr "Numero di linee del brim del supporto"
+
+#: fdmprinter.def.json
+msgctxt "support_brim_line_count description"
+msgid "The number of lines used for the support brim. More brim lines enhance adhesion to the build plate, at the cost of some extra material."
+msgstr "Corrisponde al numero di linee utilizzate per il brim del supporto. Più linee brim migliorano l’adesione al piano di stampa, ma utilizzano una maggiore quantità di materiale."
+
#: fdmprinter.def.json
msgctxt "support_z_distance label"
msgid "Support Z Distance"
@@ -3361,8 +3644,9 @@ 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"
@@ -3404,6 +3688,16 @@ msgctxt "gradual_support_infill_step_height description"
msgid "The height of support infill of a given density before switching to half the density."
msgstr "Indica l’altezza di riempimento del supporto di una data densità prima di passare a metà densità."
+#: fdmprinter.def.json
+msgctxt "minimum_support_area label"
+msgid "Minimum Support Area"
+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 "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"
msgid "Enable Support Interface"
@@ -3629,6 +3923,66 @@ msgctxt "support_bottom_pattern option zigzag"
msgid "Zig Zag"
msgstr "Zig Zag"
+#: fdmprinter.def.json
+msgctxt "minimum_interface_area label"
+msgid "Minimum Support Interface Area"
+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 "Dimensioni minime area per i poligoni di interfaccia del supporto. I poligoni con un’area inferiore a questo valore non verranno generati."
+
+#: fdmprinter.def.json
+msgctxt "minimum_roof_area label"
+msgid "Minimum Support Roof Area"
+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 "Dimensioni minime area per le parti superiori del supporto. I poligoni con un’area inferiore a questo valore non verranno generati."
+
+#: fdmprinter.def.json
+msgctxt "minimum_bottom_area label"
+msgid "Minimum Support Floor Area"
+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 "Dimensioni minime area per le parti inferiori del supporto. I poligoni con un’area inferiore a questo valore non verranno generati."
+
+#: fdmprinter.def.json
+msgctxt "support_interface_offset label"
+msgid "Support Interface Horizontal Expansion"
+msgstr "Espansione orizzontale interfaccia supporto"
+
+#: fdmprinter.def.json
+msgctxt "support_interface_offset description"
+msgid "Amount of offset applied to the support interface polygons."
+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 "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 "Entità di offset applicato alle parti superiori del supporto."
+
+#: fdmprinter.def.json
+msgctxt "support_bottom_offset label"
+msgid "Support Floor Horizontal Expansion"
+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 "Entità di offset applicato alle parti inferiori del supporto."
+
#: fdmprinter.def.json
msgctxt "support_fan_enable label"
msgid "Fan Speed Override"
@@ -3670,14 +4024,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"
@@ -3833,6 +4187,16 @@ msgctxt "brim_line_count description"
msgid "The number of lines used for a brim. More brim lines enhance adhesion to the build plate, but also reduces the effective print area."
msgstr "Corrisponde al numero di linee utilizzate per un brim. Più linee brim migliorano l’adesione al piano di stampa, ma con riduzione dell'area di stampa."
+#: fdmprinter.def.json
+msgctxt "brim_replaces_support label"
+msgid "Brim Replaces Support"
+msgstr "Brim in sostituzione del supporto"
+
+#: fdmprinter.def.json
+msgctxt "brim_replaces_support description"
+msgid "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."
+msgstr "Abilita la stampa del brim intorno al modello anche se quello spazio dovrebbe essere occupato dal supporto. Sostituisce alcune zone del primo strato del supporto con zone del brim."
+
#: fdmprinter.def.json
msgctxt "brim_outside_only label"
msgid "Brim Only on Outside"
@@ -4163,16 +4527,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"
@@ -4213,16 +4567,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"
@@ -4233,6 +4577,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"
@@ -4515,8 +4869,9 @@ 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"
@@ -4748,6 +5103,16 @@ 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."
+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."
+
#: fdmprinter.def.json
msgctxt "support_skip_some_zags label"
msgid "Break Up Support In Chunks"
@@ -5005,8 +5370,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"
@@ -5349,7 +5714,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
@@ -5359,7 +5724,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
@@ -5369,7 +5734,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
@@ -5379,7 +5744,7 @@ msgstr "La differenza in altezza dello strato successivo rispetto al precedente.
#: fdmprinter.def.json
msgctxt "adaptive_layer_height_threshold label"
-msgid "Adaptive layers threshold"
+msgid "Adaptive Layers Threshold"
msgstr "Soglia strati adattivi"
#: fdmprinter.def.json
@@ -5597,6 +5962,156 @@ 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 "command_line_settings label"
msgid "Command Line Settings"
@@ -5657,6 +6172,162 @@ 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 "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."
+
+#~ 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 "Indica la quantità di sovrapposizione tra il rivestimento esterno e le pareti. Una leggera sovrapposizione consente il saldo collegamento delle pareti al rivestimento esterno."
+
+#~ msgctxt "switch_extruder_retraction_amount description"
+#~ msgid "The amount of retraction: Set at 0 for no retraction at all. This should generally be the same as the length of the heat zone."
+#~ msgstr "Indica il valore di retrazione: impostato a 0 per nessuna retrazione. Questo valore generalmente dovrebbe essere lo stesso della lunghezza della zona di riscaldamento."
+
+#~ 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 and also to only comb within the infill. Note that the 'Within Infill' option behaves exactly like the 'Not in Skin' option in earlier Cura releases."
+#~ 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 effettuando il combing solo nel riempimento. Si noti che l’opzione ‘Nel riempimento' si comporta esattamente come l’opzione ‘Non nel rivestimento' delle precedenti versioni Cura."
+
+#~ msgctxt "connect_skin_polygons description"
+#~ msgid "Connect top/bottom skin paths where they run next to each other. For the concentric pattern enabling this setting greatly reduces the travel time, but because the connections can happend midway over infill this feature can reduce the top surface quality."
+#~ msgstr "Collega i percorsi del rivestimento esterno superiore/inferiore quando corrono uno accanto all’altro. Per le configurazioni concentriche, l’abilitazione di questa impostazione riduce notevolmente il tempo di spostamento, tuttavia poiché i collegamenti possono aver luogo a metà del riempimento, con questa funzione la qualità della superficie superiore potrebbe risultare inferiore."
+
+#~ msgctxt "infill_pattern description"
+#~ msgid "The pattern of the infill material of the print. The line and zig zag infill swap direction on alternate layers, reducing material cost. The grid, triangle, tri-hexagon, cubic, octet, quarter cubic, cross and concentric patterns are fully printed every layer. Cubic, quarter cubic and octet infill change with every layer to provide a more equal distribution of strength over each direction."
+#~ msgstr "Configurazione del materiale di riempimento della stampa. Il riempimento a linea e a zig zag cambia direzione su strati alternati, riducendo il costo del materiale. Le configurazioni a griglia, a triangolo, tri-esagonali, cubiche, ottagonali, a quarto di cubo, incrociate e concentriche sono stampate completamente su ogni strato. Le configurazioni cubiche, a quarto di cubo e ottagonali variano per ciascuno strato per garantire una più uniforme distribuzione della forza in ogni direzione."
+
#~ msgctxt "infill_pattern option concentric_3d"
#~ msgid "Concentric 3D"
#~ msgstr "3D concentrica"
diff --git a/resources/i18n/ja_JP/cura.po b/resources/i18n/ja_JP/cura.po
index 80fefa2b42..574fb89d7b 100644
--- a/resources/i18n/ja_JP/cura.po
+++ b/resources/i18n/ja_JP/cura.po
@@ -1,24 +1,24 @@
# Cura
-# Copyright (C) 2018 Ultimaker
+# Copyright (C) 2019 Ultimaker B.V.
# This file is distributed under the same license as the Cura package.
-# Ruben Dulek , 2018.
+# Ruben Dulek , 2019.
#
msgid ""
msgstr ""
-"Project-Id-Version: Cura 3.5\n"
+"Project-Id-Version: Cura 4.2\n"
"Report-Msgid-Bugs-To: r.dulek@ultimaker.com\n"
-"POT-Creation-Date: 2018-09-19 17:07+0200\n"
-"PO-Revision-Date: 2018-09-28 15:19+0200\n"
-"Last-Translator: Bothof \n"
-"Language-Team: Japanese\n"
+"POT-Creation-Date: 2019-07-16 14:38+0200\n"
+"PO-Revision-Date: 2019-07-29 16:09+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:27
msgctxt "@action"
msgid "Machine Settings"
msgstr "プリンターの設定"
@@ -48,15 +48,15 @@ msgstr "GCodeWriter は非テキストモードはサポートしていません
#: /home/ruben/Projects/Cura/plugins/GCodeWriter/GCodeWriter.py:73
#: /home/ruben/Projects/Cura/plugins/GCodeWriter/GCodeWriter.py:89
msgctxt "@warning:status"
-msgid "Please generate G-code before saving."
-msgstr "保存する前に G-code を生成してください。"
+msgid "Please prepare G-code before exporting."
+msgstr "エクスポートする前にG-codeの準備をしてください。"
-#: /home/ruben/Projects/Cura/plugins/ModelChecker/ModelChecker.py:30
+#: /home/ruben/Projects/Cura/plugins/ModelChecker/ModelChecker.py:31
msgctxt "@info:title"
msgid "3D Model Assistant"
msgstr "3Dモデルアシスタント"
-#: /home/ruben/Projects/Cura/plugins/ModelChecker/ModelChecker.py:80
+#: /home/ruben/Projects/Cura/plugins/ModelChecker/ModelChecker.py:90
#, python-brace-format
msgctxt "@info:status"
msgid ""
@@ -70,10 +70,10 @@ msgstr ""
"