diff --git a/.dockerignore b/.dockerignore
new file mode 100644
index 0000000000..d25d71bcc9
--- /dev/null
+++ b/.dockerignore
@@ -0,0 +1,4 @@
+.git
+.github
+resources/materials
+CuraEngine
\ No newline at end of file
diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md
index b78b9b91a2..c69cf91433 100644
--- a/.github/ISSUE_TEMPLATE.md
+++ b/.github/ISSUE_TEMPLATE.md
@@ -1,9 +1,12 @@
@@ -23,6 +26,9 @@ Thank you for using Cura!
**Display Driver**
+**Printer**
+
+
**Steps to Reproduce**
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000000..68255c56b9
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,45 @@
+FROM ultimaker/cura-build-environment:1
+
+# Environment vars for easy configuration
+ENV CURA_APP_DIR=/srv/cura
+
+# Ensure our sources dir exists
+RUN mkdir $CURA_APP_DIR
+
+# Setup CuraEngine
+ENV CURA_ENGINE_BRANCH=master
+WORKDIR $CURA_APP_DIR
+RUN git clone -b $CURA_ENGINE_BRANCH --depth 1 https://github.com/Ultimaker/CuraEngine
+WORKDIR $CURA_APP_DIR/CuraEngine
+RUN mkdir build
+WORKDIR $CURA_APP_DIR/CuraEngine/build
+RUN cmake3 ..
+RUN make
+RUN make install
+
+# TODO: setup libCharon
+
+# Setup Uranium
+ENV URANIUM_BRANCH=master
+WORKDIR $CURA_APP_DIR
+RUN git clone -b $URANIUM_BRANCH --depth 1 https://github.com/Ultimaker/Uranium
+
+# Setup materials
+ENV MATERIALS_BRANCH=master
+WORKDIR $CURA_APP_DIR
+RUN git clone -b $MATERIALS_BRANCH --depth 1 https://github.com/Ultimaker/fdm_materials materials
+
+# Setup Cura
+WORKDIR $CURA_APP_DIR/Cura
+ADD . .
+RUN mv $CURA_APP_DIR/materials resources/materials
+
+# Make sure Cura can find CuraEngine
+RUN ln -s /usr/local/bin/CuraEngine $CURA_APP_DIR/Cura
+
+# Run Cura
+WORKDIR $CURA_APP_DIR/Cura
+ENV PYTHONPATH=${PYTHONPATH}:$CURA_APP_DIR/Uranium
+RUN chmod +x ./CuraEngine
+RUN chmod +x ./run_in_docker.sh
+CMD "./run_in_docker.sh"
diff --git a/Jenkinsfile b/Jenkinsfile
index 20c7303719..83104aea18 100644
--- a/Jenkinsfile
+++ b/Jenkinsfile
@@ -1,5 +1,5 @@
-timeout(time: 2, unit: "HOURS") {
- parallel_nodes(['linux && cura', 'windows && cura']) {
+parallel_nodes(['linux && cura', 'windows && cura']) {
+ timeout(time: 2, unit: "HOURS") {
// Prepare building
stage('Prepare') {
// Ensure we start with a clean build directory.
diff --git a/README.md b/README.md
index 6ea839a300..70466e9c22 100644
--- a/README.md
+++ b/README.md
@@ -27,6 +27,10 @@ Build scripts
-------------
Please checkout [cura-build](https://github.com/Ultimaker/cura-build) for detailed building instructions.
+Running from Source
+-------------
+Please check our [Wiki page](https://github.com/Ultimaker/Cura/wiki/Running-Cura-from-Source) for details about running Cura from source.
+
Plugins
-------------
Please check our [Wiki page](https://github.com/Ultimaker/Cura/wiki/Plugin-Directory) for details about creating and using plugins.
@@ -41,25 +45,7 @@ Please check out [Wiki page](https://github.com/Ultimaker/Cura/wiki/Cura-Setting
Translating Cura
----------------
-If you'd like to contribute a translation of Cura, please first look for [any existing translation](https://github.com/Ultimaker/Cura/tree/master/resources/i18n). If your language is already there in the source code but not in Cura's interface, it may be partially translated.
-
-There are four files that need to be translated for Cura:
-1. https://github.com/Ultimaker/Cura/blob/master/resources/i18n/cura.pot
-2. https://github.com/Ultimaker/Cura/blob/master/resources/i18n/fdmextruder.def.json.pot
-3. https://github.com/Ultimaker/Cura/blob/master/resources/i18n/fdmprinter.def.json.pot (This one is the most work.)
-4. https://github.com/Ultimaker/Uranium/blob/master/resources/i18n/uranium.pot
-
-Copy these files and rename them to `*.po` (remove the `t`). Then create the actual translations by filling in the empty `msgstr` entries. These are gettext files, which are plain text so you can open them with any text editor such as Notepad or GEdit, but it is probably easier with a specialised tool such as [POEdit](https://poedit.net/) or [Virtaal](http://virtaal.translatehouse.org/).
-
-Do not hestiate to ask us about a translation or the meaning of some text via Github Issues.
-
-Once the translation is complete, it's probably best to test them in Cura. Use your favourite software to convert the .po file to a .mo file (such as [GetText](https://www.gnu.org/software/gettext/)). Then put the .mo files in the `.../resources/i18n//LC_MESSAGES` folder in your Cura installation. Then find your Cura configuration file (next to the log as described above, except on Linux where it is located in `~/.config/cura`) and change the language preference to the name of the folder you just created. Then start Cura. If working correctly, your Cura should now be translated.
-
-To submit your translation, ideally you would make two pull requests where all `*.po` files are located in that same `` folder in the resources of both the Cura and Uranium repositories. Put `cura.po`, `fdmprinter.def.json.po` and `fdmextruder.def.json.po` in the Cura repository, and put `uranium.po` in the Uranium repository. Then submit the pull requests to Github. For people with less experience with Git, you can also e-mail the translations to the e-mail address listed at the top of the [cura.pot](https://github.com/Ultimaker/Cura/blob/master/resources/i18n/cura.pot) file as the `Report-Msgid-Bugs-To` entry and we'll make sure it gets checked and included.
-
-After the translation is submitted, the Cura maintainers will check for its completeness and check whether it is consistent. We will take special care to look for common mistakes, such as translating mark-up `` code and such. We are often not fluent in every language, so we expect the translator and the international users to make corrections where necessary. Of course, there will always be some mistakes in every translation.
-
-When the next Cura release comes around, some of the texts will have changed and some new texts will have been added. Around the time when the beta is released we will invoke a string freeze, meaning that no developer is allowed to make changes to the texts. Then we will update the translation template `.pot` files and ask all our translators to update their translations. If you are unable to update the translation in time for the actual release, we will remove the language from the drop-down menu in the Preferences window. The translation stays in Cura however, so that someone might pick it up again later and update it with the newest texts. Also, users who had previously selected the language can still continue Cura in their language but English text will appear among the original text.
+Please check out [Wiki page](https://github.com/Ultimaker/Cura/wiki/Translating-Cura) about how to translate Cura into other languages.
License
----------------
diff --git a/cura.appdata.xml b/cura.appdata.xml
index 5c67814fae..2d8bff15ec 100644
--- a/cura.appdata.xml
+++ b/cura.appdata.xml
@@ -3,7 +3,7 @@
cura.desktopCC0-1.0
- AGPL-3.0 and CC-BY-SA-4.0
+ LGPL-3.0 and CC-BY-SA-4.0CuraThe world's most advanced 3d printer software
@@ -15,7 +15,7 @@
Novices can start printing right away
-
Experts are able to customize 200 settings to achieve the best results
+
Experts are able to customize 300 settings to achieve the best results
Optimized profiles for Ultimaker materials
Supported by a global network of Ultimaker certified service partners
Print multiple objects at once with different settings for each object
@@ -26,6 +26,6 @@
http://software.ultimaker.com/Cura.png
- https://ultimaker.com/en/products/cura-software
+ https://ultimaker.com/en/products/cura-software?utm_source=cura&utm_medium=software&utm_campaign=resourcesCura
diff --git a/cura/BuildVolume.py b/cura/BuildVolume.py
index 7a495b2064..d93ce1107d 100755
--- a/cura/BuildVolume.py
+++ b/cura/BuildVolume.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.
from cura.Scene.CuraSceneNode import CuraSceneNode
@@ -74,6 +74,11 @@ class BuildVolume(SceneNode):
self._adhesion_type = None
self._platform = Platform(self)
+ self._build_volume_message = Message(catalog.i18nc("@info:status",
+ "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."), title = catalog.i18nc("@info:title", "Build Volume"))
+
self._global_container_stack = None
Application.getInstance().globalContainerStackChanged.connect(self._onStackChanged)
self._onStackChanged()
@@ -97,11 +102,6 @@ class BuildVolume(SceneNode):
self._setting_change_timer.setSingleShot(True)
self._setting_change_timer.timeout.connect(self._onSettingChangeTimerFinished)
- self._build_volume_message = Message(catalog.i18nc("@info:status",
- "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."), title = catalog.i18nc("@info:title","Build Volume"))
-
# Must be after setting _build_volume_message, apparently that is used in getMachineManager.
# activeQualityChanged is always emitted after setActiveVariant, setActiveMaterial and setActiveQuality.
# Therefore this works.
@@ -111,6 +111,9 @@ class BuildVolume(SceneNode):
# but it does not update the disallowed areas after material change
Application.getInstance().getMachineManager().activeStackChanged.connect(self._onStackChanged)
+ # Enable and disable extruder
+ Application.getInstance().getMachineManager().extruderChanged.connect(self.updateNodeBoundaryCheck)
+
# list of settings which were updated
self._changed_settings_since_last_rebuild = []
@@ -133,6 +136,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._scene_objects = new_scene_objects
self._onSettingPropertyChanged("print_sequence", "value") # Create fake event, so right settings are triggered.
@@ -147,7 +151,6 @@ class BuildVolume(SceneNode):
active_extruder_changed = node.callDecoration("getActiveExtruderChangedSignal")
if active_extruder_changed is not None:
active_extruder_changed.connect(self._updateDisallowedAreasAndRebuild)
- self._updateDisallowedAreasAndRebuild()
def setWidth(self, width):
if width is not None:
@@ -195,7 +198,8 @@ class BuildVolume(SceneNode):
return True
- ## For every sliceable node, update outsideBuildArea
+ ## For every sliceable node, update node._outside_buildarea
+ #
def updateNodeBoundaryCheck(self):
root = Application.getInstance().getController().getScene().getRoot()
nodes = list(BreadthFirstIterator(root))
@@ -212,12 +216,30 @@ class BuildVolume(SceneNode):
for node in nodes:
# Need to check group nodes later
- self.checkBoundsAndUpdate(node, bounds = build_volume_bounding_box)
+ if node.callDecoration("isGroup"):
+ group_nodes.append(node) # Keep list of affected group_nodes
+
+ if node.callDecoration("isSliceable") or node.callDecoration("isGroup"):
+ if node.collidesWithBbox(build_volume_bounding_box):
+ node.setOutsideBuildArea(True)
+ continue
+
+ if node.collidesWithArea(self.getDisallowedAreas()):
+ node.setOutsideBuildArea(True)
+ continue
+
+ # Mark the node as outside build volume if the set extruder is disabled
+ extruder_position = node.callDecoration("getActiveExtruderPosition")
+ if not self._global_container_stack.extruders[extruder_position].isEnabled:
+ node.setOutsideBuildArea(True)
+ continue
+
+ node.setOutsideBuildArea(False)
# Group nodes should override the _outside_buildarea property of their children.
for group_node in group_nodes:
for child_node in group_node.getAllChildren():
- child_node._outside_buildarea = group_node._outside_buildarea
+ 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):
@@ -237,24 +259,20 @@ class BuildVolume(SceneNode):
build_volume_bounding_box = bounds
if node.callDecoration("isSliceable") or node.callDecoration("isGroup"):
- bbox = node.getBoundingBox()
-
- # Mark the node as outside the build volume if the bounding box test fails.
- if build_volume_bounding_box.intersectsBox(bbox) != AxisAlignedBox.IntersectionResult.FullIntersection:
+ if node.collidesWithBbox(build_volume_bounding_box):
+ node.setOutsideBuildArea(True)
+ return
+
+ if node.collidesWithArea(self.getDisallowedAreas()):
+ node.setOutsideBuildArea(True)
+ return
+
+ # Mark the node as outside build volume if the set extruder is disabled
+ extruder_position = node.callDecoration("getActiveExtruderPosition")
+ if not self._global_container_stack.extruders[extruder_position].isEnabled:
node.setOutsideBuildArea(True)
return
- convex_hull = self.callDecoration("getConvexHull")
- if convex_hull:
- if not convex_hull.isValid():
- return
- # Check for collisions between disallowed areas and the object
- for area in self.getDisallowedAreas():
- overlap = convex_hull.intersectsPolygon(area)
- if overlap is None:
- continue
- node.setOutsideBuildArea(True)
- return
node.setOutsideBuildArea(False)
## Recalculates the build volume & disallowed areas.
@@ -714,12 +732,17 @@ 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
- 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 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],
+ ])
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.
@@ -798,6 +821,7 @@ 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.
result[extruder_id] = []
for polygon in machine_disallowed_polygons:
@@ -908,8 +932,8 @@ class BuildVolume(SceneNode):
# stack.
#
# \return A sequence of setting values, one for each extruder.
- def _getSettingFromAllExtruders(self, setting_key, property = "value"):
- all_values = ExtruderManager.getInstance().getAllExtruderSettings(setting_key, property)
+ def _getSettingFromAllExtruders(self, setting_key):
+ 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"):
@@ -922,7 +946,7 @@ class BuildVolume(SceneNode):
# not part of the collision radius, such as bed adhesion (skirt/brim/raft)
# and travel avoid distance.
def _getEdgeDisallowedSize(self):
- if not self._global_container_stack:
+ if not self._global_container_stack or not self._global_container_stack.extruders:
return 0
container_stack = self._global_container_stack
@@ -1000,7 +1024,7 @@ 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_size", "prime_tower_position_x", "prime_tower_position_y"]
+ _tower_settings = ["prime_tower_enable", "prime_tower_circular", "prime_tower_size", "prime_tower_position_x", "prime_tower_position_y"]
_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"]
_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.
diff --git a/cura/CrashHandler.py b/cura/CrashHandler.py
index b5d4001fe2..c082578218 100644
--- a/cura/CrashHandler.py
+++ b/cura/CrashHandler.py
@@ -1,7 +1,6 @@
-# Copyright (c) 2017 Ultimaker B.V.
+# Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
-import sys
import platform
import traceback
import faulthandler
@@ -13,15 +12,19 @@ import json
import ssl
import urllib.request
import urllib.error
+import shutil
-from PyQt5.QtCore import QT_VERSION_STR, PYQT_VERSION_STR, QCoreApplication
-from PyQt5.QtWidgets import QDialog, QDialogButtonBox, QVBoxLayout, QLabel, QTextEdit, QGroupBox
+from PyQt5.QtCore import QT_VERSION_STR, PYQT_VERSION_STR, Qt, QUrl
+from PyQt5.QtWidgets import QDialog, QDialogButtonBox, QVBoxLayout, QLabel, QTextEdit, QGroupBox, QCheckBox, QPushButton
+from PyQt5.QtGui import QDesktopServices
+from UM.Resources import Resources
from UM.Application import Application
from UM.Logger import Logger
from UM.View.GL.OpenGL import OpenGL
from UM.i18n import i18nCatalog
from UM.Platform import Platform
+from UM.Resources import Resources
catalog = i18nCatalog("cura")
@@ -49,10 +52,11 @@ fatal_exception_types = [
class CrashHandler:
crash_url = "https://stats.ultimaker.com/api/cura"
- def __init__(self, exception_type, value, tb):
+ def __init__(self, exception_type, value, tb, has_started = True):
self.exception_type = exception_type
self.value = value
self.traceback = tb
+ self.has_started = has_started
self.dialog = None # Don't create a QDialog before there is a QApplication
# While we create the GUI, the information will be stored for sending afterwards
@@ -64,21 +68,143 @@ class CrashHandler:
for part in line.rstrip("\n").split("\n"):
Logger.log("c", part)
- if not CuraDebugMode and exception_type not in fatal_exception_types:
+ # 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:
return
- application = QCoreApplication.instance()
- if not application:
- sys.exit(1)
+ if not has_started:
+ self._send_report_checkbox = None
+ self.early_crash_dialog = self._createEarlyCrashDialog()
self.dialog = QDialog()
self._createDialog()
+ def _createEarlyCrashDialog(self):
+ dialog = QDialog()
+ dialog.setMinimumWidth(500)
+ dialog.setMinimumHeight(170)
+ dialog.setWindowTitle(catalog.i18nc("@title:window", "Cura Crashed"))
+ dialog.finished.connect(self._closeEarlyCrashDialog)
+
+ layout = QVBoxLayout(dialog)
+
+ label = QLabel()
+ label.setText(catalog.i18nc("@label crash message", """
A fatal error has occurred.
+
Unfortunately, Cura encountered an unrecoverable error during start up. It was possibly caused by some incorrect configuration files. We suggest to backup and reset your configuration.
+
Backups can be found in the configuration folder.
+
Please send us this Crash Report to fix the problem.
+ """))
+ label.setWordWrap(True)
+ layout.addWidget(label)
+
+ # "send report" check box and show details
+ self._send_report_checkbox = QCheckBox(catalog.i18nc("@action:button", "Send crash report to Ultimaker"), dialog)
+ self._send_report_checkbox.setChecked(True)
+
+ show_details_button = QPushButton(catalog.i18nc("@action:button", "Show detailed crash report"), dialog)
+ show_details_button.setMaximumWidth(200)
+ show_details_button.clicked.connect(self._showDetailedReport)
+
+ show_configuration_folder_button = QPushButton(catalog.i18nc("@action:button", "Show configuration folder"), dialog)
+ show_configuration_folder_button.setMaximumWidth(200)
+ show_configuration_folder_button.clicked.connect(self._showConfigurationFolder)
+
+ layout.addWidget(self._send_report_checkbox)
+ layout.addWidget(show_details_button)
+ layout.addWidget(show_configuration_folder_button)
+
+ # "backup and start clean" and "close" buttons
+ buttons = QDialogButtonBox()
+ buttons.addButton(QDialogButtonBox.Close)
+ buttons.addButton(catalog.i18nc("@action:button", "Backup and Reset Configuration"), QDialogButtonBox.AcceptRole)
+ buttons.rejected.connect(self._closeEarlyCrashDialog)
+ buttons.accepted.connect(self._backupAndStartClean)
+
+ layout.addWidget(buttons)
+
+ return dialog
+
+ def _closeEarlyCrashDialog(self):
+ if self._send_report_checkbox.isChecked():
+ self._sendCrashReport()
+ os._exit(1)
+
+ def _backupAndStartClean(self):
+ # backup the current cura directories and create clean ones
+ from cura.CuraVersion import CuraVersion
+ from UM.Resources import Resources
+ # The early crash may happen before those information is set in Resources, so we need to set them here to
+ # make sure that Resources can find the correct place.
+ Resources.ApplicationIdentifier = "cura"
+ Resources.ApplicationVersion = CuraVersion
+ config_path = Resources.getConfigStoragePath()
+ data_path = Resources.getDataStoragePath()
+ cache_path = Resources.getCacheStoragePath()
+
+ folders_to_backup = []
+ folders_to_remove = [] # only cache folder needs to be removed
+
+ folders_to_backup.append(config_path)
+ if data_path != config_path:
+ folders_to_backup.append(data_path)
+
+ # Only remove the cache folder if it's not the same as data or config
+ if cache_path not in (config_path, data_path):
+ folders_to_remove.append(cache_path)
+
+ for folder in folders_to_remove:
+ shutil.rmtree(folder, ignore_errors = True)
+ for folder in folders_to_backup:
+ base_name = os.path.basename(folder)
+ root_dir = os.path.dirname(folder)
+
+ import datetime
+ date_now = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
+ idx = 0
+ file_name = base_name + "_" + date_now
+ zip_file_path = os.path.join(root_dir, file_name + ".zip")
+ while os.path.exists(zip_file_path):
+ idx += 1
+ file_name = base_name + "_" + date_now + "_" + idx
+ zip_file_path = os.path.join(root_dir, file_name + ".zip")
+ try:
+ # only create the zip backup when the folder exists
+ if os.path.exists(folder):
+ # remove the .zip extension because make_archive() adds it
+ zip_file_path = zip_file_path[:-4]
+ shutil.make_archive(zip_file_path, "zip", root_dir = root_dir, base_dir = base_name)
+
+ # remove the folder only when the backup is successful
+ shutil.rmtree(folder, ignore_errors = True)
+
+ # create an empty folder so Resources will not try to copy the old ones
+ os.makedirs(folder, 0o0755, exist_ok=True)
+
+ except Exception as e:
+ Logger.logException("e", "Failed to backup [%s] to file [%s]", folder, zip_file_path)
+ if not self.has_started:
+ print("Failed to backup [%s] to file [%s]: %s", folder, zip_file_path, e)
+
+ self.early_crash_dialog.close()
+
+ def _showConfigurationFolder(self):
+ path = Resources.getConfigStoragePath();
+ QDesktopServices.openUrl(QUrl.fromLocalFile( path ))
+
+ def _showDetailedReport(self):
+ self.dialog.exec_()
+
## Creates a modal dialog.
def _createDialog(self):
self.dialog.setMinimumWidth(640)
self.dialog.setMinimumHeight(640)
self.dialog.setWindowTitle(catalog.i18nc("@title:window", "Crash Report"))
+ # if the application has not fully started, this will be a detailed report dialog which should not
+ # close the application when it's closed.
+ if self.has_started:
+ self.dialog.finished.connect(self._close)
layout = QVBoxLayout(self.dialog)
@@ -89,6 +215,9 @@ class CrashHandler:
layout.addWidget(self._userDescriptionWidget())
layout.addWidget(self._buttonsWidget())
+ def _close(self):
+ os._exit(1)
+
def _messageWidget(self):
label = QLabel()
label.setText(catalog.i18nc("@label crash message", """
A fatal error has occurred. Please send us this Crash Report to fix the problem
@@ -130,7 +259,7 @@ class CrashHandler:
opengl_instance = OpenGL.getInstance()
if not opengl_instance:
self.data["opengl"] = {"version": "n/a", "vendor": "n/a", "type": "n/a"}
- return catalog.i18nc("@label", "not yet initialised ")
+ return catalog.i18nc("@label", "Not yet initialized ")
info = "
"
info += catalog.i18nc("@label OpenGL version", "
OpenGL Version: {version}
").format(version = opengl_instance.getOpenGLVersion())
@@ -148,8 +277,8 @@ class CrashHandler:
layout = QVBoxLayout()
text_area = QTextEdit()
- trace_dict = traceback.format_exception(self.exception_type, self.value, self.traceback)
- trace = "".join(trace_dict)
+ trace_list = traceback.format_exception(self.exception_type, self.value, self.traceback)
+ trace = "".join(trace_list)
text_area.setText(trace)
text_area.setReadOnly(True)
@@ -157,14 +286,28 @@ class CrashHandler:
group.setLayout(layout)
# Parsing all the information to fill the dictionary
- summary = trace_dict[len(trace_dict)-1].rstrip("\n")
- module = trace_dict[len(trace_dict)-2].rstrip("\n").split("\n")
+ summary = ""
+ if len(trace_list) >= 1:
+ summary = trace_list[len(trace_list)-1].rstrip("\n")
+ module = [""]
+ if len(trace_list) >= 2:
+ module = trace_list[len(trace_list)-2].rstrip("\n").split("\n")
module_split = module[0].split(", ")
- filepath = module_split[0].split("\"")[1]
+
+ filepath_directory_split = module_split[0].split("\"")
+ filepath = ""
+ if len(filepath_directory_split) > 1:
+ filepath = filepath_directory_split[1]
directory, filename = os.path.split(filepath)
- line = int(module_split[1].lstrip("line "))
- function = module_split[2].lstrip("in ")
- code = module[1].lstrip(" ")
+ line = ""
+ if len(module_split) > 1:
+ line = int(module_split[1].lstrip("line "))
+ function = ""
+ if len(module_split) > 2:
+ function = module_split[2].lstrip("in ")
+ code = ""
+ if len(module) > 1:
+ code = module[1].lstrip(" ")
# Using this workaround for a cross-platform path splitting
split_path = []
@@ -189,7 +332,7 @@ class CrashHandler:
json_metadata_file = os.path.join(directory, "plugin.json")
try:
- with open(json_metadata_file, "r") as f:
+ with open(json_metadata_file, "r", encoding = "utf-8") as f:
try:
metadata = json.loads(f.read())
module_version = metadata["version"]
@@ -217,9 +360,9 @@ class CrashHandler:
text_area = QTextEdit()
tmp_file_fd, tmp_file_path = tempfile.mkstemp(prefix = "cura-crash", text = True)
os.close(tmp_file_fd)
- with open(tmp_file_path, "w") as f:
+ with open(tmp_file_path, "w", encoding = "utf-8") as f:
faulthandler.dump_traceback(f, all_threads=True)
- with open(tmp_file_path, "r") as f:
+ with open(tmp_file_path, "r", encoding = "utf-8") as f:
logdata = f.read()
text_area.setText(logdata)
@@ -249,9 +392,13 @@ class CrashHandler:
def _buttonsWidget(self):
buttons = QDialogButtonBox()
buttons.addButton(QDialogButtonBox.Close)
- buttons.addButton(catalog.i18nc("@action:button", "Send report"), QDialogButtonBox.AcceptRole)
+ # Like above, this will be served as a separate detailed report dialog if the application has not yet been
+ # fully loaded. In this case, "send report" will be a check box in the early crash dialog, so there is no
+ # need for this extra button.
+ if self.has_started:
+ buttons.addButton(catalog.i18nc("@action:button", "Send report"), QDialogButtonBox.AcceptRole)
+ buttons.accepted.connect(self._sendCrashReport)
buttons.rejected.connect(self.dialog.close)
- buttons.accepted.connect(self._sendCrashReport)
return buttons
@@ -269,15 +416,23 @@ class CrashHandler:
kwoptions["context"] = ssl._create_unverified_context()
Logger.log("i", "Sending crash report info to [%s]...", self.crash_url)
+ if not self.has_started:
+ print("Sending crash report info to [%s]...\n" % self.crash_url)
try:
f = urllib.request.urlopen(self.crash_url, **kwoptions)
Logger.log("i", "Sent crash report info.")
+ if not self.has_started:
+ print("Sent crash report info.\n")
f.close()
- except urllib.error.HTTPError:
+ except urllib.error.HTTPError as e:
Logger.logException("e", "An HTTP error occurred while trying to send crash report")
- except Exception: # We don't want any exception to cause problems
+ if not self.has_started:
+ print("An HTTP error occurred while trying to send crash report: %s" % e)
+ except Exception as e: # We don't want any exception to cause problems
Logger.logException("e", "An exception occurred while trying to send crash report")
+ if not self.has_started:
+ print("An exception occurred while trying to send crash report: %s" % e)
os._exit(1)
diff --git a/cura/CuraActions.py b/cura/CuraActions.py
index f5aace805b..75338f17b6 100644
--- a/cura/CuraActions.py
+++ b/cura/CuraActions.py
@@ -94,6 +94,10 @@ class CuraActions(QObject):
removed_group_nodes.append(group_node)
op.addOperation(SetParentOperation(remaining_nodes_in_group[0], group_node.getParent()))
op.addOperation(RemoveSceneNodeOperation(group_node))
+
+ # Reset the print information
+ Application.getInstance().getController().getScene().sceneChanged.emit(node)
+
op.push()
## Set the extruder that should be used to print the selection.
@@ -105,10 +109,6 @@ class CuraActions(QObject):
nodes_to_change = []
for node in Selection.getAllSelectedObjects():
- # Do not change any nodes that already have the right extruder set.
- if node.callDecoration("getActiveExtruder") == extruder_id:
- continue
-
# If the node is a group, apply the active extruder to all children of the group.
if node.callDecoration("isGroup"):
for grouped_node in BreadthFirstIterator(node):
@@ -121,6 +121,10 @@ class CuraActions(QObject):
nodes_to_change.append(grouped_node)
continue
+ # Do not change any nodes that already have the right extruder set.
+ if node.callDecoration("getActiveExtruder") == extruder_id:
+ continue
+
nodes_to_change.append(node)
if not nodes_to_change:
diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py
index b825e456c2..b7731c5c8c 100755
--- a/cura/CuraApplication.py
+++ b/cura/CuraApplication.py
@@ -1,6 +1,10 @@
-# Copyright (c) 2017 Ultimaker B.V.
-# Copyright (c) 2017 Ultimaker B.V.
+# Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
+
+#Type hinting.
+from typing import Dict
+
+from PyQt5.QtCore import QObject, QTimer
from PyQt5.QtNetwork import QLocalServer
from PyQt5.QtNetwork import QLocalSocket
@@ -11,6 +15,7 @@ from UM.Math.Vector import Vector
from UM.Math.Quaternion import Quaternion
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
@@ -50,13 +55,25 @@ from UM.Settings.SettingDefinition import SettingDefinition, DefinitionPropertyT
from UM.Settings.ContainerRegistry import ContainerRegistry
from UM.Settings.SettingFunction import SettingFunction
from cura.Settings.MachineNameValidator import MachineNameValidator
-from cura.Settings.ProfilesModel import ProfilesModel
-from cura.Settings.MaterialsModel import MaterialsModel
-from cura.Settings.QualityAndUserProfilesModel import QualityAndUserProfilesModel
+
+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.MaterialManagementModel import MaterialManagementModel
+from cura.Machines.Models.GenericMaterialsModel import GenericMaterialsModel
+from cura.Machines.Models.BrandMaterialsModel import BrandMaterialsModel
+from cura.Machines.Models.QualityManagementModel import QualityManagementModel
+from cura.Machines.Models.QualitySettingsModel import QualitySettingsModel
+from cura.Machines.Models.MachineManagementModel import MachineManagementModel
+
+from cura.Machines.MachineErrorChecker import MachineErrorChecker
+
from cura.Settings.SettingInheritanceManager import SettingInheritanceManager
-from cura.Settings.UserProfilesModel import UserProfilesModel
from cura.Settings.SimpleModeSettingsManager import SimpleModeSettingsManager
+from cura.Machines.VariantManager import VariantManager
from . import PlatformPhysics
from . import BuildVolume
@@ -69,17 +86,14 @@ from . import CameraImageProvider
from . import MachineActionManager
from cura.Settings.MachineManager import MachineManager
-from cura.Settings.MaterialManager import MaterialManager
from cura.Settings.ExtruderManager import ExtruderManager
from cura.Settings.UserChangesModel import UserChangesModel
from cura.Settings.ExtrudersModel import ExtrudersModel
-from cura.Settings.ContainerSettingsModel import ContainerSettingsModel
from cura.Settings.MaterialSettingsVisibilityHandler import MaterialSettingsVisibilityHandler
-from cura.Settings.QualitySettingsModel import QualitySettingsModel
from cura.Settings.ContainerManager import ContainerManager
+from cura.Settings.SettingVisibilityPresetsModel import SettingVisibilityPresetsModel
from cura.ObjectsModel import ObjectsModel
-from cura.BuildPlateModel import BuildPlateModel
from PyQt5.QtCore import QUrl, pyqtSignal, pyqtProperty, QEvent, Q_ENUMS
from UM.FlameProfiler import pyqtSlot
@@ -87,6 +101,7 @@ from PyQt5.QtGui import QColor, QIcon
from PyQt5.QtWidgets import QMessageBox
from PyQt5.QtQml import qmlRegisterUncreatableType, qmlRegisterSingletonType, qmlRegisterType
+from configparser import ConfigParser
import sys
import os.path
import numpy
@@ -95,6 +110,7 @@ import os
import argparse
import json
+
numpy.seterr(all="ignore")
MYPY = False
@@ -113,6 +129,8 @@ class CuraApplication(QtApplication):
# changes of the settings.
SettingVersion = 4
+ Created = False
+
class ResourceTypes:
QmlFiles = Resources.UserType + 1
Firmware = Resources.UserType + 2
@@ -123,17 +141,11 @@ class CuraApplication(QtApplication):
MachineStack = Resources.UserType + 7
ExtruderStack = Resources.UserType + 8
DefinitionChangesContainer = Resources.UserType + 9
+ SettingVisibilityPreset = Resources.UserType + 10
Q_ENUMS(ResourceTypes)
- # FIXME: This signal belongs to the MachineManager, but the CuraEngineBackend plugin requires on it.
- # Because plugins are initialized before the ContainerRegistry, putting this signal in MachineManager
- # will make it initialized before ContainerRegistry does, and it won't find the active machine, thus
- # Cura will always show the Add Machine Dialog upon start.
- stacksValidationFinished = pyqtSignal() # Emitted whenever a validation is finished
-
def __init__(self, **kwargs):
-
# this list of dir names will be used by UM to detect an old cura directory
for dir_name in ["extruders", "machine_instances", "materials", "plugins", "quality", "user", "variants"]:
Resources.addExpectedDirNameInData(dir_name)
@@ -177,6 +189,7 @@ class CuraApplication(QtApplication):
Resources.addStorageType(self.ResourceTypes.ExtruderStack, "extruders")
Resources.addStorageType(self.ResourceTypes.MachineStack, "machine_instances")
Resources.addStorageType(self.ResourceTypes.DefinitionChangesContainer, "definition_changes")
+ Resources.addStorageType(self.ResourceTypes.SettingVisibilityPreset, "setting_visibility")
ContainerRegistry.getInstance().addResourceType(self.ResourceTypes.QualityInstanceContainer, "quality")
ContainerRegistry.getInstance().addResourceType(self.ResourceTypes.QualityInstanceContainer, "quality_changes")
@@ -194,10 +207,10 @@ class CuraApplication(QtApplication):
UM.VersionUpgradeManager.VersionUpgradeManager.getInstance().setCurrentVersions(
{
("quality_changes", InstanceContainer.Version * 1000000 + self.SettingVersion): (self.ResourceTypes.QualityInstanceContainer, "application/x-uranium-instancecontainer"),
- ("machine_stack", ContainerStack.Version * 1000000 + self.SettingVersion): (self.ResourceTypes.MachineStack, "application/x-cura-globalstack"),
- ("extruder_train", ContainerStack.Version * 1000000 + self.SettingVersion): (self.ResourceTypes.ExtruderStack, "application/x-cura-extruderstack"),
- ("preferences", Preferences.Version * 1000000 + self.SettingVersion): (Resources.Preferences, "application/x-uranium-preferences"),
- ("user", InstanceContainer.Version * 1000000 + self.SettingVersion): (self.ResourceTypes.UserInstanceContainer, "application/x-uranium-instancecontainer"),
+ ("machine_stack", ContainerStack.Version * 1000000 + self.SettingVersion): (self.ResourceTypes.MachineStack, "application/x-cura-globalstack"),
+ ("extruder_train", ContainerStack.Version * 1000000 + self.SettingVersion): (self.ResourceTypes.ExtruderStack, "application/x-cura-extruderstack"),
+ ("preferences", Preferences.Version * 1000000 + self.SettingVersion): (Resources.Preferences, "application/x-uranium-preferences"),
+ ("user", InstanceContainer.Version * 1000000 + self.SettingVersion): (self.ResourceTypes.UserInstanceContainer, "application/x-uranium-instancecontainer"),
("definition_changes", InstanceContainer.Version * 1000000 + self.SettingVersion): (self.ResourceTypes.DefinitionChangesContainer, "application/x-uranium-instancecontainer"),
}
)
@@ -209,11 +222,14 @@ class CuraApplication(QtApplication):
self._machine_manager = None # This is initialized on demand.
self._extruder_manager = None
self._material_manager = None
+ self._quality_manager = None
self._object_manager = None
self._build_plate_model = None
+ self._multi_build_plate_model = None
self._setting_inheritance_manager = None
self._simple_mode_settings_manager = None
self._cura_scene_controller = None
+ self._machine_error_checker = None
self._additional_components = {} # Components to add to certain areas in the interface
@@ -224,6 +240,12 @@ class CuraApplication(QtApplication):
tray_icon_name = "cura-icon-32.png",
**kwargs)
+ # FOR TESTING ONLY
+ if kwargs["parsed_command_line"].get("trigger_early_crash", False):
+ assert not "This crash is triggered by the trigger_early_crash command line argument."
+
+ self._variant_manager = None
+
self.default_theme = "cura-light"
self.setWindowIcon(QIcon(Resources.getPath(Resources.Images, "cura-icon.png")))
@@ -257,17 +279,22 @@ class CuraApplication(QtApplication):
self._center_after_select = False
self._camera_animation = None
self._cura_actions = None
- self._started = False
+ self.started = False
self._message_box_callback = None
self._message_box_callback_arguments = []
self._preferred_mimetype = ""
self._i18n_catalog = i18nCatalog("cura")
- self.getController().getScene().sceneChanged.connect(self.updatePlatformActivity)
+ self._update_platform_activity_timer = QTimer()
+ self._update_platform_activity_timer.setInterval(500)
+ self._update_platform_activity_timer.setSingleShot(True)
+ self._update_platform_activity_timer.timeout.connect(self.updatePlatformActivity)
+
+ self.getController().getScene().sceneChanged.connect(self.updatePlatformActivityDelayed)
self.getController().toolOperationStopped.connect(self._onToolOperationStopped)
self.getController().contextMenuRequested.connect(self._onContextMenuRequested)
- self.getCuraSceneController().activeBuildPlateChanged.connect(self.updatePlatformActivity)
+ self.getCuraSceneController().activeBuildPlateChanged.connect(self.updatePlatformActivityDelayed)
Resources.addType(self.ResourceTypes.QmlFiles, "qml")
Resources.addType(self.ResourceTypes.Firmware, "firmware")
@@ -278,16 +305,25 @@ class CuraApplication(QtApplication):
# Since they are empty, they should never be serialized and instead just programmatically created.
# We need them to simplify the switching between materials.
empty_container = ContainerRegistry.getInstance().getEmptyInstanceContainer()
+ self.empty_container = empty_container
+
+ empty_definition_changes_container = copy.deepcopy(empty_container)
+ empty_definition_changes_container.setMetaDataEntry("id", "empty_definition_changes")
+ empty_definition_changes_container.addMetaDataEntry("type", "definition_changes")
+ ContainerRegistry.getInstance().addContainer(empty_definition_changes_container)
+ self.empty_definition_changes_container = empty_definition_changes_container
empty_variant_container = copy.deepcopy(empty_container)
empty_variant_container.setMetaDataEntry("id", "empty_variant")
empty_variant_container.addMetaDataEntry("type", "variant")
ContainerRegistry.getInstance().addContainer(empty_variant_container)
+ self.empty_variant_container = empty_variant_container
empty_material_container = copy.deepcopy(empty_container)
empty_material_container.setMetaDataEntry("id", "empty_material")
empty_material_container.addMetaDataEntry("type", "material")
ContainerRegistry.getInstance().addContainer(empty_material_container)
+ self.empty_material_container = empty_material_container
empty_quality_container = copy.deepcopy(empty_container)
empty_quality_container.setMetaDataEntry("id", "empty_quality")
@@ -296,12 +332,14 @@ class CuraApplication(QtApplication):
empty_quality_container.addMetaDataEntry("type", "quality")
empty_quality_container.addMetaDataEntry("supported", False)
ContainerRegistry.getInstance().addContainer(empty_quality_container)
+ self.empty_quality_container = empty_quality_container
empty_quality_changes_container = copy.deepcopy(empty_container)
empty_quality_changes_container.setMetaDataEntry("id", "empty_quality_changes")
empty_quality_changes_container.addMetaDataEntry("type", "quality_changes")
empty_quality_changes_container.addMetaDataEntry("quality_type", "not_supported")
ContainerRegistry.getInstance().addContainer(empty_quality_changes_container)
+ self.empty_quality_changes_container = empty_quality_changes_container
with ContainerRegistry.getInstance().lockFile():
ContainerRegistry.getInstance().loadAllMetadata()
@@ -343,57 +381,9 @@ class CuraApplication(QtApplication):
preferences.setDefault("local_file/last_used_type", "text/x-gcode")
- preferences.setDefault("general/visible_settings", """
- machine_settings
- resolution
- layer_height
- shell
- wall_thickness
- top_bottom_thickness
- z_seam_x
- z_seam_y
- infill
- infill_sparse_density
- gradual_infill_steps
- material
- material_print_temperature
- material_bed_temperature
- material_diameter
- material_flow
- retraction_enable
- speed
- speed_print
- speed_travel
- acceleration_print
- acceleration_travel
- jerk_print
- jerk_travel
- travel
- cooling
- cool_fan_enabled
- support
- support_enable
- support_extruder_nr
- support_type
- platform_adhesion
- adhesion_type
- adhesion_extruder_nr
- brim_width
- raft_airgap
- layer_0_z_overlap
- raft_surface_layers
- dual
- prime_tower_enable
- prime_tower_size
- prime_tower_position_x
- prime_tower_position_y
- meshfix
- blackmagic
- print_sequence
- infill_mesh
- cutting_mesh
- experimental
- """.replace("\n", ";").replace(" ", ""))
+ default_visibility_profile = SettingVisibilityPresetsModel.getInstance().getItem(0)
+
+ preferences.setDefault("general/visible_settings", ";".join(default_visibility_profile["settings"]))
self.applicationShuttingDown.connect(self.saveSettings)
self.engineCreatedSignal.connect(self._onEngineCreated)
@@ -405,6 +395,12 @@ class CuraApplication(QtApplication):
self.getCuraSceneController().setActiveBuildPlate(0) # Initialize
+ self._quality_profile_drop_down_menu_model = None
+ self._custom_quality_profile_drop_down_menu_model = None
+
+ CuraApplication.Created = True
+
+
def _onEngineCreated(self):
self._engine.addImageProvider("camera", CameraImageProvider.CameraImageProvider())
@@ -459,8 +455,6 @@ class CuraApplication(QtApplication):
has_user_interaction = True
return has_user_interaction
- onDiscardOrKeepProfileChangesClosed = pyqtSignal() # Used to notify other managers that the dialog was closed
-
@pyqtSlot(str)
def discardOrKeepProfileChangesClosed(self, option):
if option == "discard":
@@ -483,7 +477,6 @@ class CuraApplication(QtApplication):
user_global_container.update()
# notify listeners that quality has changed (after user selected discard or keep)
- self.onDiscardOrKeepProfileChangesClosed.emit()
self.getMachineManager().activeQualityChanged.emit()
@pyqtSlot(int)
@@ -499,7 +492,7 @@ class CuraApplication(QtApplication):
#
# Note that the AutoSave plugin also calls this method.
def saveSettings(self):
- if not self._started: # Do not do saving during application start
+ if not self.started: # Do not do saving during application start
return
ContainerRegistry.getInstance().saveDirtyContainers()
@@ -525,7 +518,13 @@ class CuraApplication(QtApplication):
def _loadPlugins(self):
self._plugin_registry.addType("profile_reader", self._addProfileReader)
self._plugin_registry.addType("profile_writer", self._addProfileWriter)
- self._plugin_registry.addPluginLocation(os.path.join(QtApplication.getInstallPrefix(), "lib", "cura"))
+
+ if Platform.isLinux():
+ lib_suffixes = {"", "64", "32", "x32"} #A few common ones on different distributions.
+ else:
+ lib_suffixes = {""}
+ for suffix in lib_suffixes:
+ self._plugin_registry.addPluginLocation(os.path.join(QtApplication.getInstallPrefix(), "lib" + suffix, "cura"))
if not hasattr(sys, "frozen"):
self._plugin_registry.addPluginLocation(os.path.join(os.path.abspath(os.path.dirname(__file__)), "..", "plugins"))
self._plugin_registry.loadPlugin("ConsoleLogger")
@@ -653,6 +652,29 @@ class CuraApplication(QtApplication):
def run(self):
self.preRun()
+ container_registry = ContainerRegistry.getInstance()
+
+ Logger.log("i", "Initializing variant manager")
+ self._variant_manager = VariantManager(container_registry)
+ self._variant_manager.initialize()
+
+ Logger.log("i", "Initializing material manager")
+ from cura.Machines.MaterialManager import MaterialManager
+ self._material_manager = MaterialManager(container_registry, parent = self)
+ self._material_manager.initialize()
+
+ Logger.log("i", "Initializing quality manager")
+ from cura.Machines.QualityManager import QualityManager
+ self._quality_manager = QualityManager(container_registry, parent = self)
+ self._quality_manager.initialize()
+
+ Logger.log("i", "Initializing machine manager")
+ self._machine_manager = MachineManager(self)
+
+ Logger.log("i", "Initializing machine error checker")
+ self._machine_error_checker = MachineErrorChecker(self)
+ self._machine_error_checker.initialize()
+
# Check if we should run as single instance or not
self._setUpSingleInstanceServer()
@@ -677,9 +699,12 @@ class CuraApplication(QtApplication):
for file_name in self._open_file_queue: # Open all the files that were queued up while plug-ins were loading.
self._openFile(file_name)
- self._started = True
+ self.started = True
+ self.initializationFinished.emit()
self.exec_()
+ initializationFinished = pyqtSignal()
+
## Run Cura without GUI elements and interaction (server mode).
def runWithoutGUI(self):
self._use_gui = False
@@ -744,9 +769,12 @@ class CuraApplication(QtApplication):
def hasGui(self):
return self._use_gui
+ def getMachineErrorChecker(self, *args) -> MachineErrorChecker:
+ return self._machine_error_checker
+
def getMachineManager(self, *args) -> MachineManager:
if self._machine_manager is None:
- self._machine_manager = MachineManager.createMachineManager()
+ self._machine_manager = MachineManager(self)
return self._machine_manager
def getExtruderManager(self, *args):
@@ -754,20 +782,32 @@ class CuraApplication(QtApplication):
self._extruder_manager = ExtruderManager.createExtruderManager()
return self._extruder_manager
+ def getVariantManager(self, *args):
+ return self._variant_manager
+
+ @pyqtSlot(result = QObject)
def getMaterialManager(self, *args):
- if self._material_manager is None:
- self._material_manager = MaterialManager.createMaterialManager()
return self._material_manager
+ @pyqtSlot(result = QObject)
+ def getQualityManager(self, *args):
+ return self._quality_manager
+
def getObjectsModel(self, *args):
if self._object_manager is None:
self._object_manager = ObjectsModel.createObjectsModel()
return self._object_manager
+ @pyqtSlot(result = QObject)
+ def getMultiBuildPlateModel(self, *args):
+ if self._multi_build_plate_model is None:
+ self._multi_build_plate_model = MultiBuildPlateModel(self)
+ return self._multi_build_plate_model
+
+ @pyqtSlot(result = QObject)
def getBuildPlateModel(self, *args):
if self._build_plate_model is None:
- self._build_plate_model = BuildPlateModel.createBuildPlateModel()
-
+ self._build_plate_model = BuildPlateModel(self)
return self._build_plate_model
def getCuraSceneController(self, *args):
@@ -805,6 +845,16 @@ class CuraApplication(QtApplication):
def getPrintInformation(self):
return self._print_information
+ def getQualityProfilesDropDownMenuModel(self, *args, **kwargs):
+ if self._quality_profile_drop_down_menu_model is None:
+ self._quality_profile_drop_down_menu_model = QualityProfilesDropDownMenuModel(self)
+ return self._quality_profile_drop_down_menu_model
+
+ def getCustomQualityProfilesDropDownMenuModel(self, *args, **kwargs):
+ if self._custom_quality_profile_drop_down_menu_model is None:
+ self._custom_quality_profile_drop_down_menu_model = CustomQualityProfilesDropDownMenuModel(self)
+ return self._custom_quality_profile_drop_down_menu_model
+
## Registers objects for the QML engine to use.
#
# \param engine The QML engine.
@@ -819,28 +869,37 @@ class CuraApplication(QtApplication):
qmlRegisterUncreatableType(CuraApplication, "Cura", 1, 0, "ResourceTypes", "Just an Enum type")
- qmlRegisterSingletonType(CuraSceneController, "Cura", 1, 2, "SceneController", self.getCuraSceneController)
+ qmlRegisterSingletonType(CuraSceneController, "Cura", 1, 0, "SceneController", self.getCuraSceneController)
qmlRegisterSingletonType(ExtruderManager, "Cura", 1, 0, "ExtruderManager", self.getExtruderManager)
qmlRegisterSingletonType(MachineManager, "Cura", 1, 0, "MachineManager", self.getMachineManager)
- qmlRegisterSingletonType(MaterialManager, "Cura", 1, 0, "MaterialManager", self.getMaterialManager)
qmlRegisterSingletonType(SettingInheritanceManager, "Cura", 1, 0, "SettingInheritanceManager", self.getSettingInheritanceManager)
- qmlRegisterSingletonType(SimpleModeSettingsManager, "Cura", 1, 2, "SimpleModeSettingsManager", self.getSimpleModeSettingsManager)
+ qmlRegisterSingletonType(SimpleModeSettingsManager, "Cura", 1, 0, "SimpleModeSettingsManager", self.getSimpleModeSettingsManager)
qmlRegisterSingletonType(MachineActionManager.MachineActionManager, "Cura", 1, 0, "MachineActionManager", self.getMachineActionManager)
- qmlRegisterSingletonType(ObjectsModel, "Cura", 1, 2, "ObjectsModel", self.getObjectsModel)
- qmlRegisterSingletonType(BuildPlateModel, "Cura", 1, 2, "BuildPlateModel", self.getBuildPlateModel)
+ qmlRegisterSingletonType(ObjectsModel, "Cura", 1, 0, "ObjectsModel", self.getObjectsModel)
+ 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(ContainerSettingsModel, "Cura", 1, 0, "ContainerSettingsModel")
- qmlRegisterSingletonType(ProfilesModel, "Cura", 1, 0, "ProfilesModel", ProfilesModel.createProfilesModel)
- qmlRegisterType(MaterialsModel, "Cura", 1, 0, "MaterialsModel")
- qmlRegisterType(QualityAndUserProfilesModel, "Cura", 1, 0, "QualityAndUserProfilesModel")
- qmlRegisterType(UserProfilesModel, "Cura", 1, 0, "UserProfilesModel")
+
+ qmlRegisterType(GenericMaterialsModel, "Cura", 1, 0, "GenericMaterialsModel")
+ qmlRegisterType(BrandMaterialsModel, "Cura", 1, 0, "BrandMaterialsModel")
+ qmlRegisterType(MaterialManagementModel, "Cura", 1, 0, "MaterialManagementModel")
+ qmlRegisterType(QualityManagementModel, "Cura", 1, 0, "QualityManagementModel")
+ qmlRegisterType(MachineManagementModel, "Cura", 1, 0, "MachineManagementModel")
+
+ qmlRegisterSingletonType(QualityProfilesDropDownMenuModel, "Cura", 1, 0,
+ "QualityProfilesDropDownMenuModel", self.getQualityProfilesDropDownMenuModel)
+ qmlRegisterSingletonType(CustomQualityProfilesDropDownMenuModel, "Cura", 1, 0,
+ "CustomQualityProfilesDropDownMenuModel", self.getCustomQualityProfilesDropDownMenuModel)
+ qmlRegisterType(NozzleModel, "Cura", 1, 0, "NozzleModel")
+
qmlRegisterType(MaterialSettingsVisibilityHandler, "Cura", 1, 0, "MaterialSettingsVisibilityHandler")
qmlRegisterType(QualitySettingsModel, "Cura", 1, 0, "QualitySettingsModel")
qmlRegisterType(MachineNameValidator, "Cura", 1, 0, "MachineNameValidator")
- qmlRegisterType(UserChangesModel, "Cura", 1, 1, "UserChangesModel")
+ qmlRegisterType(UserChangesModel, "Cura", 1, 0, "UserChangesModel")
qmlRegisterSingletonType(ContainerManager, "Cura", 1, 0, "ContainerManager", ContainerManager.createContainerManager)
+ qmlRegisterSingletonType(SettingVisibilityPresetsModel, "Cura", 1, 0, "SettingVisibilityPresetsModel", SettingVisibilityPresetsModel.createSettingVisibilityPresetsModel)
# As of Qt5.7, it is necessary to get rid of any ".." in the path for the singleton to work.
actions_url = QUrl.fromLocalFile(os.path.abspath(Resources.getPath(CuraApplication.ResourceTypes.QmlFiles, "Actions.qml")))
@@ -916,12 +975,16 @@ class CuraApplication(QtApplication):
def getSceneBoundingBoxString(self):
return self._i18n_catalog.i18nc("@info 'width', 'depth' and 'height' are variable names that must NOT be translated; just translate the format of ##x##x## mm.", "%(width).1f x %(depth).1f x %(height).1f mm") % {'width' : self._scene_bounding_box.width.item(), 'depth': self._scene_bounding_box.depth.item(), 'height' : self._scene_bounding_box.height.item()}
+ def updatePlatformActivityDelayed(self, node = None):
+ if node is not None and node.getMeshData() is not None:
+ self._update_platform_activity_timer.start()
+
## Update scene bounding box for current build plate
def updatePlatformActivity(self, node = None):
count = 0
scene_bounding_box = None
is_block_slicing_node = False
- active_build_plate = self.getBuildPlateModel().activeBuildPlate
+ active_build_plate = self.getMultiBuildPlateModel().activeBuildPlate
for node in DepthFirstIterator(self.getController().getScene().getRoot()):
if (
not issubclass(type(node), CuraSceneNode) or
@@ -1058,8 +1121,9 @@ class CuraApplication(QtApplication):
Selection.add(node)
## Delete all nodes containing mesh data in the scene.
+ # \param only_selectable. Set this to False to delete objects from all build plates
@pyqtSlot()
- def deleteAll(self):
+ def deleteAll(self, only_selectable = True):
Logger.log("i", "Clearing scene")
if not self.getController().getToolsEnabled():
return
@@ -1070,7 +1134,9 @@ class CuraApplication(QtApplication):
continue
if (not node.getMeshData() and not node.callDecoration("getLayerData")) and not node.callDecoration("isGroup"):
continue # Node that doesnt have a mesh and is not a group.
- if not node.isSelectable():
+ if only_selectable and not node.isSelectable():
+ continue
+ if not node.callDecoration("isSliceable") and not node.callDecoration("getLayerData") and not node.callDecoration("isGroup"):
continue # Only remove nodes that are selectable.
if node.getParent() and node.getParent().callDecoration("isGroup"):
continue # Grouped nodes don't need resetting as their parent (the group) is resetted)
@@ -1081,16 +1147,12 @@ class CuraApplication(QtApplication):
for node in nodes:
op.addOperation(RemoveSceneNodeOperation(node))
+ # Reset the print information
+ self.getController().getScene().sceneChanged.emit(node)
+
op.push()
Selection.clear()
- # Reset the print information:
- self.getController().getScene().sceneChanged.emit(node)
- # self._print_information.setToZeroPrintInformation(self.getBuildPlateModel().activeBuildPlate)
-
- # stay on the same build plate
- #self.getCuraSceneController().setActiveBuildPlate(0) # Select first build plate
-
## Reset all translation on nodes with mesh data.
@pyqtSlot()
def resetAllTranslation(self):
@@ -1171,7 +1233,7 @@ class CuraApplication(QtApplication):
@pyqtSlot()
def arrangeAll(self):
nodes = []
- active_build_plate = self.getBuildPlateModel().activeBuildPlate
+ active_build_plate = self.getMultiBuildPlateModel().activeBuildPlate
for node in DepthFirstIterator(self.getController().getScene().getRoot()):
if not isinstance(node, SceneNode):
continue
@@ -1225,7 +1287,7 @@ class CuraApplication(QtApplication):
Logger.log("i", "Reloading all loaded mesh data.")
nodes = []
for node in DepthFirstIterator(self.getController().getScene().getRoot()):
- if not isinstance(node, SceneNode) or not node.getMeshData():
+ if not isinstance(node, CuraSceneNode) or not node.getMeshData():
continue
nodes.append(node)
@@ -1320,7 +1382,7 @@ class CuraApplication(QtApplication):
group_decorator = GroupDecorator()
group_node.addDecorator(group_decorator)
group_node.addDecorator(ConvexHullDecorator())
- group_node.addDecorator(BuildPlateDecorator(self.getBuildPlateModel().activeBuildPlate))
+ group_node.addDecorator(BuildPlateDecorator(self.getMultiBuildPlateModel().activeBuildPlate))
group_node.setParent(self.getController().getScene().getRoot())
group_node.setSelectable(True)
center = Selection.getSelectionCenter()
@@ -1450,7 +1512,7 @@ class CuraApplication(QtApplication):
self._currently_loading_files.append(f)
if extension in self._non_sliceable_extensions:
- self.deleteAll()
+ self.deleteAll(only_selectable = False)
job = ReadMeshJob(f)
job.finished.connect(self._readMeshFinished)
@@ -1465,7 +1527,7 @@ class CuraApplication(QtApplication):
arrange_objects_on_load = (
not Preferences.getInstance().getValue("cura/use_multi_build_plate") or
not Preferences.getInstance().getValue("cura/not_arrange_objects_on_load"))
- target_build_plate = self.getBuildPlateModel().activeBuildPlate if arrange_objects_on_load else -1
+ target_build_plate = self.getMultiBuildPlateModel().activeBuildPlate if arrange_objects_on_load else -1
root = self.getController().getScene().getRoot()
fixed_nodes = []
@@ -1474,12 +1536,22 @@ class CuraApplication(QtApplication):
fixed_nodes.append(node_)
arranger = Arrange.create(fixed_nodes = fixed_nodes)
min_offset = 8
+ default_extruder_position = self.getMachineManager().defaultExtruderPosition
+ default_extruder_id = self._global_container_stack.extruders[default_extruder_position].getId()
for original_node in nodes:
# Create a CuraSceneNode just if the original node is not that type
- node = original_node if isinstance(original_node, CuraSceneNode) else CuraSceneNode()
- node.setMeshData(original_node.getMeshData())
+ if isinstance(original_node, CuraSceneNode):
+ node = original_node
+ else:
+ node = CuraSceneNode()
+ node.setMeshData(original_node.getMeshData())
+
+ #Setting meshdata does not apply scaling.
+ if(original_node.getScale() != Vector(1.0, 1.0, 1.0)):
+ node.scale(original_node.getScale())
+
node.setSelectable(True)
node.setName(os.path.basename(filename))
@@ -1531,6 +1603,8 @@ class CuraApplication(QtApplication):
op = AddSceneNodeOperation(node, scene.getRoot())
op.push()
+
+ node.callDecoration("setActiveExtruder", default_extruder_id)
scene.sceneChanged.emit(node)
self.fileCompleted.emit(filename)
@@ -1551,7 +1625,7 @@ class CuraApplication(QtApplication):
result = workspace_reader.preRead(file_path, show_dialog=False)
return result == WorkspaceReader.PreReadResult.accepted
except Exception as e:
- Logger.log("e", "Could not check file %s: %s", file_url, e)
+ Logger.logException("e", "Could not check file %s: %s", file_url)
return False
def _onContextMenuRequested(self, x: float, y: float) -> None:
diff --git a/cura/Machines/ContainerNode.py b/cura/Machines/ContainerNode.py
new file mode 100644
index 0000000000..6a839fb921
--- /dev/null
+++ b/cura/Machines/ContainerNode.py
@@ -0,0 +1,49 @@
+# Copyright (c) 2018 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+
+from typing import Optional
+
+from collections import OrderedDict
+
+from UM.Logger import Logger
+from UM.Settings.InstanceContainer import InstanceContainer
+
+
+##
+# A metadata / container combination. Use getContainer() to get the container corresponding to the metadata.
+#
+# ContainerNode is a multi-purpose class. It has two main purposes:
+# 1. It encapsulates an InstanceContainer. It contains that InstanceContainer's
+# - metadata (Always)
+# - container (lazy-loaded when needed)
+# 2. It also serves as a node in a hierarchical InstanceContainer lookup table/tree.
+# This is used in Variant, Material, and Quality Managers.
+#
+class ContainerNode:
+ __slots__ = ("metadata", "container", "children_map")
+
+ def __init__(self, metadata: Optional[dict] = None):
+ self.metadata = metadata
+ self.container = None
+ self.children_map = OrderedDict()
+
+ def getChildNode(self, child_key: str) -> Optional["ContainerNode"]:
+ return self.children_map.get(child_key)
+
+ def getContainer(self) -> "InstanceContainer":
+ if self.metadata is None:
+ raise RuntimeError("Cannot get container for a ContainerNode without metadata")
+
+ if self.container is None:
+ container_id = self.metadata["id"]
+ Logger.log("i", "Lazy-loading container [%s]", container_id)
+ from UM.Settings.ContainerRegistry import ContainerRegistry
+ container_list = ContainerRegistry.getInstance().findInstanceContainers(id = container_id)
+ if not container_list:
+ raise RuntimeError("Failed to lazy-load container [%s], cannot find it" % container_id)
+ self.container = container_list[0]
+
+ return self.container
+
+ def __str__(self) -> str:
+ return "%s[%s]" % (self.__class__.__name__, self.metadata.get("id"))
diff --git a/cura/Machines/MachineErrorChecker.py b/cura/Machines/MachineErrorChecker.py
new file mode 100644
index 0000000000..37de4f30ce
--- /dev/null
+++ b/cura/Machines/MachineErrorChecker.py
@@ -0,0 +1,181 @@
+# Copyright (c) 2018 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+
+import time
+
+from collections import deque
+
+from PyQt5.QtCore import QObject, QTimer, pyqtSignal, pyqtProperty
+
+from UM.Application import Application
+from UM.Logger import Logger
+from UM.Settings.SettingDefinition import SettingDefinition
+from UM.Settings.Validator import ValidatorState
+
+
+#
+# This class performs setting error checks for the currently active machine.
+#
+# The whole error checking process is pretty heavy which can take ~0.5 secs, so it can cause GUI to lag.
+# The idea here is to split the whole error check into small tasks, each of which only checks a single setting key
+# in a stack. According to my profiling results, the maximal runtime for such a sub-task is <0.03 secs, which should
+# be good enough. Moreover, if any changes happened to the machine, we can cancel the check in progress without wait
+# for it to finish the complete work.
+#
+class MachineErrorChecker(QObject):
+
+ def __init__(self, parent = None):
+ super().__init__(parent)
+
+ self._global_stack = None
+
+ self._has_errors = True # Result of the error check, indicating whether there are errors in the stack
+ self._error_keys = set() # A set of settings keys that have errors
+ self._error_keys_in_progress = set() # The variable that stores the results of the currently in progress check
+
+ self._stacks_and_keys_to_check = None # a FIFO queue of tuples (stack, key) to check for errors
+
+ self._need_to_check = False # Whether we need to schedule a new check or not. This flag is set when a new
+ # error check needs to take place while there is already one running at the moment.
+ self._check_in_progress = False # Whether there is an error check running in progress at the moment.
+
+ self._application = Application.getInstance()
+ self._machine_manager = self._application.getMachineManager()
+
+ self._start_time = 0 # measure checking time
+
+ # This timer delays the starting of error check so we can react less frequently if the user is frequently
+ # changing settings.
+ self._error_check_timer = QTimer(self)
+ self._error_check_timer.setInterval(100)
+ self._error_check_timer.setSingleShot(True)
+
+ def initialize(self):
+ self._error_check_timer.timeout.connect(self._rescheduleCheck)
+
+ # Reconnect all signals when the active machine gets changed.
+ self._machine_manager.globalContainerChanged.connect(self._onMachineChanged)
+
+ # Whenever the machine settings get changed, we schedule an error check.
+ self._machine_manager.globalContainerChanged.connect(self.startErrorCheck)
+ self._machine_manager.globalValueChanged.connect(self.startErrorCheck)
+
+ self._onMachineChanged()
+
+ def _onMachineChanged(self):
+ if self._global_stack:
+ self._global_stack.propertyChanged.disconnect(self.startErrorCheck)
+ self._global_stack.containersChanged.disconnect(self.startErrorCheck)
+
+ for extruder in self._global_stack.extruders.values():
+ extruder.propertyChanged.disconnect(self.startErrorCheck)
+ 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.containersChanged.connect(self.startErrorCheck)
+
+ for extruder in self._global_stack.extruders.values():
+ extruder.propertyChanged.connect(self.startErrorCheck)
+ extruder.containersChanged.connect(self.startErrorCheck)
+
+ hasErrorUpdated = pyqtSignal()
+ needToWaitForResultChanged = pyqtSignal()
+ errorCheckFinished = pyqtSignal()
+
+ @pyqtProperty(bool, notify = hasErrorUpdated)
+ def hasError(self) -> bool:
+ return self._has_errors
+
+ @pyqtProperty(bool, notify = needToWaitForResultChanged)
+ def needToWaitForResult(self) -> bool:
+ return self._need_to_check or self._check_in_progress
+
+ # Starts the error check timer to schedule a new error check.
+ def startErrorCheck(self, *args):
+ if not self._check_in_progress:
+ self._need_to_check = True
+ self.needToWaitForResultChanged.emit()
+ self._error_check_timer.start()
+
+ # This function is called by the timer to reschedule a new error check.
+ # If there is no check in progress, it will start a new one. If there is any, it sets the "_need_to_check" flag
+ # to notify the current check to stop and start a new one.
+ def _rescheduleCheck(self):
+ if self._check_in_progress and not self._need_to_check:
+ self._need_to_check = True
+ self.needToWaitForResultChanged.emit()
+ return
+
+ self._error_keys_in_progress = set()
+ self._need_to_check = False
+ self.needToWaitForResultChanged.emit()
+
+ global_stack = self._machine_manager.activeMachine
+ if global_stack is None:
+ Logger.log("i", "No active machine, nothing to check.")
+ return
+
+ # 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 key in stack.getAllKeys():
+ self._stacks_and_keys_to_check.append((stack, key))
+
+ self._application.callLater(self._checkStack)
+ self._start_time = time.time()
+ Logger.log("d", "New error check scheduled.")
+
+ def _checkStack(self):
+ if self._need_to_check:
+ Logger.log("d", "Need to check for errors again. Discard the current progress and reschedule a check.")
+ self._check_in_progress = False
+ self._application.callLater(self.startErrorCheck)
+ return
+
+ self._check_in_progress = True
+
+ # If there is nothing to check any more, it means there is no error.
+ if not self._stacks_and_keys_to_check:
+ # Finish
+ self._setResult(False)
+ return
+
+ # Get the next stack and key to check
+ stack, key = self._stacks_and_keys_to_check.popleft()
+
+ enabled = stack.getProperty(key, "enabled")
+ if not enabled:
+ self._application.callLater(self._checkStack)
+ return
+
+ validation_state = stack.getProperty(key, "validationState")
+ if validation_state is None:
+ # Setting is not validated. This can happen if there is only a setting definition.
+ # We do need to validate it, because a setting definitions value can be set by a function, which could
+ # be an invalid setting.
+ definition = stack.getSettingDefinition(key)
+ validator_type = SettingDefinition.getValidatorForType(definition.type)
+ if validator_type:
+ validator = validator_type(key)
+ validation_state = validator(stack)
+ if validation_state in (ValidatorState.Exception, ValidatorState.MaximumError, ValidatorState.MinimumError):
+ # Finish
+ self._setResult(True)
+ return
+
+ # Schedule the check for the next key
+ self._application.callLater(self._checkStack)
+
+ def _setResult(self, result: bool):
+ if result != self._has_errors:
+ self._has_errors = result
+ self.hasErrorUpdated.emit()
+ self._machine_manager.stacksValidationChanged.emit()
+ self._need_to_check = False
+ self._check_in_progress = False
+ self.needToWaitForResultChanged.emit()
+ self.errorCheckFinished.emit()
+ Logger.log("i", "Error check finished, result = %s, time = %0.1fs", result, time.time() - self._start_time)
diff --git a/cura/Machines/MaterialGroup.py b/cura/Machines/MaterialGroup.py
new file mode 100644
index 0000000000..93c8a227a8
--- /dev/null
+++ b/cura/Machines/MaterialGroup.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 cura.Machines.MaterialNode import MaterialNode #For type checking.
+
+## A MaterialGroup represents a group of material InstanceContainers that are derived from a single material profile.
+# The main InstanceContainer which has the ID of the material profile file name is called the "root_material". For
+# example: "generic_abs" is the root material (ID) of "generic_abs_ultimaker3" and "generic_abs_ultimaker3_AA_0.4",
+# and "generic_abs_ultimaker3" and "generic_abs_ultimaker3_AA_0.4" are derived materials of "generic_abs".
+#
+# Using "generic_abs" as an example, the MaterialGroup for "generic_abs" will contain the following information:
+# - name: "generic_abs", root_material_id
+# - root_material_node: MaterialNode of "generic_abs"
+# - derived_material_node_list: A list of MaterialNodes that are derived from "generic_abs",
+# so "generic_abs_ultimaker3", "generic_abs_ultimaker3_AA_0.4", etc.
+#
+class MaterialGroup:
+ __slots__ = ("name", "is_read_only", "root_material_node", "derived_material_node_list")
+
+ def __init__(self, name: str, root_material_node: MaterialNode):
+ self.name = name
+ self.is_read_only = False
+ self.root_material_node = root_material_node
+ self.derived_material_node_list = [] #type: List[MaterialNode]
+
+ def __str__(self) -> str:
+ return "%s[%s]" % (self.__class__.__name__, self.name)
diff --git a/cura/Machines/MaterialManager.py b/cura/Machines/MaterialManager.py
new file mode 100644
index 0000000000..0a82fcc764
--- /dev/null
+++ b/cura/Machines/MaterialManager.py
@@ -0,0 +1,511 @@
+# Copyright (c) 2018 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+
+from collections import defaultdict, OrderedDict
+import copy
+import uuid
+from typing import Optional, TYPE_CHECKING
+
+from PyQt5.Qt import QTimer, QObject, pyqtSignal, pyqtSlot
+
+from UM.Application import Application
+from UM.Logger import Logger
+from UM.Settings.ContainerRegistry import ContainerRegistry
+from UM.Settings.SettingFunction import SettingFunction
+from UM.Util import parseBool
+
+from .MaterialNode import MaterialNode
+from .MaterialGroup import MaterialGroup
+
+if TYPE_CHECKING:
+ from cura.Settings.GlobalStack import GlobalStack
+
+
+#
+# MaterialManager maintains a number of maps and trees for material lookup.
+# The models GUI and QML use are now only dependent on the MaterialManager. That means as long as the data in
+# MaterialManager gets updated correctly, the GUI models should be updated correctly too, and the same goes for GUI.
+#
+# For now, updating the lookup maps and trees here is very simple: we discard the old data completely and recreate them
+# again. This means the update is exactly the same as initialization. There are performance concerns about this approach
+# but so far the creation of the tables and maps is very fast and there is no noticeable slowness, we keep it like this
+# because it's simple.
+#
+class MaterialManager(QObject):
+
+ materialsUpdated = pyqtSignal() # Emitted whenever the material lookup tables are updated.
+
+ def __init__(self, container_registry, parent = None):
+ super().__init__(parent)
+ self._application = Application.getInstance()
+ self._container_registry = container_registry # type: ContainerRegistry
+
+ self._fallback_materials_map = dict() # material_type -> generic material metadata
+ self._material_group_map = dict() # root_material_id -> MaterialGroup
+ self._diameter_machine_variant_material_map = dict() # approximate diameter str -> dict(machine_definition_id -> MaterialNode)
+
+ # We're using these two maps to convert between the specific diameter material id and the generic material id
+ # because the generic material ids are used in qualities and definitions, while the specific diameter material is meant
+ # i.e. generic_pla -> generic_pla_175
+ self._material_diameter_map = defaultdict(dict) # root_material_id -> approximate diameter str -> root_material_id for that diameter
+ self._diameter_material_map = dict() # material id including diameter (generic_pla_175) -> material root id (generic_pla)
+
+ # This is used in Legacy UM3 send material function and the material management page.
+ self._guid_material_groups_map = defaultdict(list) # GUID -> a list of material_groups
+
+ # The machine definition ID for the non-machine-specific materials.
+ # This is used as the last fallback option if the given machine-specific material(s) cannot be found.
+ self._default_machine_definition_id = "fdmprinter"
+ self._default_approximate_diameter_for_quality_search = "3"
+
+ # When a material gets added/imported, there can be more than one InstanceContainers. In those cases, we don't
+ # want to react on every container/metadata changed signal. The timer here is to buffer it a bit so we don't
+ # react too many time.
+ self._update_timer = QTimer(self)
+ self._update_timer.setInterval(300)
+ self._update_timer.setSingleShot(True)
+ self._update_timer.timeout.connect(self._updateMaps)
+
+ self._container_registry.containerMetaDataChanged.connect(self._onContainerMetadataChanged)
+ self._container_registry.containerAdded.connect(self._onContainerMetadataChanged)
+ self._container_registry.containerRemoved.connect(self._onContainerMetadataChanged)
+
+ def initialize(self):
+ # Find all materials and put them in a matrix for quick search.
+ material_metadatas = {metadata["id"]: metadata for metadata in self._container_registry.findContainersMetadata(type = "material")}
+
+ self._material_group_map = dict()
+
+ # Map #1
+ # root_material_id -> MaterialGroup
+ for material_id, material_metadata in material_metadatas.items():
+ # We don't store empty material in the lookup tables
+ if material_id == "empty_material":
+ continue
+
+ root_material_id = material_metadata.get("base_file")
+ if root_material_id not in self._material_group_map:
+ self._material_group_map[root_material_id] = MaterialGroup(root_material_id, MaterialNode(material_metadatas[root_material_id]))
+ self._material_group_map[root_material_id].is_read_only = self._container_registry.isReadOnly(root_material_id)
+ group = self._material_group_map[root_material_id]
+
+ #Store this material in the group of the appropriate root material.
+ if material_id != root_material_id:
+ new_node = MaterialNode(material_metadata)
+ group.derived_material_node_list.append(new_node)
+
+ # Order this map alphabetically so it's easier to navigate in a debugger
+ self._material_group_map = OrderedDict(sorted(self._material_group_map.items(), key = lambda x: x[0]))
+
+ # Map #1.5
+ # GUID -> material group list
+ self._guid_material_groups_map = defaultdict(list)
+ for root_material_id, material_group in self._material_group_map.items():
+ guid = material_group.root_material_node.metadata["GUID"]
+ self._guid_material_groups_map[guid].append(material_group)
+
+ # Map #2
+ # Lookup table for material type -> fallback material metadata, only for read-only materials
+ grouped_by_type_dict = dict()
+ for root_material_id, material_node in self._material_group_map.items():
+ if not self._container_registry.isReadOnly(root_material_id):
+ continue
+ material_type = material_node.root_material_node.metadata["material"]
+ if material_type not in grouped_by_type_dict:
+ grouped_by_type_dict[material_type] = {"generic": None,
+ "others": []}
+ brand = material_node.root_material_node.metadata["brand"]
+ if brand.lower() == "generic":
+ to_add = True
+ if material_type in grouped_by_type_dict:
+ diameter = material_node.root_material_node.metadata.get("approximate_diameter")
+ if diameter != self._default_approximate_diameter_for_quality_search:
+ to_add = False # don't add if it's not the default diameter
+ if to_add:
+ grouped_by_type_dict[material_type] = material_node.root_material_node.metadata
+ self._fallback_materials_map = grouped_by_type_dict
+
+ # Map #3
+ # There can be multiple material profiles for the same material with different diameters, such as "generic_pla"
+ # and "generic_pla_175". This is inconvenient when we do material-specific quality lookup because a quality can
+ # be for either "generic_pla" or "generic_pla_175", but not both. This map helps to get the correct material ID
+ # for quality search.
+ self._material_diameter_map = defaultdict(dict)
+ self._diameter_material_map = dict()
+
+ # Group the material IDs by the same name, material, brand, and color but with different diameters.
+ material_group_dict = dict()
+ keys_to_fetch = ("name", "material", "brand", "color")
+ for root_material_id, machine_node in self._material_group_map.items():
+ if not self._container_registry.isReadOnly(root_material_id):
+ continue
+
+ root_material_metadata = machine_node.root_material_node.metadata
+
+ key_data = []
+ for key in keys_to_fetch:
+ key_data.append(root_material_metadata.get(key))
+ key_data = tuple(key_data)
+
+ if key_data not in material_group_dict:
+ material_group_dict[key_data] = dict()
+ approximate_diameter = root_material_metadata.get("approximate_diameter")
+ material_group_dict[key_data][approximate_diameter] = root_material_metadata["id"]
+
+ # Map [root_material_id][diameter] -> root_material_id for this diameter
+ for data_dict in material_group_dict.values():
+ for root_material_id1 in data_dict.values():
+ if root_material_id1 in self._material_diameter_map:
+ continue
+ diameter_map = data_dict
+ for root_material_id2 in data_dict.values():
+ self._material_diameter_map[root_material_id2] = diameter_map
+
+ default_root_material_id = data_dict.get(self._default_approximate_diameter_for_quality_search)
+ if default_root_material_id is None:
+ default_root_material_id = list(data_dict.values())[0] # no default diameter present, just take "the" only one
+ for root_material_id in data_dict.values():
+ self._diameter_material_map[root_material_id] = default_root_material_id
+
+ # Map #4
+ # "machine" -> "variant_name" -> "root material ID" -> specific material InstanceContainer
+ # Construct the "machine" -> "variant" -> "root material ID" -> specific material InstanceContainer
+ self._diameter_machine_variant_material_map = dict()
+ for material_metadata in material_metadatas.values():
+ # We don't store empty material in the lookup tables
+ if material_metadata["id"] == "empty_material":
+ continue
+
+ root_material_id = material_metadata["base_file"]
+ definition = material_metadata["definition"]
+ approximate_diameter = material_metadata["approximate_diameter"]
+
+ if approximate_diameter not in self._diameter_machine_variant_material_map:
+ self._diameter_machine_variant_material_map[approximate_diameter] = {}
+
+ machine_variant_material_map = self._diameter_machine_variant_material_map[approximate_diameter]
+ if definition not in machine_variant_material_map:
+ machine_variant_material_map[definition] = MaterialNode()
+
+ machine_node = machine_variant_material_map[definition]
+ variant_name = material_metadata.get("variant_name")
+ if not variant_name:
+ # if there is no variant, this material is for the machine, so put its metadata in the machine node.
+ machine_node.material_map[root_material_id] = MaterialNode(material_metadata)
+ else:
+ # this material is variant-specific, so we save it in a variant-specific node under the
+ # machine-specific node
+ if variant_name not in machine_node.children_map:
+ machine_node.children_map[variant_name] = MaterialNode()
+
+ variant_node = machine_node.children_map[variant_name]
+ if root_material_id not in variant_node.material_map:
+ variant_node.material_map[root_material_id] = MaterialNode(material_metadata)
+ else:
+ # Sanity check: make sure we don't have duplicated variant-specific materials for the same machine
+ raise RuntimeError("Found duplicate variant name [%s] for machine [%s] in material [%s]" %
+ (variant_name, definition, material_metadata["id"]))
+
+ self.materialsUpdated.emit()
+
+ def _updateMaps(self):
+ Logger.log("i", "Updating material lookup data ...")
+ self.initialize()
+
+ def _onContainerMetadataChanged(self, container):
+ self._onContainerChanged(container)
+
+ def _onContainerChanged(self, container):
+ container_type = container.getMetaDataEntry("type")
+ if container_type != "material":
+ return
+
+ # update the maps
+ self._update_timer.start()
+
+ def getMaterialGroup(self, root_material_id: str) -> Optional[MaterialGroup]:
+ return self._material_group_map.get(root_material_id)
+
+ def getRootMaterialIDForDiameter(self, root_material_id: str, approximate_diameter: str) -> str:
+ return self._material_diameter_map.get(root_material_id).get(approximate_diameter, root_material_id)
+
+ def getRootMaterialIDWithoutDiameter(self, root_material_id: str) -> str:
+ return self._diameter_material_map.get(root_material_id)
+
+ def getMaterialGroupListByGUID(self, guid: str) -> Optional[list]:
+ return self._guid_material_groups_map.get(guid)
+
+ #
+ # Return a dict with all root material IDs (k) and ContainerNodes (v) that's suitable for the given setup.
+ #
+ def getAvailableMaterials(self, machine_definition_id: str, extruder_variant_name: Optional[str],
+ diameter: float) -> dict:
+ # round the diameter to get the approximate diameter
+ rounded_diameter = str(round(diameter))
+ if rounded_diameter not in self._diameter_machine_variant_material_map:
+ Logger.log("i", "Cannot find materials with diameter [%s] (rounded to [%s])", diameter, rounded_diameter)
+ return dict()
+
+ # If there are variant materials, get the variant material
+ machine_variant_material_map = self._diameter_machine_variant_material_map[rounded_diameter]
+ machine_node = machine_variant_material_map.get(machine_definition_id)
+ default_machine_node = machine_variant_material_map.get(self._default_machine_definition_id)
+ variant_node = None
+ if extruder_variant_name is not None and machine_node is not None:
+ variant_node = machine_node.getChildNode(extruder_variant_name)
+
+ nodes_to_check = [variant_node, machine_node, default_machine_node]
+
+ # Fallback mechanism of finding materials:
+ # 1. variant-specific material
+ # 2. machine-specific material
+ # 3. generic material (for fdmprinter)
+ material_id_metadata_dict = dict()
+ for node in nodes_to_check:
+ if node is not None:
+ for material_id, node in node.material_map.items():
+ if material_id not in material_id_metadata_dict:
+ material_id_metadata_dict[material_id] = node
+
+ return material_id_metadata_dict
+
+ #
+ # A convenience function to get available materials for the given machine with the extruder position.
+ #
+ def getAvailableMaterialsForMachineExtruder(self, machine: "GlobalStack",
+ extruder_stack: "ExtruderStack") -> Optional[dict]:
+ machine_definition_id = machine.definition.getId()
+ variant_name = None
+ if extruder_stack.variant.getId() != "empty_variant":
+ variant_name = extruder_stack.variant.getName()
+ diameter = extruder_stack.approximateMaterialDiameter
+
+ # Fetch the available materials (ContainerNode) for the current active machine and extruder setup.
+ return self.getAvailableMaterials(machine_definition_id, variant_name, diameter)
+
+ #
+ # Gets MaterialNode for the given extruder and machine with the given material name.
+ # Returns None if:
+ # 1. the given machine doesn't have materials;
+ # 2. cannot find any material InstanceContainers with the given settings.
+ #
+ def getMaterialNode(self, machine_definition_id: str, extruder_variant_name: Optional[str],
+ diameter: float, root_material_id: str) -> Optional["InstanceContainer"]:
+ # round the diameter to get the approximate diameter
+ rounded_diameter = str(round(diameter))
+ if rounded_diameter not in self._diameter_machine_variant_material_map:
+ Logger.log("i", "Cannot find materials with diameter [%s] (rounded to [%s]) for root material id [%s]",
+ diameter, rounded_diameter, root_material_id)
+ return None
+
+ # If there are variant materials, get the variant material
+ machine_variant_material_map = self._diameter_machine_variant_material_map[rounded_diameter]
+ machine_node = machine_variant_material_map.get(machine_definition_id)
+ variant_node = None
+
+ # Fallback for "fdmprinter" if the machine-specific materials cannot be found
+ if machine_node is None:
+ machine_node = machine_variant_material_map.get(self._default_machine_definition_id)
+ if machine_node is not None and extruder_variant_name is not None:
+ variant_node = machine_node.getChildNode(extruder_variant_name)
+
+ # Fallback mechanism of finding materials:
+ # 1. variant-specific material
+ # 2. machine-specific material
+ # 3. generic material (for fdmprinter)
+ nodes_to_check = [variant_node, machine_node,
+ machine_variant_material_map.get(self._default_machine_definition_id)]
+
+ material_node = None
+ for node in nodes_to_check:
+ if node is not None:
+ material_node = node.material_map.get(root_material_id)
+ if material_node:
+ break
+
+ return material_node
+
+ #
+ # Gets MaterialNode for the given extruder and machine with the given material type.
+ # Returns None if:
+ # 1. the given machine doesn't have materials;
+ # 2. cannot find any material InstanceContainers with the given settings.
+ #
+ def getMaterialNodeByType(self, global_stack: "GlobalStack", extruder_variant_name: str, material_guid: str) -> Optional["MaterialNode"]:
+ node = None
+ machine_definition = global_stack.definition
+ if parseBool(machine_definition.getMetaDataEntry("has_materials", False)):
+ material_diameter = machine_definition.getProperty("material_diameter", "value")
+ if isinstance(material_diameter, SettingFunction):
+ material_diameter = material_diameter(global_stack)
+
+ # Look at the guid to material dictionary
+ root_material_id = None
+ for material_group in self._guid_material_groups_map[material_guid]:
+ if material_group.is_read_only:
+ root_material_id = material_group.root_material_node.metadata["id"]
+ break
+
+ if not root_material_id:
+ Logger.log("i", "Cannot find materials with guid [%s] ", material_guid)
+ return None
+
+ node = self.getMaterialNode(machine_definition.getId(), extruder_variant_name,
+ material_diameter, root_material_id)
+ return node
+
+ #
+ # Used by QualityManager. Built-in quality profiles may be based on generic material IDs such as "generic_pla".
+ # For materials such as ultimaker_pla_orange, no quality profiles may be found, so we should fall back to use
+ # the generic material IDs to search for qualities.
+ #
+ # An example would be, suppose we have machine with preferred material set to "filo3d_pla" (1.75mm), but its
+ # extruders only use 2.85mm materials, then we won't be able to find the preferred material for this machine.
+ # A fallback would be to fetch a generic material of the same type "PLA" as "filo3d_pla", and in this case it will
+ # be "generic_pla". This function is intended to get a generic fallback material for the given material type.
+ #
+ # This function returns the generic root material ID for the given material type, where material types are "PLA",
+ # "ABS", etc.
+ #
+ def getFallbackMaterialIdByMaterialType(self, material_type: str) -> Optional[str]:
+ # For safety
+ if material_type not in self._fallback_materials_map:
+ Logger.log("w", "The material type [%s] does not have a fallback material" % material_type)
+ return None
+ fallback_material = self._fallback_materials_map[material_type]
+ if fallback_material:
+ return self.getRootMaterialIDWithoutDiameter(fallback_material["id"])
+ else:
+ return None
+
+ def getDefaultMaterial(self, global_stack: "GlobalStack", extruder_variant_name: Optional[str]) -> Optional["MaterialNode"]:
+ node = None
+ machine_definition = global_stack.definition
+ if parseBool(global_stack.getMetaDataEntry("has_materials", False)):
+ material_diameter = machine_definition.getProperty("material_diameter", "value")
+ if isinstance(material_diameter, SettingFunction):
+ material_diameter = material_diameter(global_stack)
+ approximate_material_diameter = str(round(material_diameter))
+ root_material_id = machine_definition.getMetaDataEntry("preferred_material")
+ root_material_id = self.getRootMaterialIDForDiameter(root_material_id, approximate_material_diameter)
+ node = self.getMaterialNode(machine_definition.getId(), extruder_variant_name,
+ material_diameter, root_material_id)
+ return node
+
+ def removeMaterialByRootId(self, root_material_id: str):
+ material_group = self.getMaterialGroup(root_material_id)
+ if not material_group:
+ Logger.log("i", "Unable to remove the material with id %s, because it doesn't exist.", root_material_id)
+ return
+
+ nodes_to_remove = [material_group.root_material_node] + material_group.derived_material_node_list
+ for node in nodes_to_remove:
+ self._container_registry.removeContainer(node.metadata["id"])
+
+ #
+ # Methods for GUI
+ #
+
+ #
+ # Sets the new name for the given material.
+ #
+ @pyqtSlot("QVariant", str)
+ def setMaterialName(self, material_node: "MaterialNode", name: str):
+ root_material_id = material_node.metadata["base_file"]
+ if self._container_registry.isReadOnly(root_material_id):
+ Logger.log("w", "Cannot set name of read-only container %s.", root_material_id)
+ return
+
+ material_group = self.getMaterialGroup(root_material_id)
+ material_group.root_material_node.getContainer().setName(name)
+
+ #
+ # Removes the given material.
+ #
+ @pyqtSlot("QVariant")
+ def removeMaterial(self, material_node: "MaterialNode"):
+ root_material_id = material_node.metadata["base_file"]
+ self.removeMaterialByRootId(root_material_id)
+
+ #
+ # Creates a duplicate of a material, which has the same GUID and base_file metadata.
+ # Returns the root material ID of the duplicated material if successful.
+ #
+ @pyqtSlot("QVariant", result = str)
+ def duplicateMaterial(self, material_node, new_base_id = None, new_metadata = None) -> Optional[str]:
+ root_material_id = material_node.metadata["base_file"]
+
+ material_group = self.getMaterialGroup(root_material_id)
+ if not material_group:
+ Logger.log("i", "Unable to duplicate the material with id %s, because it doesn't exist.", root_material_id)
+ return None
+
+ base_container = material_group.root_material_node.getContainer()
+
+ # Ensure all settings are saved.
+ self._application.saveSettings()
+
+ # Create a new ID & container to hold the data.
+ new_containers = []
+ if new_base_id is None:
+ new_base_id = self._container_registry.uniqueName(base_container.getId())
+ new_base_container = copy.deepcopy(base_container)
+ new_base_container.getMetaData()["id"] = new_base_id
+ new_base_container.getMetaData()["base_file"] = new_base_id
+ if new_metadata is not None:
+ for key, value in new_metadata.items():
+ new_base_container.getMetaData()[key] = value
+ new_containers.append(new_base_container)
+
+ # Clone all of them.
+ for node in material_group.derived_material_node_list:
+ container_to_copy = node.getContainer()
+ # Create unique IDs for every clone.
+ new_id = new_base_id
+ if container_to_copy.getMetaDataEntry("definition") != "fdmprinter":
+ new_id += "_" + container_to_copy.getMetaDataEntry("definition")
+ if container_to_copy.getMetaDataEntry("variant_name"):
+ variant_name = container_to_copy.getMetaDataEntry("variant_name")
+ new_id += "_" + variant_name.replace(" ", "_")
+
+ new_container = copy.deepcopy(container_to_copy)
+ new_container.getMetaData()["id"] = new_id
+ new_container.getMetaData()["base_file"] = new_base_id
+ if new_metadata is not None:
+ for key, value in new_metadata.items():
+ new_container.getMetaData()[key] = value
+
+ new_containers.append(new_container)
+
+ for container_to_add in new_containers:
+ container_to_add.setDirty(True)
+ self._container_registry.addContainer(container_to_add)
+ return new_base_id
+
+ #
+ # Create a new material by cloning Generic PLA for the current material diameter and generate a new GUID.
+ #
+ @pyqtSlot(result = str)
+ def createMaterial(self) -> str:
+ from UM.i18n import i18nCatalog
+ catalog = i18nCatalog("cura")
+ # Ensure all settings are saved.
+ self._application.saveSettings()
+
+ global_stack = self._application.getGlobalContainerStack()
+ approximate_diameter = str(round(global_stack.getProperty("material_diameter", "value")))
+ root_material_id = "generic_pla"
+ root_material_id = self.getRootMaterialIDForDiameter(root_material_id, approximate_diameter)
+ material_group = self.getMaterialGroup(root_material_id)
+
+ # Create a new ID & container to hold the data.
+ new_id = self._container_registry.uniqueName("custom_material")
+ new_metadata = {"name": catalog.i18nc("@label", "Custom Material"),
+ "brand": catalog.i18nc("@label", "Custom"),
+ "GUID": str(uuid.uuid4()),
+ }
+
+ self.duplicateMaterial(material_group.root_material_node,
+ new_base_id = new_id,
+ new_metadata = new_metadata)
+ return new_id
diff --git a/cura/Machines/MaterialNode.py b/cura/Machines/MaterialNode.py
new file mode 100644
index 0000000000..fde11186c2
--- /dev/null
+++ b/cura/Machines/MaterialNode.py
@@ -0,0 +1,21 @@
+# Copyright (c) 2018 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+
+from typing import Optional
+
+from .ContainerNode import ContainerNode
+
+
+#
+# A MaterialNode is a node in the material lookup tree/map/table. It contains 2 (extra) fields:
+# - material_map: a one-to-one map of "material_root_id" to material_node.
+# - children_map: the key-value map for child nodes of this node. This is used in a lookup tree.
+#
+#
+class MaterialNode(ContainerNode):
+ __slots__ = ("material_map", "children_map")
+
+ def __init__(self, metadata: Optional[dict] = None):
+ super().__init__(metadata = metadata)
+ self.material_map = {} # material_root_id -> material_node
+ self.children_map = {} # mapping for the child nodes
diff --git a/cura/Machines/Models/BaseMaterialsModel.py b/cura/Machines/Models/BaseMaterialsModel.py
new file mode 100644
index 0000000000..0a1337feeb
--- /dev/null
+++ b/cura/Machines/Models/BaseMaterialsModel.py
@@ -0,0 +1,68 @@
+# 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 UM.Application import Application
+from UM.Qt.ListModel import ListModel
+
+
+#
+# This is the base model class for GenericMaterialsModel and BrandMaterialsModel
+# 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
+#
+class BaseMaterialsModel(ListModel):
+ RootMaterialIdRole = Qt.UserRole + 1
+ IdRole = Qt.UserRole + 2
+ NameRole = Qt.UserRole + 3
+ BrandRole = Qt.UserRole + 4
+ MaterialRole = Qt.UserRole + 5
+ ColorRole = Qt.UserRole + 6
+ ContainerNodeRole = Qt.UserRole + 7
+
+ extruderPositionChanged = pyqtSignal()
+
+ def __init__(self, parent = None):
+ super().__init__(parent)
+ self._application = Application.getInstance()
+ self._machine_manager = self._application.getMachineManager()
+
+ self.addRoleName(self.RootMaterialIdRole, "root_material_id")
+ self.addRoleName(self.IdRole, "id")
+ self.addRoleName(self.NameRole, "name")
+ self.addRoleName(self.BrandRole, "brand")
+ self.addRoleName(self.MaterialRole, "material")
+ self.addRoleName(self.ColorRole, "color_name")
+ self.addRoleName(self.ContainerNodeRole, "container_node")
+
+ self._extruder_position = 0
+ self._extruder_stack = None
+
+ def _updateExtruderStack(self):
+ global_stack = self._machine_manager.activeMachine
+ if global_stack is None:
+ return
+
+ if self._extruder_stack is not None:
+ self._extruder_stack.pyqtContainersChanged.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)
+
+ def setExtruderPosition(self, position: int):
+ if self._extruder_position != position:
+ self._extruder_position = position
+ self._updateExtruderStack()
+ self.extruderPositionChanged.emit()
+
+ @pyqtProperty(int, fset = setExtruderPosition, notify = extruderPositionChanged)
+ def extruderPosition(self) -> int:
+ return self._extruder_position
+
+ #
+ # This is an abstract method that needs to be implemented by
+ #
+ def _update(self):
+ pass
diff --git a/cura/Machines/Models/BrandMaterialsModel.py b/cura/Machines/Models/BrandMaterialsModel.py
new file mode 100644
index 0000000000..f6c9a14632
--- /dev/null
+++ b/cura/Machines/Models/BrandMaterialsModel.py
@@ -0,0 +1,137 @@
+# 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 UM.Qt.ListModel import ListModel
+from UM.Logger import Logger
+from cura.Machines.Models.BaseMaterialsModel import BaseMaterialsModel
+
+
+#
+# This is an intermediate model to group materials with different colours for a same brand and type.
+#
+class MaterialsModelGroupedByType(ListModel):
+ NameRole = Qt.UserRole + 1
+ ColorsRole = Qt.UserRole + 2
+
+ def __init__(self, parent = None):
+ super().__init__(parent)
+
+ self.addRoleName(self.NameRole, "name")
+ self.addRoleName(self.ColorsRole, "colors")
+
+
+#
+# This model is used to show branded materials in the material drop down menu.
+# The structure of the menu looks like this:
+# Brand -> Material Type -> list of materials
+#
+# To illustrate, a branded material menu may look like this:
+# Ultimaker -> PLA -> Yellow PLA
+# -> Black PLA
+# -> ...
+# -> ABS -> White ABS
+# ...
+#
+class BrandMaterialsModel(ListModel):
+ NameRole = Qt.UserRole + 1
+ MaterialsRole = Qt.UserRole + 2
+
+ extruderPositionChanged = pyqtSignal()
+
+ def __init__(self, parent = None):
+ super().__init__(parent)
+
+ self.addRoleName(self.NameRole, "name")
+ self.addRoleName(self.MaterialsRole, "materials")
+
+ self._extruder_position = 0
+
+ from cura.CuraApplication import CuraApplication
+ self._machine_manager = CuraApplication.getInstance().getMachineManager()
+ self._extruder_manager = CuraApplication.getInstance().getExtruderManager()
+ self._material_manager = CuraApplication.getInstance().getMaterialManager()
+
+ self._machine_manager.activeStackChanged.connect(self._update) #Update when switching machines.
+ self._material_manager.materialsUpdated.connect(self._update) #Update when the list of materials changes.
+ self._update()
+
+ def setExtruderPosition(self, position: int):
+ if self._extruder_position != position:
+ self._extruder_position = position
+ self.extruderPositionChanged.emit()
+
+ @pyqtProperty(int, fset = setExtruderPosition, notify = extruderPositionChanged)
+ def extruderPosition(self) -> int:
+ return self._extruder_position
+
+ def _update(self):
+ Logger.log("d", "Updating {model_class_name}.".format(model_class_name = self.__class__.__name__))
+ global_stack = self._machine_manager.activeMachine
+ if global_stack is None:
+ self.setItems([])
+ return
+ extruder_position = str(self._extruder_position)
+ if extruder_position not in global_stack.extruders:
+ self.setItems([])
+ return
+ extruder_stack = global_stack.extruders[str(self._extruder_position)]
+
+ available_material_dict = self._material_manager.getAvailableMaterialsForMachineExtruder(global_stack,
+ extruder_stack)
+ if available_material_dict is None:
+ self.setItems([])
+ return
+
+ brand_item_list = []
+ brand_group_dict = {}
+ for root_material_id, container_node in available_material_dict.items():
+ metadata = container_node.metadata
+ brand = metadata["brand"]
+ # Only add results for generic materials
+ if brand.lower() == "generic":
+ continue
+
+ if brand not in brand_group_dict:
+ brand_group_dict[brand] = {}
+
+ material_type = metadata["material"]
+ if material_type not in brand_group_dict[brand]:
+ brand_group_dict[brand][material_type] = []
+
+ item = {"root_material_id": root_material_id,
+ "id": metadata["id"],
+ "name": metadata["name"],
+ "brand": metadata["brand"],
+ "material": metadata["material"],
+ "color_name": metadata["color_name"],
+ "container_node": container_node
+ }
+ brand_group_dict[brand][material_type].append(item)
+
+ for brand, material_dict in brand_group_dict.items():
+ brand_item = {"name": brand,
+ "materials": MaterialsModelGroupedByType(self)}
+
+ material_type_item_list = []
+ for material_type, material_list in material_dict.items():
+ material_type_item = {"name": material_type,
+ "colors": BaseMaterialsModel(self)}
+ material_type_item["colors"].clear()
+
+ # Sort materials by name
+ material_list = sorted(material_list, key = lambda x: x["name"].upper())
+ material_type_item["colors"].setItems(material_list)
+
+ material_type_item_list.append(material_type_item)
+
+ # Sort material type by name
+ material_type_item_list = sorted(material_type_item_list, key = lambda x: x["name"].upper())
+ brand_item["materials"].setItems(material_type_item_list)
+
+ brand_item_list.append(brand_item)
+
+ # Sort brand by name
+ brand_item_list = sorted(brand_item_list, key = lambda x: x["name"].upper())
+ self.setItems(brand_item_list)
diff --git a/cura/Machines/Models/BuildPlateModel.py b/cura/Machines/Models/BuildPlateModel.py
new file mode 100644
index 0000000000..e1b4f40d8e
--- /dev/null
+++ b/cura/Machines/Models/BuildPlateModel.py
@@ -0,0 +1,51 @@
+# Copyright (c) 2018 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+
+from PyQt5.QtCore import Qt
+
+from UM.Application import Application
+from UM.Logger import Logger
+from UM.Qt.ListModel import ListModel
+from UM.Util import parseBool
+
+from cura.Machines.VariantManager import VariantType
+
+
+class BuildPlateModel(ListModel):
+ NameRole = Qt.UserRole + 1
+ ContainerNodeRole = Qt.UserRole + 2
+
+ def __init__(self, parent = None):
+ super().__init__(parent)
+
+ self.addRoleName(self.NameRole, "name")
+ self.addRoleName(self.ContainerNodeRole, "container_node")
+
+ self._application = Application.getInstance()
+ self._variant_manager = self._application._variant_manager
+ self._machine_manager = self._application.getMachineManager()
+
+ self._machine_manager.globalContainerChanged.connect(self._update)
+
+ self._update()
+
+ def _update(self):
+ Logger.log("d", "Updating {model_class_name}.".format(model_class_name = self.__class__.__name__))
+ global_stack = self._machine_manager._global_container_stack
+ if not global_stack:
+ self.setItems([])
+ return
+
+ has_variants = parseBool(global_stack.getMetaDataEntry("has_variant_buildplates", False))
+ if not has_variants:
+ self.setItems([])
+ return
+
+ variant_dict = self._variant_manager.getVariantNodes(global_stack, variant_type = VariantType.BUILD_PLATE)
+
+ item_list = []
+ for name, variant_node in variant_dict.items():
+ item = {"name": name,
+ "container_node": variant_node}
+ item_list.append(item)
+ self.setItems(item_list)
diff --git a/cura/Machines/Models/CustomQualityProfilesDropDownMenuModel.py b/cura/Machines/Models/CustomQualityProfilesDropDownMenuModel.py
new file mode 100644
index 0000000000..dcade8cb0d
--- /dev/null
+++ b/cura/Machines/Models/CustomQualityProfilesDropDownMenuModel.py
@@ -0,0 +1,37 @@
+# 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.QualityProfilesDropDownMenuModel import QualityProfilesDropDownMenuModel
+
+
+#
+# This model is used for the custom profile items in the profile drop down menu.
+#
+class CustomQualityProfilesDropDownMenuModel(QualityProfilesDropDownMenuModel):
+
+ def _update(self):
+ Logger.log("d", "Updating {model_class_name}.".format(model_class_name = self.__class__.__name__))
+
+ active_global_stack = self._machine_manager.activeMachine
+ if active_global_stack is None:
+ self.setItems([])
+ Logger.log("d", "No active GlobalStack, set %s as empty.", self.__class__.__name__)
+ return
+
+ quality_changes_group_dict = self._quality_manager.getQualityChangesGroups(active_global_stack)
+
+ item_list = []
+ for key in sorted(quality_changes_group_dict, key = lambda name: name.upper()):
+ quality_changes_group = quality_changes_group_dict[key]
+
+ item = {"name": quality_changes_group.name,
+ "layer_height": "",
+ "layer_height_without_unit": "",
+ "available": quality_changes_group.is_available,
+ "quality_changes_group": quality_changes_group}
+
+ item_list.append(item)
+
+ self.setItems(item_list)
diff --git a/cura/Machines/Models/GenericMaterialsModel.py b/cura/Machines/Models/GenericMaterialsModel.py
new file mode 100644
index 0000000000..2fac919f3e
--- /dev/null
+++ b/cura/Machines/Models/GenericMaterialsModel.py
@@ -0,0 +1,61 @@
+# 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):
+
+ def __init__(self, parent = None):
+ super().__init__(parent)
+
+ from cura.CuraApplication import CuraApplication
+ self._machine_manager = CuraApplication.getInstance().getMachineManager()
+ self._extruder_manager = CuraApplication.getInstance().getExtruderManager()
+ self._material_manager = CuraApplication.getInstance().getMaterialManager()
+
+ self._machine_manager.activeStackChanged.connect(self._update) #Update when switching machines.
+ self._material_manager.materialsUpdated.connect(self._update) #Update when the list of materials changes.
+ self._update()
+
+ def _update(self):
+ Logger.log("d", "Updating {model_class_name}.".format(model_class_name = self.__class__.__name__))
+
+ global_stack = self._machine_manager.activeMachine
+ if global_stack is None:
+ self.setItems([])
+ return
+ extruder_position = str(self._extruder_position)
+ if extruder_position not in global_stack.extruders:
+ self.setItems([])
+ return
+ extruder_stack = global_stack.extruders[extruder_position]
+
+ available_material_dict = self._material_manager.getAvailableMaterialsForMachineExtruder(global_stack,
+ extruder_stack)
+ if available_material_dict is None:
+ self.setItems([])
+ return
+
+ item_list = []
+ for root_material_id, container_node in available_material_dict.items():
+ metadata = container_node.metadata
+ # Only add results for generic materials
+ if metadata["brand"].lower() != "generic":
+ continue
+
+ item = {"root_material_id": root_material_id,
+ "id": metadata["id"],
+ "name": metadata["name"],
+ "brand": metadata["brand"],
+ "material": metadata["material"],
+ "color_name": metadata["color_name"],
+ "container_node": container_node
+ }
+ item_list.append(item)
+
+ # Sort the item list by material name alphabetically
+ item_list = sorted(item_list, key = lambda d: d["name"].upper())
+
+ self.setItems(item_list)
diff --git a/cura/Machines/Models/MachineManagementModel.py b/cura/Machines/Models/MachineManagementModel.py
new file mode 100644
index 0000000000..481a692675
--- /dev/null
+++ b/cura/Machines/Models/MachineManagementModel.py
@@ -0,0 +1,79 @@
+# 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 pyqtSlot, pyqtProperty, Qt, pyqtSignal
+
+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):
+ 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 printes
+ 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/MaterialManagementModel.py b/cura/Machines/Models/MaterialManagementModel.py
new file mode 100644
index 0000000000..46e9cb887a
--- /dev/null
+++ b/cura/Machines/Models/MaterialManagementModel.py
@@ -0,0 +1,104 @@
+# Copyright (c) 2018 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+
+from PyQt5.QtCore import Qt
+
+from UM.Logger import Logger
+from UM.Qt.ListModel import ListModel
+
+
+#
+# This model is for the Material management page.
+#
+class MaterialManagementModel(ListModel):
+ RootMaterialIdRole = Qt.UserRole + 1
+ DisplayNameRole = Qt.UserRole + 2
+ BrandRole = Qt.UserRole + 3
+ MaterialTypeRole = Qt.UserRole + 4
+ ColorNameRole = Qt.UserRole + 5
+ ColorCodeRole = Qt.UserRole + 6
+ ContainerNodeRole = Qt.UserRole + 7
+ ContainerIdRole = Qt.UserRole + 8
+
+ DescriptionRole = Qt.UserRole + 9
+ AdhesionInfoRole = Qt.UserRole + 10
+ ApproximateDiameterRole = Qt.UserRole + 11
+ GuidRole = Qt.UserRole + 12
+ DensityRole = Qt.UserRole + 13
+ DiameterRole = Qt.UserRole + 14
+ IsReadOnlyRole = Qt.UserRole + 15
+
+ def __init__(self, parent = None):
+ super().__init__(parent)
+
+ self.addRoleName(self.RootMaterialIdRole, "root_material_id")
+ self.addRoleName(self.DisplayNameRole, "name")
+ self.addRoleName(self.BrandRole, "brand")
+ self.addRoleName(self.MaterialTypeRole, "material")
+ self.addRoleName(self.ColorNameRole, "color_name")
+ self.addRoleName(self.ColorCodeRole, "color_code")
+ self.addRoleName(self.ContainerNodeRole, "container_node")
+ self.addRoleName(self.ContainerIdRole, "container_id")
+
+ self.addRoleName(self.DescriptionRole, "description")
+ self.addRoleName(self.AdhesionInfoRole, "adhesion_info")
+ self.addRoleName(self.ApproximateDiameterRole, "approximate_diameter")
+ self.addRoleName(self.GuidRole, "guid")
+ self.addRoleName(self.DensityRole, "density")
+ self.addRoleName(self.DiameterRole, "diameter")
+ self.addRoleName(self.IsReadOnlyRole, "is_read_only")
+
+ from cura.CuraApplication import CuraApplication
+ self._container_registry = CuraApplication.getInstance().getContainerRegistry()
+ self._machine_manager = CuraApplication.getInstance().getMachineManager()
+ self._extruder_manager = CuraApplication.getInstance().getExtruderManager()
+ self._material_manager = CuraApplication.getInstance().getMaterialManager()
+
+ self._machine_manager.globalContainerChanged.connect(self._update)
+ self._extruder_manager.activeExtruderChanged.connect(self._update)
+ self._material_manager.materialsUpdated.connect(self._update)
+
+ self._update()
+
+ def _update(self):
+ Logger.log("d", "Updating {model_class_name}.".format(model_class_name = self.__class__.__name__))
+
+ global_stack = self._machine_manager.activeMachine
+ if global_stack is None:
+ self.setItems([])
+ return
+ active_extruder_stack = self._machine_manager.activeStack
+
+ available_material_dict = self._material_manager.getAvailableMaterialsForMachineExtruder(global_stack,
+ active_extruder_stack)
+ if available_material_dict is None:
+ self.setItems([])
+ return
+
+ material_list = []
+ for root_material_id, container_node in available_material_dict.items():
+ keys_to_fetch = ("name",
+ "brand",
+ "material",
+ "color_name",
+ "color_code",
+ "description",
+ "adhesion_info",
+ "approximate_diameter",)
+
+ item = {"root_material_id": container_node.metadata["base_file"],
+ "container_node": container_node,
+ "guid": container_node.metadata["GUID"],
+ "container_id": container_node.metadata["id"],
+ "density": container_node.metadata.get("properties", {}).get("density", ""),
+ "diameter": container_node.metadata.get("properties", {}).get("diameter", ""),
+ "is_read_only": self._container_registry.isReadOnly(container_node.metadata["id"]),
+ }
+
+ for key in keys_to_fetch:
+ item[key] = container_node.metadata.get(key, "")
+
+ material_list.append(item)
+
+ material_list = sorted(material_list, key = lambda k: (k["brand"].upper(), k["name"].upper()))
+ self.setItems(material_list)
diff --git a/cura/BuildPlateModel.py b/cura/Machines/Models/MultiBuildPlateModel.py
similarity index 60%
rename from cura/BuildPlateModel.py
rename to cura/Machines/Models/MultiBuildPlateModel.py
index 73f61202c6..958e93837a 100644
--- a/cura/BuildPlateModel.py
+++ b/cura/Machines/Models/MultiBuildPlateModel.py
@@ -1,24 +1,37 @@
-from PyQt5.QtCore import pyqtSignal, pyqtProperty, pyqtSlot
+# Copyright (c) 2018 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+
+from PyQt5.QtCore import QTimer, pyqtSignal, pyqtProperty
-from UM.Qt.ListModel import ListModel
-from UM.Scene.Selection import Selection
-from UM.Logger import Logger
from UM.Application import Application
+from UM.Scene.Selection import Selection
+from UM.Qt.ListModel import ListModel
-class BuildPlateModel(ListModel):
+#
+# This is the model for multi build plate feature.
+# This has nothing to do with the build plate types you can choose on the sidebar for a machine.
+#
+class MultiBuildPlateModel(ListModel):
+
maxBuildPlateChanged = pyqtSignal()
activeBuildPlateChanged = pyqtSignal()
selectionChanged = pyqtSignal()
- def __init__(self):
- super().__init__()
- Application.getInstance().getController().getScene().sceneChanged.connect(self._updateSelectedObjectBuildPlateNumbers)
+ def __init__(self, parent = None):
+ super().__init__(parent)
+
+ self._update_timer = QTimer()
+ self._update_timer.setInterval(100)
+ self._update_timer.setSingleShot(True)
+ self._update_timer.timeout.connect(self._updateSelectedObjectBuildPlateNumbers)
+
+ self._application = Application.getInstance()
+ self._application.getController().getScene().sceneChanged.connect(self._updateSelectedObjectBuildPlateNumbersDelayed)
Selection.selectionChanged.connect(self._updateSelectedObjectBuildPlateNumbers)
self._max_build_plate = 1 # default
self._active_build_plate = -1
- self._selection_build_plates = []
def setMaxBuildPlate(self, max_build_plate):
self._max_build_plate = max_build_plate
@@ -37,9 +50,8 @@ class BuildPlateModel(ListModel):
def activeBuildPlate(self):
return self._active_build_plate
- @staticmethod
- def createBuildPlateModel():
- return BuildPlateModel()
+ def _updateSelectedObjectBuildPlateNumbersDelayed(self, *args):
+ self._update_timer.start()
def _updateSelectedObjectBuildPlateNumbers(self, *args):
result = set()
diff --git a/cura/Machines/Models/NozzleModel.py b/cura/Machines/Models/NozzleModel.py
new file mode 100644
index 0000000000..0879998b7d
--- /dev/null
+++ b/cura/Machines/Models/NozzleModel.py
@@ -0,0 +1,61 @@
+# Copyright (c) 2018 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+
+from PyQt5.QtCore import Qt
+
+from UM.Application import Application
+from UM.Logger import Logger
+from UM.Qt.ListModel import ListModel
+from UM.Util import parseBool
+
+
+class NozzleModel(ListModel):
+ IdRole = Qt.UserRole + 1
+ HotendNameRole = Qt.UserRole + 2
+ ContainerNodeRole = Qt.UserRole + 3
+
+ def __init__(self, parent = None):
+ super().__init__(parent)
+
+ self.addRoleName(self.IdRole, "id")
+ self.addRoleName(self.HotendNameRole, "hotend_name")
+ self.addRoleName(self.ContainerNodeRole, "container_node")
+
+ self._application = Application.getInstance()
+ self._machine_manager = self._application.getMachineManager()
+ self._variant_manager = self._application.getVariantManager()
+
+ self._machine_manager.globalContainerChanged.connect(self._update)
+ self._update()
+
+ 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([])
+ return
+
+ has_variants = parseBool(global_stack.getMetaDataEntry("has_variants", False))
+ if not has_variants:
+ self.setItems([])
+ return
+
+ from cura.Machines.VariantManager import VariantType
+ variant_node_dict = self._variant_manager.getVariantNodes(global_stack, VariantType.NOZZLE)
+ if not variant_node_dict:
+ self.setItems([])
+ return
+
+ item_list = []
+ for hotend_name, container_node in sorted(variant_node_dict.items(), key = lambda i: i[0].upper()):
+ item = {"id": hotend_name,
+ "hotend_name": hotend_name,
+ "container_node": container_node
+ }
+
+ item_list.append(item)
+
+ self.setItems(item_list)
diff --git a/cura/Machines/Models/QualityManagementModel.py b/cura/Machines/Models/QualityManagementModel.py
new file mode 100644
index 0000000000..4d2b551805
--- /dev/null
+++ b/cura/Machines/Models/QualityManagementModel.py
@@ -0,0 +1,124 @@
+# Copyright (c) 2018 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+
+from PyQt5.QtCore import Qt, pyqtSlot
+
+from UM.Qt.ListModel import ListModel
+from UM.Logger import Logger
+
+#
+# This the QML model for the quality management page.
+#
+class QualityManagementModel(ListModel):
+ NameRole = Qt.UserRole + 1
+ IsReadOnlyRole = Qt.UserRole + 2
+ QualityGroupRole = Qt.UserRole + 3
+ QualityChangesGroupRole = Qt.UserRole + 4
+
+ def __init__(self, parent = None):
+ super().__init__(parent)
+
+ self.addRoleName(self.NameRole, "name")
+ self.addRoleName(self.IsReadOnlyRole, "is_read_only")
+ self.addRoleName(self.QualityGroupRole, "quality_group")
+ self.addRoleName(self.QualityChangesGroupRole, "quality_changes_group")
+
+ from cura.CuraApplication import CuraApplication
+ self._container_registry = CuraApplication.getInstance().getContainerRegistry()
+ self._machine_manager = CuraApplication.getInstance().getMachineManager()
+ self._extruder_manager = CuraApplication.getInstance().getExtruderManager()
+ self._quality_manager = CuraApplication.getInstance().getQualityManager()
+
+ self._machine_manager.globalContainerChanged.connect(self._update)
+ self._quality_manager.qualitiesUpdated.connect(self._update)
+
+ self._update()
+
+ def _update(self):
+ Logger.log("d", "Updating {model_class_name}.".format(model_class_name = self.__class__.__name__))
+
+ global_stack = self._machine_manager.activeMachine
+
+ quality_group_dict = self._quality_manager.getQualityGroups(global_stack)
+ quality_changes_group_dict = self._quality_manager.getQualityChangesGroups(global_stack)
+
+ available_quality_types = set(quality_type for quality_type, quality_group in quality_group_dict.items()
+ if quality_group.is_available)
+ if not available_quality_types and not quality_changes_group_dict:
+ # Nothing to show
+ self.setItems([])
+ return
+
+ item_list = []
+ # Create quality group items
+ for quality_group in quality_group_dict.values():
+ if not quality_group.is_available:
+ continue
+
+ item = {"name": quality_group.name,
+ "is_read_only": True,
+ "quality_group": quality_group,
+ "quality_changes_group": None}
+ item_list.append(item)
+ # Sort by quality names
+ item_list = sorted(item_list, key = lambda x: x["name"].upper())
+
+ # Create quality_changes group items
+ quality_changes_item_list = []
+ for quality_changes_group in quality_changes_group_dict.values():
+ if quality_changes_group.quality_type not in available_quality_types:
+ continue
+ quality_group = quality_group_dict[quality_changes_group.quality_type]
+ item = {"name": quality_changes_group.name,
+ "is_read_only": False,
+ "quality_group": quality_group,
+ "quality_changes_group": quality_changes_group}
+ quality_changes_item_list.append(item)
+
+ # Sort quality_changes items by names and append to the item list
+ quality_changes_item_list = sorted(quality_changes_item_list, key = lambda x: x["name"].upper())
+ item_list += quality_changes_item_list
+
+ self.setItems(item_list)
+
+ # TODO: Duplicated code here from InstanceContainersModel. Refactor and remove this later.
+ #
+ ## Gets a list of the possible file filters that the plugins have
+ # registered they can read or write. The convenience meta-filters
+ # "All Supported Types" and "All Files" are added when listing
+ # readers, but not when listing writers.
+ #
+ # \param io_type \type{str} name of the needed IO type
+ # \return A list of strings indicating file name filters for a file
+ # dialog.
+ @pyqtSlot(str, result = "QVariantList")
+ def getFileNameFilters(self, io_type):
+ from UM.i18n import i18nCatalog
+ catalog = i18nCatalog("uranium")
+ #TODO: This function should be in UM.Resources!
+ filters = []
+ all_types = []
+ for plugin_id, meta_data in self._getIOPlugins(io_type):
+ for io_plugin in meta_data[io_type]:
+ filters.append(io_plugin["description"] + " (*." + io_plugin["extension"] + ")")
+ all_types.append("*.{0}".format(io_plugin["extension"]))
+
+ if "_reader" in io_type:
+ # if we're listing readers, add the option to show all supported files as the default option
+ filters.insert(0, catalog.i18nc("@item:inlistbox", "All Supported Types ({0})", " ".join(all_types)))
+ filters.append(catalog.i18nc("@item:inlistbox", "All Files (*)")) # Also allow arbitrary files, if the user so prefers.
+ return filters
+
+ ## Gets a list of profile reader or writer plugins
+ # \return List of tuples of (plugin_id, meta_data).
+ def _getIOPlugins(self, io_type):
+ from UM.PluginRegistry import PluginRegistry
+ pr = PluginRegistry.getInstance()
+ active_plugin_ids = pr.getActivePlugins()
+
+ result = []
+ for plugin_id in active_plugin_ids:
+ meta_data = pr.getMetaData(plugin_id)
+ if io_type in meta_data:
+ result.append( (plugin_id, meta_data) )
+ return result
diff --git a/cura/Machines/Models/QualityProfilesDropDownMenuModel.py b/cura/Machines/Models/QualityProfilesDropDownMenuModel.py
new file mode 100644
index 0000000000..d8c4b668cf
--- /dev/null
+++ b/cura/Machines/Models/QualityProfilesDropDownMenuModel.py
@@ -0,0 +1,107 @@
+# Copyright (c) 2018 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+
+from PyQt5.QtCore import Qt
+
+from UM.Application import Application
+from UM.Logger import Logger
+from UM.Qt.ListModel import ListModel
+
+from cura.Machines.QualityManager import QualityGroup
+
+
+#
+# QML Model for all built-in quality profiles. This model is used for the drop-down quality menu.
+#
+class QualityProfilesDropDownMenuModel(ListModel):
+ NameRole = Qt.UserRole + 1
+ QualityTypeRole = Qt.UserRole + 2
+ LayerHeightRole = Qt.UserRole + 3
+ LayerHeightUnitRole = Qt.UserRole + 4
+ AvailableRole = Qt.UserRole + 5
+ QualityGroupRole = Qt.UserRole + 6
+ QualityChangesGroupRole = Qt.UserRole + 7
+
+ def __init__(self, parent = None):
+ super().__init__(parent)
+
+ self.addRoleName(self.NameRole, "name")
+ self.addRoleName(self.QualityTypeRole, "quality_type")
+ self.addRoleName(self.LayerHeightRole, "layer_height")
+ self.addRoleName(self.LayerHeightUnitRole, "layer_height_unit")
+ 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._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._layer_height_unit = "" # This is cached
+
+ self._update()
+
+ def _update(self):
+ Logger.log("d", "Updating {model_class_name}.".format(model_class_name = self.__class__.__name__))
+
+ global_stack = self._machine_manager.activeMachine
+ if global_stack is None:
+ self.setItems([])
+ Logger.log("d", "No active GlobalStack, set quality profile model as empty.")
+ return
+
+ # Check for material compatibility
+ if not self._machine_manager.activeMaterialsCompatible():
+ Logger.log("d", "No active material compatibility, set quality profile model as empty.")
+ self.setItems([])
+ return
+
+ quality_group_dict = self._quality_manager.getQualityGroups(global_stack)
+
+ item_list = []
+ for key in sorted(quality_group_dict):
+ quality_group = quality_group_dict[key]
+
+ layer_height = self._fetchLayerHeight(quality_group)
+
+ item = {"name": quality_group.name,
+ "quality_type": quality_group.quality_type,
+ "layer_height": layer_height,
+ "layer_height_unit": self._layer_height_unit,
+ "available": quality_group.is_available,
+ "quality_group": quality_group}
+
+ item_list.append(item)
+
+ # Sort items based on layer_height
+ item_list = sorted(item_list, key = lambda x: x["layer_height"])
+
+ self.setItems(item_list)
+
+ def _fetchLayerHeight(self, quality_group: "QualityGroup"):
+ global_stack = self._machine_manager.activeMachine
+ if not self._layer_height_unit:
+ unit = global_stack.definition.getProperty("layer_height", "unit")
+ if not unit:
+ unit = ""
+ self._layer_height_unit = unit
+
+ default_layer_height = global_stack.definition.getProperty("layer_height", "value")
+
+ # Get layer_height from the quality profile for the GlobalStack
+ container = quality_group.node_for_global.getContainer()
+
+ layer_height = default_layer_height
+ if container.hasProperty("layer_height", "value"):
+ layer_height = container.getProperty("layer_height", "value")
+ else:
+ # Look for layer_height in the GlobalStack from material -> definition
+ container = global_stack.definition
+ if container.hasProperty("layer_height", "value"):
+ layer_height = container.getProperty("layer_height", "value")
+ return float(layer_height)
diff --git a/cura/Machines/Models/QualitySettingsModel.py b/cura/Machines/Models/QualitySettingsModel.py
new file mode 100644
index 0000000000..b38f6f65c8
--- /dev/null
+++ b/cura/Machines/Models/QualitySettingsModel.py
@@ -0,0 +1,164 @@
+# Copyright (c) 2018 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+
+from PyQt5.QtCore import pyqtProperty, pyqtSignal, Qt
+
+from UM.Application import Application
+from UM.Logger import Logger
+from UM.Qt.ListModel import ListModel
+from UM.Settings.ContainerRegistry import ContainerRegistry
+
+
+#
+# This model is used to show details settings of the selected quality in the quality management page.
+#
+class QualitySettingsModel(ListModel):
+ KeyRole = Qt.UserRole + 1
+ LabelRole = Qt.UserRole + 2
+ UnitRole = Qt.UserRole + 3
+ ProfileValueRole = Qt.UserRole + 4
+ ProfileValueSourceRole = Qt.UserRole + 5
+ UserValueRole = Qt.UserRole + 6
+ CategoryRole = Qt.UserRole + 7
+
+ GLOBAL_STACK_POSITION = -1
+
+ def __init__(self, parent = None):
+ super().__init__(parent = parent)
+
+ self.addRoleName(self.KeyRole, "key")
+ self.addRoleName(self.LabelRole, "label")
+ self.addRoleName(self.UnitRole, "unit")
+ self.addRoleName(self.ProfileValueRole, "profile_value")
+ self.addRoleName(self.ProfileValueSourceRole, "profile_value_source")
+ self.addRoleName(self.UserValueRole, "user_value")
+ self.addRoleName(self.CategoryRole, "category")
+
+ self._container_registry = ContainerRegistry.getInstance()
+ self._application = Application.getInstance()
+ self._quality_manager = self._application.getQualityManager()
+
+ self._selected_position = self.GLOBAL_STACK_POSITION #Must be either GLOBAL_STACK_POSITION or an extruder position (0, 1, etc.)
+ self._selected_quality_item = None # The selected quality in the quality management page
+ self._i18n_catalog = None
+
+ self._quality_manager.qualitiesUpdated.connect(self._update)
+
+ self._update()
+
+ selectedPositionChanged = pyqtSignal()
+ selectedQualityItemChanged = pyqtSignal()
+
+ def setSelectedPosition(self, selected_position):
+ if selected_position != self._selected_position:
+ self._selected_position = selected_position
+ self.selectedPositionChanged.emit()
+ self._update()
+
+ @pyqtProperty(int, fset = setSelectedPosition, notify = selectedPositionChanged)
+ def selectedPosition(self):
+ return self._selected_position
+
+ def setSelectedQualityItem(self, selected_quality_item):
+ if selected_quality_item != self._selected_quality_item:
+ self._selected_quality_item = selected_quality_item
+ self.selectedQualityItemChanged.emit()
+ self._update()
+
+ @pyqtProperty("QVariantMap", fset = setSelectedQualityItem, notify = selectedQualityItemChanged)
+ def selectedQualityItem(self):
+ return self._selected_quality_item
+
+ def _update(self):
+ Logger.log("d", "Updating {model_class_name}.".format(model_class_name = self.__class__.__name__))
+
+ if not self._selected_quality_item:
+ self.setItems([])
+ return
+
+ items = []
+
+ global_container_stack = self._application.getGlobalContainerStack()
+ definition_container = global_container_stack.definition
+
+ quality_group = self._selected_quality_item["quality_group"]
+ quality_changes_group = self._selected_quality_item["quality_changes_group"]
+
+ if self._selected_position == self.GLOBAL_STACK_POSITION:
+ quality_node = quality_group.node_for_global
+ else:
+ quality_node = quality_group.nodes_for_extruders.get(str(self._selected_position))
+ settings_keys = quality_group.getAllKeys()
+ quality_containers = []
+ if quality_node is not None:
+ quality_containers.append(quality_node.getContainer())
+
+ # Here, if the user has selected a quality changes, then "quality_changes_group" will not be None, and we fetch
+ # the settings in that quality_changes_group.
+ if quality_changes_group is not None:
+ if self._selected_position == self.GLOBAL_STACK_POSITION:
+ quality_changes_node = quality_changes_group.node_for_global
+ else:
+ quality_changes_node = quality_changes_group.nodes_for_extruders.get(str(self._selected_position))
+ if quality_changes_node is not None: # it can be None if number of extruders are changed during runtime
+ try:
+ quality_containers.insert(0, quality_changes_node.getContainer())
+ except RuntimeError:
+ # FIXME: This is to prevent incomplete update of QualityManager
+ Logger.logException("d", "Failed to get container for quality changes node %s", quality_changes_node)
+ return
+ settings_keys.update(quality_changes_group.getAllKeys())
+
+ # We iterate over all definitions instead of settings in a quality/qualtiy_changes group is because in the GUI,
+ # the settings are grouped together by categories, and we had to go over all the definitions to figure out
+ # which setting belongs in which category.
+ current_category = ""
+ for definition in definition_container.findDefinitions():
+ if definition.type == "category":
+ current_category = definition.label
+ if self._i18n_catalog:
+ current_category = self._i18n_catalog.i18nc(definition.key + " label", definition.label)
+ continue
+
+ profile_value = None
+ profile_value_source = ""
+ for quality_container in quality_containers:
+ new_value = quality_container.getProperty(definition.key, "value")
+
+ if new_value is not None:
+ profile_value_source = quality_container.getMetaDataEntry("type")
+ profile_value = new_value
+
+ # Global tab should use resolve (if there is one)
+ if self._selected_position == self.GLOBAL_STACK_POSITION:
+ resolve_value = global_container_stack.getProperty(definition.key, "resolve")
+ if resolve_value is not None and definition.key in settings_keys:
+ profile_value = resolve_value
+
+ if profile_value is not None:
+ break
+
+ if self._selected_position == self.GLOBAL_STACK_POSITION:
+ user_value = global_container_stack.userChanges.getProperty(definition.key, "value")
+ else:
+ extruder_stack = global_container_stack.extruders[str(self._selected_position)]
+ user_value = extruder_stack.userChanges.getProperty(definition.key, "value")
+
+ if profile_value is None and user_value is None:
+ continue
+
+ label = definition.label
+ if self._i18n_catalog:
+ label = self._i18n_catalog.i18nc(definition.key + " label", label)
+
+ items.append({
+ "key": definition.key,
+ "label": label,
+ "unit": definition.unit,
+ "profile_value": "" if profile_value is None else str(profile_value), # it is for display only
+ "profile_value_source": profile_value_source,
+ "user_value": "" if user_value is None else str(user_value),
+ "category": current_category
+ })
+
+ self.setItems(items)
diff --git a/cura/Machines/Models/__init__.py b/cura/Machines/Models/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/cura/Machines/QualityChangesGroup.py b/cura/Machines/QualityChangesGroup.py
new file mode 100644
index 0000000000..ad320a7006
--- /dev/null
+++ b/cura/Machines/QualityChangesGroup.py
@@ -0,0 +1,27 @@
+# Copyright (c) 2018 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+
+from UM.Application import Application
+
+from .QualityGroup import QualityGroup
+
+
+class QualityChangesGroup(QualityGroup):
+ def __init__(self, name: str, quality_type: str, parent = None):
+ super().__init__(name, quality_type, parent)
+ self._container_registry = Application.getInstance().getContainerRegistry()
+
+ def addNode(self, node: "QualityNode"):
+ extruder_position = node.metadata.get("position")
+ if extruder_position is None: #Then we're a global quality changes profile.
+ if self.node_for_global is not None:
+ raise RuntimeError("{group} tries to overwrite the existing node_for_global {original_global} with {new_global}".format(group = self, original_global = self.node_for_global, new_global = node))
+ self.node_for_global = node
+ else: #This is an extruder's quality changes profile.
+ if extruder_position in self.nodes_for_extruders:
+ raise RuntimeError("%s tries to overwrite the existing nodes_for_extruders position [%s] %s with %s" %
+ (self, extruder_position, self.node_for_global, node))
+ self.nodes_for_extruders[extruder_position] = node
+
+ def __str__(self) -> str:
+ return "%s[<%s>, available = %s]" % (self.__class__.__name__, self.name, self.is_available)
diff --git a/cura/Machines/QualityGroup.py b/cura/Machines/QualityGroup.py
new file mode 100644
index 0000000000..02096cfb36
--- /dev/null
+++ b/cura/Machines/QualityGroup.py
@@ -0,0 +1,50 @@
+# Copyright (c) 2018 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+
+from typing import Dict, Optional, List
+
+from PyQt5.QtCore import QObject, pyqtSlot
+
+
+#
+# A QualityGroup represents a group of containers that must be applied to each ContainerStack when it's used.
+# Some concrete examples are Quality and QualityChanges: when we select quality type "normal", this quality type
+# must be applied to all stacks in a machine, although each stack can have different containers. Use an Ultimaker 3
+# as an example, suppose we choose quality type "normal", the actual InstanceContainers on each stack may look
+# as below:
+# GlobalStack ExtruderStack 1 ExtruderStack 2
+# quality container: um3_global_normal um3_aa04_pla_normal um3_aa04_abs_normal
+#
+# This QualityGroup is mainly used in quality and quality_changes to group the containers that can be applied to
+# a machine, so when a quality/custom quality is selected, the container can be directly applied to each stack instead
+# of looking them up again.
+#
+class QualityGroup(QObject):
+
+ def __init__(self, name: str, quality_type: str, parent = None):
+ super().__init__(parent)
+ self.name = name
+ self.node_for_global = None # type: Optional["QualityGroup"]
+ self.nodes_for_extruders = {} # type: Dict[int, "QualityGroup"]
+ self.quality_type = quality_type
+ self.is_available = False
+
+ @pyqtSlot(result = str)
+ def getName(self) -> str:
+ return self.name
+
+ def getAllKeys(self) -> set:
+ result = set()
+ for node in [self.node_for_global] + list(self.nodes_for_extruders.values()):
+ if node is None:
+ continue
+ result.update(node.getContainer().getAllKeys())
+ return result
+
+ def getAllNodes(self) -> List["QualityGroup"]:
+ result = []
+ if self.node_for_global is not None:
+ result.append(self.node_for_global)
+ for extruder_node in self.nodes_for_extruders.values():
+ result.append(extruder_node)
+ return result
diff --git a/cura/Machines/QualityManager.py b/cura/Machines/QualityManager.py
new file mode 100644
index 0000000000..8d972c9192
--- /dev/null
+++ b/cura/Machines/QualityManager.py
@@ -0,0 +1,493 @@
+# Copyright (c) 2018 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+
+from typing import TYPE_CHECKING, Optional
+
+from PyQt5.QtCore import QObject, QTimer, pyqtSignal, pyqtSlot
+
+from UM.Application import Application
+from UM.Logger import Logger
+from UM.Util import parseBool
+from UM.Settings.InstanceContainer import InstanceContainer
+
+from cura.Settings.ExtruderStack import ExtruderStack
+
+from .QualityGroup import QualityGroup
+from .QualityNode import QualityNode
+
+if TYPE_CHECKING:
+ from UM.Settings.DefinitionContainer import DefinitionContainer
+ from cura.Settings.GlobalStack import GlobalStack
+ from .QualityChangesGroup import QualityChangesGroup
+
+
+#
+# Similar to MaterialManager, QualityManager maintains a number of maps and trees for quality profile lookup.
+# The models GUI and QML use are now only dependent on the QualityManager. That means as long as the data in
+# QualityManager gets updated correctly, the GUI models should be updated correctly too, and the same goes for GUI.
+#
+# For now, updating the lookup maps and trees here is very simple: we discard the old data completely and recreate them
+# again. This means the update is exactly the same as initialization. There are performance concerns about this approach
+# but so far the creation of the tables and maps is very fast and there is no noticeable slowness, we keep it like this
+# because it's simple.
+#
+class QualityManager(QObject):
+
+ qualitiesUpdated = pyqtSignal()
+
+ def __init__(self, container_registry, parent = None):
+ super().__init__(parent)
+ self._application = Application.getInstance()
+ self._material_manager = self._application.getMaterialManager()
+ self._container_registry = container_registry
+
+ self._empty_quality_container = self._application.empty_quality_container
+ self._empty_quality_changes_container = self._application.empty_quality_changes_container
+
+ self._machine_variant_material_quality_type_to_quality_dict = {} # for quality lookup
+ self._machine_quality_type_to_quality_changes_dict = {} # for quality_changes lookup
+
+ self._default_machine_definition_id = "fdmprinter"
+
+ self._container_registry.containerMetaDataChanged.connect(self._onContainerMetadataChanged)
+ self._container_registry.containerAdded.connect(self._onContainerMetadataChanged)
+ self._container_registry.containerRemoved.connect(self._onContainerMetadataChanged)
+
+ # When a custom quality gets added/imported, there can be more than one InstanceContainers. In those cases,
+ # we don't want to react on every container/metadata changed signal. The timer here is to buffer it a bit so
+ # we don't react too many time.
+ self._update_timer = QTimer(self)
+ self._update_timer.setInterval(300)
+ self._update_timer.setSingleShot(True)
+ self._update_timer.timeout.connect(self._updateMaps)
+
+ def initialize(self):
+ # Initialize the lookup tree for quality profiles with following structure:
+ # -> ->
+ # ->
+
+ self._machine_variant_material_quality_type_to_quality_dict = {} # for quality lookup
+ self._machine_quality_type_to_quality_changes_dict = {} # for quality_changes lookup
+
+ quality_metadata_list = self._container_registry.findContainersMetadata(type = "quality")
+ for metadata in quality_metadata_list:
+ if metadata["id"] == "empty_quality":
+ continue
+
+ definition_id = metadata["definition"]
+ quality_type = metadata["quality_type"]
+
+ root_material_id = metadata.get("material")
+ variant_name = metadata.get("variant")
+ is_global_quality = metadata.get("global_quality", False)
+ is_global_quality = is_global_quality or (root_material_id is None and variant_name is None)
+
+ # Sanity check: material+variant and is_global_quality cannot be present at the same time
+ if is_global_quality and (root_material_id or variant_name):
+ raise RuntimeError("Quality profile [%s] contains invalid data: it is a global quality but contains 'material' and 'nozzle' info." % metadata["id"])
+
+ if definition_id not in self._machine_variant_material_quality_type_to_quality_dict:
+ self._machine_variant_material_quality_type_to_quality_dict[definition_id] = QualityNode()
+ machine_node = self._machine_variant_material_quality_type_to_quality_dict[definition_id]
+
+ if is_global_quality:
+ # For global qualities, save data in the machine node
+ machine_node.addQualityMetadata(quality_type, metadata)
+ continue
+
+ if variant_name is not None:
+ # If variant_name is specified in the quality/quality_changes profile, check if material is specified,
+ # too.
+ if variant_name not in machine_node.children_map:
+ machine_node.children_map[variant_name] = QualityNode()
+ variant_node = machine_node.children_map[variant_name]
+
+ if root_material_id is None:
+ # If only variant_name is specified but material is not, add the quality/quality_changes metadata
+ # into the current variant node.
+ variant_node.addQualityMetadata(quality_type, metadata)
+ else:
+ # If only variant_name and material are both specified, go one level deeper: create a material node
+ # under the current variant node, and then add the quality/quality_changes metadata into the
+ # material node.
+ if root_material_id not in variant_node.children_map:
+ variant_node.children_map[root_material_id] = QualityNode()
+ material_node = variant_node.children_map[root_material_id]
+
+ material_node.addQualityMetadata(quality_type, metadata)
+
+ else:
+ # If variant_name is not specified, check if material is specified.
+ if root_material_id is not None:
+ if root_material_id not in machine_node.children_map:
+ machine_node.children_map[root_material_id] = QualityNode()
+ material_node = machine_node.children_map[root_material_id]
+
+ material_node.addQualityMetadata(quality_type, metadata)
+
+ # Initialize the lookup tree for quality_changes profiles with following structure:
+ # -> ->
+ quality_changes_metadata_list = self._container_registry.findContainersMetadata(type = "quality_changes")
+ for metadata in quality_changes_metadata_list:
+ if metadata["id"] == "empty_quality_changes":
+ continue
+
+ machine_definition_id = metadata["definition"]
+ quality_type = metadata["quality_type"]
+
+ if machine_definition_id not in self._machine_quality_type_to_quality_changes_dict:
+ self._machine_quality_type_to_quality_changes_dict[machine_definition_id] = QualityNode()
+ machine_node = self._machine_quality_type_to_quality_changes_dict[machine_definition_id]
+ machine_node.addQualityChangesMetadata(quality_type, metadata)
+
+ Logger.log("d", "Lookup tables updated.")
+ self.qualitiesUpdated.emit()
+
+ def _updateMaps(self):
+ self.initialize()
+
+ def _onContainerMetadataChanged(self, container):
+ self._onContainerChanged(container)
+
+ def _onContainerChanged(self, container):
+ container_type = container.getMetaDataEntry("type")
+ if container_type not in ("quality", "quality_changes"):
+ return
+
+ # update the cache table
+ self._update_timer.start()
+
+ # Updates the given quality groups' availabilities according to which extruders are being used/ enabled.
+ def _updateQualityGroupsAvailability(self, machine: "GlobalStack", quality_group_list):
+ used_extruders = set()
+ for i in range(machine.getProperty("machine_extruder_count", "value")):
+ if machine.extruders[str(i)].isEnabled:
+ used_extruders.add(str(i))
+
+ # Update the "is_available" flag for each quality group.
+ for quality_group in quality_group_list:
+ is_available = True
+ if quality_group.node_for_global is None:
+ is_available = False
+ if is_available:
+ for position in used_extruders:
+ if position not in quality_group.nodes_for_extruders:
+ is_available = False
+ break
+
+ quality_group.is_available = is_available
+
+ # Returns a dict of "custom profile name" -> QualityChangesGroup
+ def getQualityChangesGroups(self, machine: "GlobalStack") -> dict:
+ machine_definition_id = getMachineDefinitionIDForQualitySearch(machine.definition)
+
+ machine_node = self._machine_quality_type_to_quality_changes_dict.get(machine_definition_id)
+ if not machine_node:
+ Logger.log("i", "Cannot find node for machine def [%s] in QualityChanges lookup table", machine_definition_id)
+ return dict()
+
+ # Update availability for each QualityChangesGroup:
+ # A custom profile is always available as long as the quality_type it's based on is available
+ quality_group_dict = self.getQualityGroups(machine)
+ available_quality_type_list = [qt for qt, qg in quality_group_dict.items() if qg.is_available]
+
+ # Iterate over all quality_types in the machine node
+ quality_changes_group_dict = dict()
+ for quality_type, quality_changes_node in machine_node.quality_type_map.items():
+ for quality_changes_name, quality_changes_group in quality_changes_node.children_map.items():
+ quality_changes_group_dict[quality_changes_name] = quality_changes_group
+ quality_changes_group.is_available = quality_type in available_quality_type_list
+
+ return quality_changes_group_dict
+
+ #
+ # Gets all quality groups for the given machine. Both available and none available ones will be included.
+ # It returns a dictionary with "quality_type"s as keys and "QualityGroup"s as values.
+ # Whether a QualityGroup is available can be unknown via the field QualityGroup.is_available.
+ # For more details, see QualityGroup.
+ #
+ def getQualityGroups(self, machine: "GlobalStack") -> dict:
+ 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_variant_materials = parseBool(machine.getMetaDataEntry("has_variant_materials", False))
+
+ # 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_variant_material_quality_type_to_quality_dict.get(machine_definition_id)
+ default_machine_node = self._machine_variant_material_quality_type_to_quality_dict.get(self._default_machine_definition_id)
+ nodes_to_check = [machine_node, default_machine_node]
+
+ # Iterate over all quality_types in the machine node
+ quality_group_dict = {}
+ for node in nodes_to_check:
+ if node and node.quality_type_map:
+ # Only include global qualities
+ if has_variant_materials:
+ quality_node = list(node.quality_type_map.values())[0]
+ is_global_quality = parseBool(quality_node.metadata.get("global_quality", False))
+ if not is_global_quality:
+ continue
+
+ for quality_type, quality_node in node.quality_type_map.items():
+ quality_group = QualityGroup(quality_node.metadata["name"], quality_type)
+ quality_group.node_for_global = quality_node
+ quality_group_dict[quality_type] = quality_group
+ break
+
+ # Iterate over all extruders to find quality containers for each extruder
+ for position, extruder in machine.extruders.items():
+ variant_name = None
+ if extruder.variant.getId() != "empty_variant":
+ variant_name = extruder.variant.getName()
+
+ # This is a list of root material IDs to use for searching for suitable quality profiles.
+ # The root material IDs in this list are in prioritized order.
+ root_material_id_list = []
+ has_material = False # flag indicating whether this extruder has a material assigned
+ if extruder.material.getId() != "empty_material":
+ has_material = True
+ root_material_id = extruder.material.getMetaDataEntry("base_file")
+ # Convert possible generic_pla_175 -> generic_pla
+ root_material_id = self._material_manager.getRootMaterialIDWithoutDiameter(root_material_id)
+ root_material_id_list.append(root_material_id)
+
+ # Also try to get the fallback 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)
+
+ # Here we construct a list of nodes we want to look for qualities with the highest priority first.
+ # The use case is that, when we look for qualities for a machine, we first want to search in the following
+ # order:
+ # 1. machine-variant-and-material-specific qualities if exist
+ # 2. machine-variant-specific qualities if exist
+ # 3. machine-material-specific qualities if exist
+ # 4. machine-specific qualities if exist
+ # 5. generic qualities if exist
+ # Each points above can be represented as a node in the lookup tree, so here we simply put those nodes into
+ # the list with priorities as the order. Later, we just need to loop over each node in this list and fetch
+ # qualities from there.
+ nodes_to_check = []
+
+ if variant_name:
+ # In this case, we have both a specific variant and a specific material
+ variant_node = machine_node.getChildNode(variant_name)
+ if variant_node and has_material:
+ for root_material_id in root_material_id_list:
+ material_node = variant_node.getChildNode(root_material_id)
+ if material_node:
+ nodes_to_check.append(material_node)
+ break
+ nodes_to_check.append(variant_node)
+
+ # In this case, we only have a specific material but NOT a variant
+ if has_material:
+ for root_material_id in root_material_id_list:
+ material_node = machine_node.getChildNode(root_material_id)
+ if material_node:
+ nodes_to_check.append(material_node)
+ break
+
+ nodes_to_check += [machine_node, default_machine_node]
+ for node in nodes_to_check:
+ if node and node.quality_type_map:
+ if has_variant_materials:
+ # Only include variant qualities; skip non global qualities
+ quality_node = list(node.quality_type_map.values())[0]
+ is_global_quality = parseBool(quality_node.metadata.get("global_quality", False))
+ if is_global_quality:
+ continue
+
+ for quality_type, quality_node in node.quality_type_map.items():
+ if quality_type not in quality_group_dict:
+ quality_group = QualityGroup(quality_node.metadata["name"], quality_type)
+ quality_group_dict[quality_type] = quality_group
+
+ quality_group = quality_group_dict[quality_type]
+ quality_group.nodes_for_extruders[position] = quality_node
+ break
+
+ # Update availabilities for each quality group
+ self._updateQualityGroupsAvailability(machine, quality_group_dict.values())
+
+ return quality_group_dict
+
+ def getQualityGroupsForMachineDefinition(self, machine: "GlobalStack") -> dict:
+ machine_definition_id = getMachineDefinitionIDForQualitySearch(machine.definition)
+
+ # To find the quality container for the GlobalStack, check in the following fall-back manner:
+ # (1) the machine-specific node
+ # (2) the generic node
+ machine_node = self._machine_variant_material_quality_type_to_quality_dict.get(machine_definition_id)
+ default_machine_node = self._machine_variant_material_quality_type_to_quality_dict.get(
+ self._default_machine_definition_id)
+ nodes_to_check = [machine_node, default_machine_node]
+
+ # Iterate over all quality_types in the machine node
+ quality_group_dict = dict()
+ for node in nodes_to_check:
+ if node and node.quality_type_map:
+ for quality_type, quality_node in node.quality_type_map.items():
+ quality_group = QualityGroup(quality_node.metadata["name"], quality_type)
+ quality_group.node_for_global = quality_node
+ quality_group_dict[quality_type] = quality_group
+ break
+
+ return quality_group_dict
+
+ #
+ # Methods for GUI
+ #
+
+ #
+ # Remove the given quality changes group.
+ #
+ @pyqtSlot(QObject)
+ def removeQualityChangesGroup(self, quality_changes_group: "QualityChangesGroup"):
+ Logger.log("i", "Removing quality changes group [%s]", quality_changes_group.name)
+ for node in quality_changes_group.getAllNodes():
+ self._container_registry.removeContainer(node.metadata["id"])
+
+ #
+ # Rename a set of quality changes containers. Returns the new name.
+ #
+ @pyqtSlot(QObject, str, result = str)
+ def renameQualityChangesGroup(self, quality_changes_group: "QualityChangesGroup", new_name: str) -> str:
+ Logger.log("i", "Renaming QualityChangesGroup[%s] to [%s]", quality_changes_group.name, new_name)
+ if new_name == quality_changes_group.name:
+ Logger.log("i", "QualityChangesGroup name [%s] unchanged.", quality_changes_group.name)
+ return new_name
+
+ new_name = self._container_registry.uniqueName(new_name)
+ for node in quality_changes_group.getAllNodes():
+ node.getContainer().setName(new_name)
+
+ quality_changes_group.name = new_name
+
+ self._application.getMachineManager().activeQualityChanged.emit()
+ self._application.getMachineManager().activeQualityGroupChanged.emit()
+
+ return new_name
+
+ #
+ # Duplicates the given quality.
+ #
+ @pyqtSlot(str, "QVariantMap")
+ def duplicateQualityChanges(self, quality_changes_name, quality_model_item):
+ global_stack = self._application.getGlobalContainerStack()
+ if not global_stack:
+ Logger.log("i", "No active global stack, cannot duplicate quality changes.")
+ return
+
+ quality_group = quality_model_item["quality_group"]
+ quality_changes_group = quality_model_item["quality_changes_group"]
+ if quality_changes_group is None:
+ # create global quality changes only
+ new_quality_changes = self._createQualityChanges(quality_group.quality_type, quality_changes_name,
+ global_stack, None)
+ self._container_registry.addContainer(new_quality_changes)
+ else:
+ new_name = self._container_registry.uniqueName(quality_changes_name)
+ for node in quality_changes_group.getAllNodes():
+ container = node.getContainer()
+ new_id = self._container_registry.uniqueName(container.getId())
+ self._container_registry.addContainer(container.duplicate(new_id, new_name))
+
+ ## Create quality changes containers from the user containers in the active stacks.
+ #
+ # This will go through the global and extruder stacks and create quality_changes containers from
+ # the user containers in each stack. These then replace the quality_changes containers in the
+ # stack and clear the user settings.
+ @pyqtSlot(str)
+ def createQualityChanges(self, base_name):
+ machine_manager = Application.getInstance().getMachineManager()
+
+ global_stack = machine_manager.activeMachine
+ if not global_stack:
+ return
+
+ active_quality_name = machine_manager.activeQualityOrQualityChangesName
+ if active_quality_name == "":
+ Logger.log("w", "No quality container found in stack %s, cannot create profile", global_stack.getId())
+ return
+
+ machine_manager.blurSettings.emit()
+ if base_name is None or base_name == "":
+ base_name = active_quality_name
+ unique_name = self._container_registry.uniqueName(base_name)
+
+ # Go through the active stacks and create quality_changes containers from the user containers.
+ stack_list = [global_stack] + list(global_stack.extruders.values())
+ for stack in stack_list:
+ user_container = stack.userChanges
+ quality_container = stack.quality
+ quality_changes_container = stack.qualityChanges
+ if not quality_container or not quality_changes_container:
+ Logger.log("w", "No quality or quality changes container found in stack %s, ignoring it", stack.getId())
+ continue
+
+ quality_type = quality_container.getMetaDataEntry("quality_type")
+ extruder_stack = None
+ if isinstance(stack, ExtruderStack):
+ extruder_stack = stack
+ new_changes = self._createQualityChanges(quality_type, unique_name, global_stack, extruder_stack)
+ from cura.Settings.ContainerManager import ContainerManager
+ ContainerManager.getInstance()._performMerge(new_changes, quality_changes_container, clear_settings = False)
+ ContainerManager.getInstance()._performMerge(new_changes, user_container)
+
+ self._container_registry.addContainer(new_changes)
+
+ #
+ # Create a quality changes container with the given setup.
+ #
+ def _createQualityChanges(self, quality_type: str, new_name: str, machine: "GlobalStack",
+ extruder_stack: Optional["ExtruderStack"]) -> "InstanceContainer":
+ base_id = machine.definition.getId() if extruder_stack is None else extruder_stack.getId()
+ new_id = base_id + "_" + new_name
+ new_id = new_id.lower().replace(" ", "_")
+ new_id = self._container_registry.uniqueName(new_id)
+
+ # Create a new quality_changes container for the quality.
+ quality_changes = InstanceContainer(new_id)
+ quality_changes.setName(new_name)
+ quality_changes.addMetaDataEntry("type", "quality_changes")
+ quality_changes.addMetaDataEntry("quality_type", quality_type)
+
+ # If we are creating a container for an extruder, ensure we add that to the container
+ if extruder_stack is not None:
+ quality_changes.addMetaDataEntry("position", extruder_stack.getMetaDataEntry("position"))
+
+ # If the machine specifies qualities should be filtered, ensure we match the current criteria.
+ machine_definition_id = getMachineDefinitionIDForQualitySearch(machine.definition)
+ quality_changes.setDefinition(machine_definition_id)
+
+ quality_changes.addMetaDataEntry("setting_version", self._application.SettingVersion)
+ return quality_changes
+
+
+#
+# Gets the machine definition ID that can be used to search for Quality containers that are suitable for the given
+# machine. The rule is as follows:
+# 1. By default, the machine definition ID for quality container search will be "fdmprinter", which is the generic
+# machine.
+# 2. If a machine has its own machine quality (with "has_machine_quality = True"), we should use the given machine's
+# own machine definition ID for quality search.
+# Example: for an Ultimaker 3, the definition ID should be "ultimaker3".
+# 3. When condition (2) is met, AND the machine has "quality_definition" defined in its definition file, then the
+# definition ID specified in "quality_definition" should be used.
+# Example: for an Ultimaker 3 Extended, it has "quality_definition = ultimaker3". This means Ultimaker 3 Extended
+# shares the same set of qualities profiles as Ultimaker 3.
+#
+def getMachineDefinitionIDForQualitySearch(machine_definition: "DefinitionContainer",
+ default_definition_id: str = "fdmprinter") -> str:
+ machine_definition_id = default_definition_id
+ if parseBool(machine_definition.getMetaDataEntry("has_machine_quality", False)):
+ # Only use the machine's own quality definition ID if this machine has machine quality.
+ machine_definition_id = machine_definition.getMetaDataEntry("quality_definition")
+ if machine_definition_id is None:
+ machine_definition_id = machine_definition.getId()
+
+ return machine_definition_id
diff --git a/cura/Machines/QualityNode.py b/cura/Machines/QualityNode.py
new file mode 100644
index 0000000000..a30e219da3
--- /dev/null
+++ b/cura/Machines/QualityNode.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 Optional
+
+from .ContainerNode import ContainerNode
+from .QualityChangesGroup import QualityChangesGroup
+
+
+#
+# QualityNode is used for BOTH quality and quality_changes containers.
+#
+class QualityNode(ContainerNode):
+
+ def __init__(self, metadata: Optional[dict] = None):
+ super().__init__(metadata = metadata)
+ self.quality_type_map = {} # quality_type -> QualityNode for InstanceContainer
+
+ def addQualityMetadata(self, quality_type: str, metadata: dict):
+ if quality_type not in self.quality_type_map:
+ self.quality_type_map[quality_type] = QualityNode(metadata)
+
+ def getQualityNode(self, quality_type: str) -> Optional["QualityNode"]:
+ return self.quality_type_map.get(quality_type)
+
+ def addQualityChangesMetadata(self, quality_type: str, metadata: dict):
+ if quality_type not in self.quality_type_map:
+ self.quality_type_map[quality_type] = QualityNode()
+ quality_type_node = self.quality_type_map[quality_type]
+
+ name = metadata["name"]
+ if name not in quality_type_node.children_map:
+ quality_type_node.children_map[name] = QualityChangesGroup(name, quality_type)
+ quality_changes_group = quality_type_node.children_map[name]
+ quality_changes_group.addNode(QualityNode(metadata))
diff --git a/cura/Machines/VariantManager.py b/cura/Machines/VariantManager.py
new file mode 100644
index 0000000000..4e033e054e
--- /dev/null
+++ b/cura/Machines/VariantManager.py
@@ -0,0 +1,145 @@
+# Copyright (c) 2018 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+
+from enum import Enum
+from collections import OrderedDict
+from typing import Optional, TYPE_CHECKING
+
+from UM.Logger import Logger
+from UM.Settings.ContainerRegistry import ContainerRegistry
+from UM.Util import parseBool
+
+from cura.Machines.ContainerNode import ContainerNode
+from cura.Settings.GlobalStack import GlobalStack
+
+if TYPE_CHECKING:
+ from UM.Settings.DefinitionContainer import DefinitionContainer
+
+
+class VariantType(Enum):
+ BUILD_PLATE = "buildplate"
+ NOZZLE = "nozzle"
+
+
+ALL_VARIANT_TYPES = (VariantType.BUILD_PLATE, VariantType.NOZZLE)
+
+
+#
+# VariantManager is THE place to look for a specific variant. It maintains two variant lookup tables with the following
+# structure:
+#
+# [machine_definition_id] -> [variant_type] -> [variant_name] -> ContainerNode(metadata / container)
+# Example: "ultimaker3" -> "buildplate" -> "Glass" (if present) -> ContainerNode
+# -> ...
+# -> "nozzle" -> "AA 0.4"
+# -> "BB 0.8"
+# -> ...
+#
+# [machine_definition_id] -> [machine_buildplate_type] -> ContainerNode(metadata / container)
+# Example: "ultimaker3" -> "glass" (this is different from the variant name) -> ContainerNode
+#
+# Note that the "container" field is not loaded in the beginning because it would defeat the purpose of lazy-loading.
+# A container is loaded when getVariant() is called to load a variant InstanceContainer.
+#
+class VariantManager:
+
+ def __init__(self, container_registry):
+ self._container_registry = container_registry # type: ContainerRegistry
+
+ self._machine_to_variant_dict_map = dict() # ->
+ self._machine_to_buildplate_dict_map = dict()
+
+ self._exclude_variant_id_list = ["empty_variant"]
+
+ #
+ # Initializes the VariantManager including:
+ # - initializing the variant lookup table based on the metadata in ContainerRegistry.
+ #
+ def initialize(self):
+ self._machine_to_variant_dict_map = OrderedDict()
+ self._machine_to_buildplate_dict_map = OrderedDict()
+
+ # Cache all variants from the container registry to a variant map for better searching and organization.
+ variant_metadata_list = self._container_registry.findContainersMetadata(type = "variant")
+ for variant_metadata in variant_metadata_list:
+ if variant_metadata["id"] in self._exclude_variant_id_list:
+ Logger.log("d", "Exclude variant [%s]", variant_metadata["id"])
+ continue
+
+ variant_name = variant_metadata["name"]
+ variant_definition = variant_metadata["definition"]
+ if variant_definition not in self._machine_to_variant_dict_map:
+ self._machine_to_variant_dict_map[variant_definition] = OrderedDict()
+ for variant_type in ALL_VARIANT_TYPES:
+ self._machine_to_variant_dict_map[variant_definition][variant_type] = dict()
+
+ variant_type = variant_metadata["hardware_type"]
+ variant_type = VariantType(variant_type)
+ variant_dict = self._machine_to_variant_dict_map[variant_definition][variant_type]
+ if variant_name in variant_dict:
+ # ERROR: duplicated variant name.
+ raise RuntimeError("Found duplicated variant name [%s], type [%s] for machine [%s]" %
+ (variant_name, variant_type, variant_definition))
+
+ variant_dict[variant_name] = ContainerNode(metadata = variant_metadata)
+
+ # If the variant is a buildplate then fill also the buildplate map
+ if variant_type == VariantType.BUILD_PLATE:
+ if variant_definition not in self._machine_to_buildplate_dict_map:
+ self._machine_to_buildplate_dict_map[variant_definition] = OrderedDict()
+
+ variant_container = self._container_registry.findContainers(type = "variant", id = variant_metadata["id"])
+ if not variant_container:
+ # ERROR: not variant container. This should never happen
+ raise RuntimeError("Not variant found [%s], type [%s] for machine [%s]" %
+ (variant_name, variant_type, variant_definition))
+ buildplate_type = variant_container[0].getProperty("machine_buildplate_type", "value")
+ if buildplate_type not in self._machine_to_buildplate_dict_map[variant_definition]:
+ self._machine_to_variant_dict_map[variant_definition][buildplate_type] = dict()
+
+ self._machine_to_buildplate_dict_map[variant_definition][buildplate_type] = variant_dict[variant_name]
+
+ #
+ # Gets the variant InstanceContainer with the given information.
+ # Almost the same as getVariantMetadata() except that this returns an InstanceContainer if present.
+ #
+ def getVariantNode(self, machine_definition_id: str, variant_name: str,
+ variant_type: Optional["VariantType"] = None) -> Optional["ContainerNode"]:
+ if variant_type is None:
+ variant_node = None
+ variant_type_dict = self._machine_to_variant_dict_map[machine_definition_id]
+ for variant_dict in variant_type_dict.values():
+ if variant_name in variant_dict:
+ variant_node = variant_dict[variant_name]
+ break
+ return variant_node
+ return self._machine_to_variant_dict_map[machine_definition_id].get(variant_type, {}).get(variant_name)
+
+ def getVariantNodes(self, machine: "GlobalStack",
+ variant_type: Optional["VariantType"] = None) -> dict:
+ machine_definition_id = machine.definition.getId()
+ return self._machine_to_variant_dict_map.get(machine_definition_id, {}).get(variant_type, {})
+
+ #
+ # Gets the default variant for the given machine definition.
+ #
+ def getDefaultVariantNode(self, machine_definition: "DefinitionContainer",
+ variant_type: VariantType) -> Optional["ContainerNode"]:
+ machine_definition_id = machine_definition.getId()
+ preferred_variant_name = None
+ if variant_type == VariantType.BUILD_PLATE:
+ if parseBool(machine_definition.getMetaDataEntry("has_variant_buildplates", False)):
+ preferred_variant_name = machine_definition.getMetaDataEntry("preferred_variant_buildplate_name")
+ else:
+ if parseBool(machine_definition.getMetaDataEntry("has_variants", False)):
+ preferred_variant_name = machine_definition.getMetaDataEntry("preferred_variant_name")
+
+ node = None
+ if preferred_variant_name:
+ node = self.getVariantNode(machine_definition_id, preferred_variant_name, variant_type)
+ return node
+
+ def getBuildplateVariantNode(self, machine_definition_id: str, buildplate_type: str) -> Optional["ContainerNode"]:
+ if machine_definition_id in self._machine_to_buildplate_dict_map:
+ return self._machine_to_buildplate_dict_map[machine_definition_id].get(buildplate_type)
+ return None
diff --git a/cura/Machines/__init__.py b/cura/Machines/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/cura/ObjectsModel.py b/cura/ObjectsModel.py
index 1516b3ee33..cfe4320e28 100644
--- a/cura/ObjectsModel.py
+++ b/cura/ObjectsModel.py
@@ -1,3 +1,8 @@
+# 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
@@ -8,13 +13,19 @@ from UM.i18n import i18nCatalog
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._update)
- Preferences.getInstance().preferenceChanged.connect(self._update)
+ Application.getInstance().getController().getScene().sceneChanged.connect(self._updateDelayed)
+ Preferences.getInstance().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
@@ -22,6 +33,9 @@ class ObjectsModel(ListModel):
self._build_plate_number = nr
self._update()
+ def _updateDelayed(self, *args):
+ self._update_timer.start()
+
def _update(self, *args):
nodes = []
filter_current_build_plate = Preferences.getInstance().getValue("view/filter_current_build_plate")
@@ -46,10 +60,15 @@ class ObjectsModel(ListModel):
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
+
nodes.append({
"name": name,
"isSelected": Selection.isSelected(node),
- "isOutsideBuildArea": node.isOutsideBuildArea(),
+ "isOutsideBuildArea": is_outside_build_area,
"buildPlateNumber": node_build_plate_number,
"node": node
})
diff --git a/cura/OneAtATimeIterator.py b/cura/OneAtATimeIterator.py
index 5653c8f1fb..84d65bae8e 100644
--- a/cura/OneAtATimeIterator.py
+++ b/cura/OneAtATimeIterator.py
@@ -18,12 +18,13 @@ class OneAtATimeIterator(Iterator.Iterator):
def _fillStack(self):
node_list = []
for node in self._scene_node.getChildren():
- if not isinstance(node, SceneNode):
+ if not issubclass(type(node), SceneNode):
continue
if node.callDecoration("getConvexHull"):
node_list.append(node)
+
if len(node_list) < 2:
self._node_stack = node_list[:]
return
diff --git a/cura/PlatformPhysics.py b/cura/PlatformPhysics.py
index 69890178e4..3d9d5d5027 100755
--- a/cura/PlatformPhysics.py
+++ b/cura/PlatformPhysics.py
@@ -40,6 +40,8 @@ class PlatformPhysics:
Preferences.getInstance().addPreference("physics/automatic_drop_down", True)
def _onSceneChanged(self, source):
+ if not source.getMeshData():
+ return
self._change_timer.start()
def _onChangeTimerFinished(self):
diff --git a/cura/PreviewPass.py b/cura/PreviewPass.py
index c1880e82ef..de21a5dc86 100644
--- a/cura/PreviewPass.py
+++ b/cura/PreviewPass.py
@@ -1,7 +1,7 @@
-# Copyright (c) 2017 Ultimaker B.V.
-# Uranium is released under the terms of the LGPLv3 or higher.
-
+# Copyright (c) 2018 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
from UM.Application import Application
+from UM.Math.Color import Color
from UM.Resources import Resources
from UM.View.RenderPass import RenderPass
@@ -17,6 +17,18 @@ MYPY = False
if MYPY:
from UM.Scene.Camera import Camera
+
+# Make color brighter by normalizing it (maximum factor 2.5 brighter)
+# color_list is a list of 4 elements: [r, g, b, a], each element is a float 0..1
+def prettier_color(color_list):
+ maximum = max(color_list[:3])
+ if maximum > 0:
+ factor = min(1 / maximum, 2.5)
+ else:
+ factor = 1.0
+ return [min(i * factor, 1.0) for i in color_list]
+
+
## A render pass subclass that renders slicable objects with default parameters.
# It uses the active camera by default, but it can be overridden to use a different camera.
#
@@ -39,7 +51,14 @@ class PreviewPass(RenderPass):
def render(self) -> None:
if not self._shader:
- self._shader = OpenGL.getInstance().createShaderProgram(Resources.getPath(Resources.Shaders, "object.shader"))
+ self._shader = OpenGL.getInstance().createShaderProgram(Resources.getPath(Resources.Shaders, "overhang.shader"))
+ self._shader.setUniformValue("u_overhangAngle", 1.0)
+ self._shader.setUniformValue("u_ambientColor", [0.1, 0.1, 0.1, 1.0])
+ self._shader.setUniformValue("u_specularColor", [0.6, 0.6, 0.6, 1.0])
+ self._shader.setUniformValue("u_shininess", 20.0)
+
+ self._gl.glClearColor(0.0, 0.0, 0.0, 0.0)
+ self._gl.glClear(self._gl.GL_COLOR_BUFFER_BIT | self._gl.GL_DEPTH_BUFFER_BIT)
# Create a new batch to be rendered
batch = RenderBatch(self._shader)
@@ -47,7 +66,9 @@ class PreviewPass(RenderPass):
# Fill up the batch with objects that can be sliced. `
for node in DepthFirstIterator(self._scene.getRoot()):
if node.callDecoration("isSliceable") and node.getMeshData() and node.isVisible():
- batch.addItem(node.getWorldTransformation(), node.getMeshData())
+ uniforms = {}
+ uniforms["diffuse_color"] = prettier_color(node.getDiffuseColor())
+ batch.addItem(node.getWorldTransformation(), node.getMeshData(), uniforms = uniforms)
self.bind()
if self._camera is None:
@@ -55,3 +76,4 @@ class PreviewPass(RenderPass):
else:
batch.render(self._camera)
self.release()
+
diff --git a/cura/PrintInformation.py b/cura/PrintInformation.py
index 5d5d59ed3b..05b740637d 100644
--- a/cura/PrintInformation.py
+++ b/cura/PrintInformation.py
@@ -1,25 +1,22 @@
# Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
-from PyQt5.QtCore import QObject, pyqtSignal, pyqtProperty
-from UM.FlameProfiler import pyqtSlot
+from typing import Dict
+import math
+import os.path
+import unicodedata
+import json
+import re # To create abbreviations for printer names.
+
+from PyQt5.QtCore import QObject, pyqtSignal, pyqtProperty, pyqtSlot
from UM.Application import Application
from UM.Logger import Logger
from UM.Qt.Duration import Duration
from UM.Preferences import Preferences
-from UM.Settings.ContainerRegistry import ContainerRegistry
-
-from cura.Settings.ExtruderManager import ExtruderManager
-from typing import Dict
-
-import math
-import os.path
-import unicodedata
-import json
-import re #To create abbreviations for printer names.
-
+from UM.Scene.SceneNode import SceneNode
from UM.i18n import i18nCatalog
+
catalog = i18nCatalog("cura")
## A class for processing and calculating minimum, current and maximum print time as well as managing the job name
@@ -65,7 +62,7 @@ class PrintInformation(QObject):
self._backend = Application.getInstance().getBackend()
if self._backend:
self._backend.printDurationMessage.connect(self._onPrintDurationMessage)
- Application.getInstance().getController().getScene().sceneChanged.connect(self.setToZeroPrintInformation)
+ Application.getInstance().getController().getScene().sceneChanged.connect(self._onSceneChanged)
self._base_name = ""
self._abbr_machine = ""
@@ -74,16 +71,19 @@ class PrintInformation(QObject):
self._active_build_plate = 0
self._initVariablesWithBuildPlate(self._active_build_plate)
- Application.getInstance().globalContainerStackChanged.connect(self._updateJobName)
- Application.getInstance().fileLoaded.connect(self.setBaseName)
- Application.getInstance().getBuildPlateModel().activeBuildPlateChanged.connect(self._onActiveBuildPlateChanged)
- Application.getInstance().workspaceLoaded.connect(self.setProjectName)
+ self._application = Application.getInstance()
+ self._multi_build_plate_model = self._application.getMultiBuildPlateModel()
+
+ 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)
Preferences.getInstance().preferenceChanged.connect(self._onPreferencesChanged)
- self._active_material_container = None
- Application.getInstance().getMachineManager().activeMaterialChanged.connect(self._onActiveMaterialChanged)
- self._onActiveMaterialChanged()
+ self._application.getMachineManager().rootMaterialChanged.connect(self._onActiveMaterialsChanged)
+ self._onActiveMaterialsChanged()
self._material_amounts = []
@@ -108,7 +108,6 @@ class PrintInformation(QObject):
self._print_time_message_values = {}
-
def _initPrintTimeMessageValues(self, build_plate_number):
# Full fill message values using keys from _print_time_message_translations
self._print_time_message_values[build_plate_number] = {}
@@ -199,11 +198,10 @@ class PrintInformation(QObject):
self._current_print_time[build_plate_number].setDuration(total_estimated_time)
def _calculateInformation(self, build_plate_number):
- if Application.getInstance().getGlobalContainerStack() is None:
+ global_stack = Application.getInstance().getGlobalContainerStack()
+ if global_stack is None:
return
- # Material amount is sent as an amount of mm^3, so calculate length from that
- radius = Application.getInstance().getGlobalContainerStack().getProperty("material_diameter", "value") / 2
self._material_lengths[build_plate_number] = []
self._material_weights[build_plate_number] = []
self._material_costs[build_plate_number] = []
@@ -211,18 +209,17 @@ class PrintInformation(QObject):
material_preference_values = json.loads(Preferences.getInstance().getValue("cura/material_settings"))
- extruder_stacks = list(ExtruderManager.getInstance().getMachineExtruders(Application.getInstance().getGlobalContainerStack().getId()))
- for index, amount in enumerate(self._material_amounts):
+ extruder_stacks = global_stack.extruders
+ for position, extruder_stack in extruder_stacks.items():
+ 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.
- material = None
- if extruder_stacks: # Multi extrusion machine
- extruder_stack = [extruder for extruder in extruder_stacks if extruder.getMetaDataEntry("position") == str(index)][0]
- density = extruder_stack.getMetaDataEntry("properties", {}).get("density", 0)
- material = extruder_stack.findContainer({"type": "material"})
- else: # Machine with no extruder stacks
- density = Application.getInstance().getGlobalContainerStack().getMetaDataEntry("properties", {}).get("density", 0)
- material = Application.getInstance().getGlobalContainerStack().findContainer({"type": "material"})
+ density = extruder_stack.getMetaDataEntry("properties", {}).get("density", 0)
+ material = extruder_stack.findContainer({"type": "material"})
+ radius = extruder_stack.getProperty("material_diameter", "value") / 2
weight = float(amount) * float(density) / 1000
cost = 0
@@ -241,6 +238,7 @@ class PrintInformation(QObject):
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:
@@ -259,25 +257,11 @@ class PrintInformation(QObject):
if preference != "cura/material_settings":
return
- for build_plate_number in range(Application.getInstance().getBuildPlateModel().maxBuildPlate + 1):
+ for build_plate_number in range(self._multi_build_plate_model.maxBuildPlate + 1):
self._calculateInformation(build_plate_number)
- def _onActiveMaterialChanged(self):
- if self._active_material_container:
- try:
- self._active_material_container.metaDataChanged.disconnect(self._onMaterialMetaDataChanged)
- except TypeError: #pyQtSignal gives a TypeError when disconnecting from something that is already disconnected.
- pass
-
- active_material_id = Application.getInstance().getMachineManager().activeMaterialId
- active_material_containers = ContainerRegistry.getInstance().findInstanceContainers(id = active_material_id)
-
- if active_material_containers:
- self._active_material_container = active_material_containers[0]
- self._active_material_container.metaDataChanged.connect(self._onMaterialMetaDataChanged)
-
def _onActiveBuildPlateChanged(self):
- new_active_build_plate = Application.getInstance().getBuildPlateModel().activeBuildPlate
+ 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
@@ -289,8 +273,8 @@ class PrintInformation(QObject):
self.materialNamesChanged.emit()
self.currentPrintTimeChanged.emit()
- def _onMaterialMetaDataChanged(self, *args, **kwargs):
- for build_plate_number in range(Application.getInstance().getBuildPlateModel().maxBuildPlate + 1):
+ def _onActiveMaterialsChanged(self, *args, **kwargs):
+ for build_plate_number in range(self._multi_build_plate_model.maxBuildPlate + 1):
self._calculateInformation(build_plate_number)
@pyqtSlot(str)
@@ -360,10 +344,10 @@ class PrintInformation(QObject):
if not global_container_stack:
self._abbr_machine = ""
return
+ active_machine_type_name = global_container_stack.definition.getName()
- global_stack_name = global_container_stack.getName()
abbr_machine = ""
- for word in re.findall(r"[\w']+", global_stack_name):
+ for word in re.findall(r"[\w']+", active_machine_type_name):
if word.lower() == "ultimaker":
abbr_machine += "UM"
elif word.isdigit():
@@ -395,12 +379,27 @@ class PrintInformation(QObject):
return result
# Simulate message with zero time duration
- def setToZeroPrintInformation(self, build_plate_number):
- temp_message = {}
- if build_plate_number not in self._print_time_message_values:
- self._print_time_message_values[build_plate_number] = {}
- for key in self._print_time_message_values[build_plate_number].keys():
- temp_message[key] = 0
+ def setToZeroPrintInformation(self, build_plate = 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():
+ temp_message[key] = 0
temp_material_amounts = [0]
- self._onPrintDurationMessage(build_plate_number, temp_message, temp_material_amounts)
+
+ 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):
+
+ # Ignore any changes that are not related to sliceable objects
+ if not isinstance(scene_node, SceneNode)\
+ or not scene_node.callDecoration("isSliceable")\
+ or not scene_node.callDecoration("getBuildPlateNumber") == self._active_build_plate:
+ return
+
+ self.setToZeroPrintInformation(self._active_build_plate)
diff --git a/cura/PrinterOutput/ConfigurationModel.py b/cura/PrinterOutput/ConfigurationModel.py
new file mode 100644
index 0000000000..c03d968b9e
--- /dev/null
+++ b/cura/PrinterOutput/ConfigurationModel.py
@@ -0,0 +1,81 @@
+# Copyright (c) 2018 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+
+from PyQt5.QtCore import pyqtProperty, QObject, pyqtSignal
+from typing import List
+
+MYPY = False
+if MYPY:
+ from cura.PrinterOutput.ExtruderConfigurationModel import ExtruderConfigurationModel
+
+
+class ConfigurationModel(QObject):
+
+ configurationChanged = pyqtSignal()
+
+ def __init__(self):
+ super().__init__()
+ self._printer_type = None
+ self._extruder_configurations = [] # type: List[ExtruderConfigurationModel]
+ self._buildplate_configuration = None
+
+ def setPrinterType(self, printer_type):
+ self._printer_type = printer_type
+
+ @pyqtProperty(str, fset = setPrinterType, notify = configurationChanged)
+ def printerType(self):
+ return self._printer_type
+
+ def setExtruderConfigurations(self, extruder_configurations):
+ self._extruder_configurations = extruder_configurations
+
+ @pyqtProperty("QVariantList", fset = setExtruderConfigurations, notify = configurationChanged)
+ def extruderConfigurations(self):
+ return self._extruder_configurations
+
+ def setBuildplateConfiguration(self, buildplate_configuration):
+ self._buildplate_configuration = buildplate_configuration
+
+ @pyqtProperty(str, fset = setBuildplateConfiguration, notify = configurationChanged)
+ def buildplateConfiguration(self):
+ return self._buildplate_configuration
+
+ ## This method is intended to indicate whether the configuration is valid or not.
+ # The method checks if the mandatory fields are or not set
+ def isValid(self):
+ if not self._extruder_configurations:
+ return False
+ for configuration in self._extruder_configurations:
+ if configuration is None:
+ return False
+ return self._printer_type is not None
+
+ def __str__(self):
+ message_chunks = []
+ message_chunks.append("Printer type: " + self._printer_type)
+ message_chunks.append("Extruders: [")
+ for configuration in self._extruder_configurations:
+ message_chunks.append(" " + str(configuration))
+ message_chunks.append("]")
+ if self._buildplate_configuration is not None:
+ message_chunks.append("Buildplate: " + self._buildplate_configuration)
+
+ return "\n".join(message_chunks)
+
+ def __eq__(self, other):
+ return hash(self) == hash(other)
+
+ ## 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.
+ def __hash__(self):
+ extruder_hash = hash(0)
+ first_extruder = None
+ for configuration in self._extruder_configurations:
+ extruder_hash ^= hash(configuration)
+ if configuration.position == 0:
+ first_extruder = configuration
+ # To ensure the correct order of the extruders, we add an "and" operation using the first extruder hash value
+ 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
diff --git a/cura/PrinterOutput/ExtruderConfigurationModel.py b/cura/PrinterOutput/ExtruderConfigurationModel.py
new file mode 100644
index 0000000000..bc7f1a7c07
--- /dev/null
+++ b/cura/PrinterOutput/ExtruderConfigurationModel.py
@@ -0,0 +1,59 @@
+# Copyright (c) 2018 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+
+from PyQt5.QtCore import pyqtProperty, QObject, pyqtSignal
+
+
+class ExtruderConfigurationModel(QObject):
+
+ extruderConfigurationChanged = pyqtSignal()
+
+ def __init__(self):
+ super().__init__()
+ self._position = -1
+ self._material = None
+ self._hotend_id = None
+
+ def setPosition(self, position):
+ self._position = position
+
+ @pyqtProperty(int, fset = setPosition, notify = extruderConfigurationChanged)
+ def position(self):
+ return self._position
+
+ def setMaterial(self, material):
+ self._material = material
+
+ @pyqtProperty(QObject, fset = setMaterial, notify = extruderConfigurationChanged)
+ def material(self):
+ return self._material
+
+ def setHotendID(self, hotend_id):
+ self._hotend_id = hotend_id
+
+ @pyqtProperty(str, fset = setHotendID, notify = extruderConfigurationChanged)
+ def hotendID(self):
+ return self._hotend_id
+
+ ## This method is intended to indicate whether the configuration is valid or not.
+ # The method checks if the mandatory fields are or not set
+ # At this moment is always valid since we allow to have empty material and variants.
+ def isValid(self):
+ return True
+
+ def __str__(self):
+ message_chunks = []
+ message_chunks.append("Position: " + str(self._position))
+ message_chunks.append("-")
+ message_chunks.append("Material: " + self.material.type if self.material else "empty")
+ message_chunks.append("-")
+ message_chunks.append("HotendID: " + self.hotendID if self.hotendID else "empty")
+ return " ".join(message_chunks)
+
+ def __eq__(self, other):
+ return hash(self) == hash(other)
+
+ # 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
diff --git a/cura/PrinterOutput/ExtruderOuputModel.py b/cura/PrinterOutput/ExtruderOutputModel.py
similarity index 70%
rename from cura/PrinterOutput/ExtruderOuputModel.py
rename to cura/PrinterOutput/ExtruderOutputModel.py
index b0be6cbbe4..e4c7f1608e 100644
--- a/cura/PrinterOutput/ExtruderOuputModel.py
+++ b/cura/PrinterOutput/ExtruderOutputModel.py
@@ -1,8 +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.
-from PyQt5.QtCore import pyqtSignal, pyqtProperty, QObject, QVariant, pyqtSlot
-from UM.Logger import Logger
+from PyQt5.QtCore import pyqtSignal, pyqtProperty, QObject, pyqtSlot
+from cura.PrinterOutput.ExtruderConfigurationModel import ExtruderConfigurationModel
from typing import Optional
@@ -17,14 +17,18 @@ class ExtruderOutputModel(QObject):
targetHotendTemperatureChanged = pyqtSignal()
hotendTemperatureChanged = pyqtSignal()
activeMaterialChanged = pyqtSignal()
+ extruderConfigurationChanged = pyqtSignal()
- def __init__(self, printer: "PrinterOutputModel", parent=None):
+ def __init__(self, printer: "PrinterOutputModel", position, parent=None):
super().__init__(parent)
self._printer = printer
+ self._position = position
self._target_hotend_temperature = 0
self._hotend_temperature = 0
self._hotend_id = ""
self._active_material = None # type: Optional[MaterialOutputModel]
+ self._extruder_configuration = ExtruderConfigurationModel()
+ self._extruder_configuration.position = self._position
@pyqtProperty(QObject, notify = activeMaterialChanged)
def activeMaterial(self) -> "MaterialOutputModel":
@@ -33,7 +37,9 @@ class ExtruderOutputModel(QObject):
def updateActiveMaterial(self, material: Optional["MaterialOutputModel"]):
if self._active_material != material:
self._active_material = material
+ self._extruder_configuration.material = self._active_material
self.activeMaterialChanged.emit()
+ self.extruderConfigurationChanged.emit()
## Update the hotend temperature. This only changes it locally.
def updateHotendTemperature(self, temperature: float):
@@ -56,7 +62,7 @@ class ExtruderOutputModel(QObject):
def targetHotendTemperature(self) -> float:
return self._target_hotend_temperature
- @pyqtProperty(float, notify=hotendTemperatureChanged)
+ @pyqtProperty(float, notify = hotendTemperatureChanged)
def hotendTemperature(self) -> float:
return self._hotend_temperature
@@ -67,4 +73,12 @@ class ExtruderOutputModel(QObject):
def updateHotendID(self, id: str):
if self._hotend_id != id:
self._hotend_id = id
+ self._extruder_configuration.hotendID = self._hotend_id
self.hotendIDChanged.emit()
+ self.extruderConfigurationChanged.emit()
+
+ @pyqtProperty(QObject, notify = extruderConfigurationChanged)
+ def extruderConfiguration(self):
+ if self._extruder_configuration.isValid():
+ return self._extruder_configuration
+ return None
diff --git a/cura/PrinterOutput/NetworkedPrinterOutputDevice.py b/cura/PrinterOutput/NetworkedPrinterOutputDevice.py
index 7cf855ee85..eefbd9ae12 100644
--- a/cura/PrinterOutput/NetworkedPrinterOutputDevice.py
+++ b/cura/PrinterOutput/NetworkedPrinterOutputDevice.py
@@ -55,6 +55,17 @@ class NetworkedPrinterOutputDevice(PrinterOutputDevice):
self._connection_state_before_timeout = None # type: Optional[ConnectionState]
+ printer_type = self._properties.get(b"machine", b"").decode("utf-8")
+ printer_type_identifiers = {
+ "9066": "ultimaker3",
+ "9511": "ultimaker3_extended"
+ }
+ self._printer_type = "Unknown"
+ for key, value in printer_type_identifiers.items():
+ if printer_type.startswith(key):
+ self._printer_type = value
+ break
+
def requestWrite(self, nodes, file_name=None, filter_by_machine=False, file_handler=None, **kwargs) -> None:
raise NotImplementedError("requestWrite needs to be implemented")
@@ -100,7 +111,7 @@ class NetworkedPrinterOutputDevice(PrinterOutputDevice):
if batched_lines_count >= max_chars_per_line:
file_data_bytes_list.append(self._compressDataAndNotifyQt("".join(batched_lines)))
batched_lines = []
- batched_lines_count
+ batched_lines_count = 0
# Don't miss the last batch (If any)
if len(batched_lines) != 0:
@@ -219,6 +230,9 @@ class NetworkedPrinterOutputDevice(PrinterOutputDevice):
reply.uploadProgress.connect(onProgress)
self._registerOnFinishedCallback(reply, onFinished)
+
+ return reply
+
def postForm(self, target: str, header_data: str, body_data: bytes, onFinished: Optional[Callable[[Any, QNetworkReply], None]], onProgress: Callable = None) -> None:
post_part = QHttpPart()
post_part.setHeader(QNetworkRequest.ContentDispositionHeader, header_data)
@@ -298,6 +312,10 @@ class NetworkedPrinterOutputDevice(PrinterOutputDevice):
def firmwareVersion(self) -> str:
return self._properties.get(b"firmware_version", b"").decode("utf-8")
+ @pyqtProperty(str, constant=True)
+ def printerType(self) -> str:
+ return self._printer_type
+
## IPadress of this printer
@pyqtProperty(str, constant=True)
def ipAddress(self) -> str:
diff --git a/cura/PrinterOutput/PrinterOutputController.py b/cura/PrinterOutput/PrinterOutputController.py
index 86ca10e2d3..1d658e79be 100644
--- a/cura/PrinterOutput/PrinterOutputController.py
+++ b/cura/PrinterOutput/PrinterOutputController.py
@@ -6,7 +6,7 @@ from UM.Logger import Logger
MYPY = False
if MYPY:
from cura.PrinterOutput.PrintJobOutputModel import PrintJobOutputModel
- from cura.PrinterOutput.ExtruderOuputModel import ExtruderOuputModel
+ from cura.PrinterOutput.ExtruderOutputModel import ExtruderOutputModel
from cura.PrinterOutput.PrinterOutputModel import PrinterOutputModel
@@ -18,7 +18,7 @@ class PrinterOutputController:
self.can_control_manually = True
self._output_device = output_device
- def setTargetHotendTemperature(self, printer: "PrinterOutputModel", extruder: "ExtruderOuputModel", temperature: int):
+ def setTargetHotendTemperature(self, printer: "PrinterOutputModel", extruder: "ExtruderOutputModel", temperature: int):
Logger.log("w", "Set target hotend temperature not implemented in controller")
def setTargetBedTemperature(self, printer: "PrinterOutputModel", temperature: int):
diff --git a/cura/PrinterOutput/PrinterOutputModel.py b/cura/PrinterOutput/PrinterOutputModel.py
index 8234989519..712f9b5b1e 100644
--- a/cura/PrinterOutput/PrinterOutputModel.py
+++ b/cura/PrinterOutput/PrinterOutputModel.py
@@ -1,11 +1,11 @@
-# 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 pyqtSignal, pyqtProperty, QObject, QVariant, pyqtSlot
-from UM.Logger import Logger
-from typing import Optional, List
+from typing import Optional
from UM.Math.Vector import Vector
-from cura.PrinterOutput.ExtruderOuputModel import ExtruderOutputModel
+from cura.PrinterOutput.ConfigurationModel import ConfigurationModel
+from cura.PrinterOutput.ExtruderOutputModel import ExtruderOutputModel
MYPY = False
if MYPY:
@@ -22,8 +22,10 @@ class PrinterOutputModel(QObject):
nameChanged = pyqtSignal()
headPositionChanged = pyqtSignal()
keyChanged = pyqtSignal()
- typeChanged = pyqtSignal()
+ printerTypeChanged = pyqtSignal()
+ buildplateChanged = pyqtSignal()
cameraChanged = pyqtSignal()
+ configurationChanged = pyqtSignal()
def __init__(self, output_controller: "PrinterOutputController", number_of_extruders: int = 1, parent=None, firmware_version = ""):
super().__init__(parent)
@@ -32,13 +34,18 @@ class PrinterOutputModel(QObject):
self._name = ""
self._key = "" # Unique identifier
self._controller = output_controller
- self._extruders = [ExtruderOutputModel(printer=self) for i in range(number_of_extruders)]
+ 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._type = ""
+ self._printer_type = ""
+ self._buildplate_name = None
+ # Update the printer configuration every time any of the extruders changes its configuration
+ for extruder in self._extruders:
+ extruder.extruderConfigurationChanged.connect(self._updateExtruderConfiguration)
self._camera = None
@@ -64,14 +71,27 @@ class PrinterOutputModel(QObject):
def camera(self):
return self._camera
- @pyqtProperty(str, notify = typeChanged)
+ @pyqtProperty(str, notify = printerTypeChanged)
def type(self):
- return self._type
+ return self._printer_type
- def updateType(self, type):
- if self._type != type:
- self._type = type
- self.typeChanged.emit()
+ 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):
@@ -103,32 +123,32 @@ class PrinterOutputModel(QObject):
self._head_position = Vector(x, y, z)
self.headPositionChanged.emit()
- @pyqtProperty("long", "long", "long")
- @pyqtProperty("long", "long", "long", "long")
+ @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("long")
- @pyqtProperty("long", "long")
+ @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("long")
- @pyqtProperty("long", "long")
+ @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("long")
- @pyqtProperty("long", "long")
+ @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("long", "long", "long")
- @pyqtSlot("long", "long", "long", "long")
+ @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)
@@ -238,3 +258,14 @@ class PrinterOutputModel(QObject):
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
+
+ def _updateExtruderConfiguration(self):
+ self._printer_configuration.extruderConfigurations = [extruder.extruderConfiguration for extruder in self._extruders]
+ self.configurationChanged.emit()
diff --git a/cura/PrinterOutputDevice.py b/cura/PrinterOutputDevice.py
index 9e603b83ae..4d6ddb8dfa 100644
--- a/cura/PrinterOutputDevice.py
+++ b/cura/PrinterOutputDevice.py
@@ -1,12 +1,11 @@
-# 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.i18n import i18nCatalog
from UM.OutputDevice.OutputDevice import OutputDevice
-from PyQt5.QtCore import pyqtProperty, QObject, QTimer, pyqtSignal
+from PyQt5.QtCore import pyqtProperty, QObject, QTimer, pyqtSignal, QVariant
from PyQt5.QtWidgets import QMessageBox
-
from UM.Logger import Logger
from UM.Signal import signalemitter
from UM.Application import Application
@@ -17,6 +16,7 @@ from typing import List, Optional
MYPY = False
if MYPY:
from cura.PrinterOutput.PrinterOutputModel import PrinterOutputModel
+ from cura.PrinterOutput.ConfigurationModel import ConfigurationModel
i18n_catalog = i18nCatalog("cura")
@@ -44,10 +44,14 @@ class PrinterOutputDevice(QObject, OutputDevice):
# 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, parent = None):
super().__init__(device_id = device_id, parent = parent)
self._printers = [] # type: List[PrinterOutputModel]
+ self._unique_configurations = [] # type: List[ConfigurationModel]
self._monitor_view_qml_path = ""
self._monitor_component = None
@@ -69,6 +73,8 @@ class PrinterOutputDevice(QObject, OutputDevice):
self._address = ""
self._connection_text = ""
+ self.printersChanged.connect(self._onPrintersChanged)
+ Application.getInstance().getOutputDeviceManager().outputDevicesChanged.connect(self._updateUniqueConfigurations)
@pyqtProperty(str, notify = connectionTextChanged)
def address(self):
@@ -175,6 +181,23 @@ class PrinterOutputDevice(QObject, OutputDevice):
self.acceptsCommandsChanged.emit()
+ # Returns the unique configurations of the printers within this output device
+ @pyqtProperty("QVariantList", notify = uniqueConfigurationsChanged)
+ def uniqueConfigurations(self):
+ return self._unique_configurations
+
+ def _updateUniqueConfigurations(self):
+ 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):
+ for printer in self._printers:
+ printer.configurationChanged.connect(self._updateUniqueConfigurations)
+
+ # At this point there may be non-updated configurations
+ self._updateUniqueConfigurations()
+
## The current processing state of the backend.
class ConnectionState(IntEnum):
diff --git a/cura/ProfileReader.py b/cura/ProfileReader.py
index d4600ed99f..460fce823e 100644
--- a/cura/ProfileReader.py
+++ b/cura/ProfileReader.py
@@ -3,6 +3,13 @@
from UM.PluginObject import PluginObject
+
+# Exception when there is no profile to import from a given files.
+# Note that this should not be treated as an exception but as an information instead.
+class NoProfileException(Exception):
+ pass
+
+
## A type of plug-ins that reads profiles from a file.
#
# The profile is then stored as instance container of the type user profile.
@@ -14,4 +21,4 @@ class ProfileReader(PluginObject):
#
# \return \type{Profile|Profile[]} The profile that was obtained from the file or a list of Profiles.
def read(self, file_name):
- raise NotImplementedError("Profile reader plug-in was not correctly implemented. The read function was not implemented.")
\ No newline at end of file
+ raise NotImplementedError("Profile reader plug-in was not correctly implemented. The read function was not implemented.")
diff --git a/cura/QualityManager.py b/cura/QualityManager.py
deleted file mode 100644
index 76a0c86a5f..0000000000
--- a/cura/QualityManager.py
+++ /dev/null
@@ -1,332 +0,0 @@
-# Copyright (c) 2017 Ultimaker B.V.
-# Cura is released under the terms of the LGPLv3 or higher.
-
-# This collects a lot of quality and quality changes related code which was split between ContainerManager
-# and the MachineManager and really needs to usable from both.
-from typing import Any, Dict, List, Optional, TYPE_CHECKING
-
-from UM.Application import Application
-from UM.Settings.ContainerRegistry import ContainerRegistry
-from UM.Settings.InstanceContainer import InstanceContainer
-from cura.Settings.ExtruderManager import ExtruderManager
-
-if TYPE_CHECKING:
- from cura.Settings.GlobalStack import GlobalStack
- from cura.Settings.ExtruderStack import ExtruderStack
- from UM.Settings.DefinitionContainer import DefinitionContainerInterface
-
-class QualityManager:
-
- ## Get the singleton instance for this class.
- @classmethod
- def getInstance(cls) -> "QualityManager":
- # Note: Explicit use of class name to prevent issues with inheritance.
- if not QualityManager.__instance:
- QualityManager.__instance = cls()
- return QualityManager.__instance
-
- __instance = None # type: "QualityManager"
-
- ## Find a quality by name for a specific machine definition and materials.
- #
- # \param quality_name
- # \param machine_definition (Optional) \type{DefinitionContainerInterface} If nothing is
- # specified then the currently selected machine definition is used.
- # \param material_containers_metadata If nothing is specified then the
- # current set of selected materials is used.
- # \return the matching quality container \type{InstanceContainer}
- def findQualityByName(self, quality_name: str, machine_definition: Optional["DefinitionContainerInterface"] = None, material_containers_metadata: Optional[List[Dict[str, Any]]] = None) -> Optional[InstanceContainer]:
- criteria = {"type": "quality", "name": quality_name}
- result = self._getFilteredContainersForStack(machine_definition, material_containers_metadata, **criteria)
-
- # Fall back to using generic materials and qualities if nothing could be found.
- if not result and material_containers_metadata and len(material_containers_metadata) == 1:
- basic_materials = self._getBasicMaterialMetadatas(material_containers_metadata[0])
- result = self._getFilteredContainersForStack(machine_definition, basic_materials, **criteria)
-
- return result[0] if result else None
-
- ## Find a quality changes container by name.
- #
- # \param quality_changes_name \type{str} the name of the quality changes container.
- # \param machine_definition (Optional) \type{DefinitionContainer} If nothing is
- # specified then the currently selected machine definition is used..
- # \return the matching quality changes containers \type{List[InstanceContainer]}
- def findQualityChangesByName(self, quality_changes_name: str, machine_definition: Optional["DefinitionContainerInterface"] = None):
- if not machine_definition:
- global_stack = Application.getGlobalContainerStack()
- if not global_stack:
- return [] #No stack, so no current definition could be found, so there are no quality changes either.
- machine_definition = global_stack.definition
-
- result = self.findAllQualityChangesForMachine(machine_definition)
- result = [quality_change for quality_change in result if quality_change.getName() == quality_changes_name]
- return result
-
- ## Fetch the list of available quality types for this combination of machine definition and materials.
- #
- # \param machine_definition \type{DefinitionContainer}
- # \param material_containers \type{List[InstanceContainer]}
- # \return \type{List[str]}
- def findAllQualityTypesForMachineAndMaterials(self, machine_definition: "DefinitionContainerInterface", material_containers: List[InstanceContainer]) -> List[str]:
- # Determine the common set of quality types which can be
- # applied to all of the materials for this machine.
- quality_type_dict = self.__fetchQualityTypeDictForMaterial(machine_definition, material_containers[0])
- common_quality_types = set(quality_type_dict.keys())
- for material_container in material_containers[1:]:
- next_quality_type_dict = self.__fetchQualityTypeDictForMaterial(machine_definition, material_container)
- common_quality_types.intersection_update(set(next_quality_type_dict.keys()))
-
- return list(common_quality_types)
-
- def findAllQualitiesForMachineAndMaterials(self, machine_definition: "DefinitionContainerInterface", material_containers: List[InstanceContainer]) -> List[InstanceContainer]:
- # Determine the common set of quality types which can be
- # applied to all of the materials for this machine.
- quality_type_dict = self.__fetchQualityTypeDictForMaterial(machine_definition, material_containers[0])
- qualities = set(quality_type_dict.values())
- for material_container in material_containers[1:]:
- next_quality_type_dict = self.__fetchQualityTypeDictForMaterial(machine_definition, material_container)
- qualities.intersection_update(set(next_quality_type_dict.values()))
-
- return list(qualities)
-
- ## Fetches a dict of quality types names to quality profiles for a combination of machine and material.
- #
- # \param machine_definition \type{DefinitionContainer} the machine definition.
- # \param material \type{InstanceContainer} the material.
- # \return \type{Dict[str, InstanceContainer]} the dict of suitable quality type names mapping to qualities.
- def __fetchQualityTypeDictForMaterial(self, machine_definition: "DefinitionContainerInterface", material: InstanceContainer) -> Dict[str, InstanceContainer]:
- qualities = self.findAllQualitiesForMachineMaterial(machine_definition, material)
- quality_type_dict = {}
- for quality in qualities:
- quality_type_dict[quality.getMetaDataEntry("quality_type")] = quality
- return quality_type_dict
-
- ## Find a quality container by quality type.
- #
- # \param quality_type \type{str} the name of the quality type to search for.
- # \param machine_definition (Optional) \type{InstanceContainer} If nothing is
- # specified then the currently selected machine definition is used.
- # \param material_containers_metadata If nothing is specified then the
- # current set of selected materials is used.
- # \return the matching quality container \type{InstanceContainer}
- def findQualityByQualityType(self, quality_type: str, machine_definition: Optional["DefinitionContainerInterface"] = None, material_containers_metadata: Optional[List[Dict[str, Any]]] = None, **kwargs) -> InstanceContainer:
- criteria = kwargs
- criteria["type"] = "quality"
- if quality_type:
- criteria["quality_type"] = quality_type
- result = self._getFilteredContainersForStack(machine_definition, material_containers_metadata, **criteria)
- # Fall back to using generic materials and qualities if nothing could be found.
- if not result and material_containers_metadata and len(material_containers_metadata) == 1:
- basic_materials = self._getBasicMaterialMetadatas(material_containers_metadata[0])
- if basic_materials:
- result = self._getFilteredContainersForStack(machine_definition, basic_materials, **criteria)
- return result[0] if result else None
-
- ## Find all suitable qualities for a combination of machine and material.
- #
- # \param machine_definition \type{DefinitionContainer} the machine definition.
- # \param material_container \type{InstanceContainer} the material.
- # \return \type{List[InstanceContainer]} the list of suitable qualities.
- def findAllQualitiesForMachineMaterial(self, machine_definition: "DefinitionContainerInterface", material_container: InstanceContainer) -> List[InstanceContainer]:
- criteria = {"type": "quality"}
- result = self._getFilteredContainersForStack(machine_definition, [material_container.getMetaData()], **criteria)
- if not result:
- basic_materials = self._getBasicMaterialMetadatas(material_container.getMetaData())
- if basic_materials:
- result = self._getFilteredContainersForStack(machine_definition, basic_materials, **criteria)
-
- return result
-
- ## Find all quality changes for a machine.
- #
- # \param machine_definition \type{DefinitionContainer} the machine definition.
- # \return \type{List[InstanceContainer]} the list of quality changes
- def findAllQualityChangesForMachine(self, machine_definition: "DefinitionContainerInterface") -> List[InstanceContainer]:
- if machine_definition.getMetaDataEntry("has_machine_quality"):
- definition_id = machine_definition.getId()
- else:
- definition_id = "fdmprinter"
-
- filter_dict = { "type": "quality_changes", "definition": definition_id }
- quality_changes_list = ContainerRegistry.getInstance().findInstanceContainers(**filter_dict)
- return quality_changes_list
-
- def findAllExtruderDefinitionsForMachine(self, machine_definition: "DefinitionContainerInterface") -> List["DefinitionContainerInterface"]:
- filter_dict = { "machine": machine_definition.getId() }
- return ContainerRegistry.getInstance().findDefinitionContainers(**filter_dict)
-
- ## Find all quality changes for a given extruder.
- #
- # \param extruder_definition The extruder to find the quality changes for.
- # \return The list of quality changes for the given extruder.
- def findAllQualityChangesForExtruder(self, extruder_definition: "DefinitionContainerInterface") -> List[InstanceContainer]:
- filter_dict = {"type": "quality_changes", "extruder": extruder_definition.getId()}
- return ContainerRegistry.getInstance().findInstanceContainers(**filter_dict)
-
- ## Find all usable qualities for a machine and extruders.
- #
- # Finds all of the qualities for this combination of machine and extruders.
- # Only one quality per quality type is returned. i.e. if there are 2 qualities with quality_type=normal
- # then only one of then is returned (at random).
- #
- # \param global_container_stack \type{GlobalStack} the global machine definition
- # \param extruder_stacks \type{List[ExtruderStack]} the list of extruder stacks
- # \return \type{List[InstanceContainer]} the list of the matching qualities. The quality profiles
- # return come from the first extruder in the given list of extruders.
- def findAllUsableQualitiesForMachineAndExtruders(self, global_container_stack: "GlobalStack", extruder_stacks: List["ExtruderStack"]) -> List[InstanceContainer]:
- global_machine_definition = global_container_stack.getBottom()
-
- machine_manager = Application.getInstance().getMachineManager()
- active_stack_id = machine_manager.activeStackId
-
- materials = []
-
- for stack in extruder_stacks:
- if stack.getId() == active_stack_id and machine_manager.newMaterial:
- materials.append(machine_manager.newMaterial)
- else:
- materials.append(stack.material)
-
- quality_types = self.findAllQualityTypesForMachineAndMaterials(global_machine_definition, materials)
-
- # Map the list of quality_types to InstanceContainers
- qualities = self.findAllQualitiesForMachineMaterial(global_machine_definition, materials[0])
- quality_type_dict = {}
- for quality in qualities:
- quality_type_dict[quality.getMetaDataEntry("quality_type")] = quality
-
- return [quality_type_dict[quality_type] for quality_type in quality_types]
-
- ## Fetch more basic versions of a material.
- #
- # This tries to find a generic or basic version of the given material.
- # \param material_container \type{Dict[str, Any]} The metadata of a
- # material to find the basic versions of.
- # \return \type{List[Dict[str, Any]]} A list of the metadata of basic
- # materials, or an empty list if none could be found.
- def _getBasicMaterialMetadatas(self, material_container: Dict[str, Any]) -> List[Dict[str, Any]]:
- if "definition" not in material_container:
- definition_id = "fdmprinter"
- else:
- material_container_definition = ContainerRegistry.getInstance().findDefinitionContainersMetadata(id = material_container["definition"])
- if not material_container_definition:
- definition_id = "fdmprinter"
- else:
- material_container_definition = material_container_definition[0]
- if "has_machine_quality" not in material_container_definition:
- definition_id = "fdmprinter"
- else:
- definition_id = material_container_definition.get("quality_definition", material_container_definition["id"])
-
- base_material = material_container.get("material")
- if base_material:
- # There is a basic material specified
- criteria = {
- "type": "material",
- "name": base_material,
- "definition": definition_id,
- "variant": material_container.get("variant")
- }
- containers = ContainerRegistry.getInstance().findInstanceContainersMetadata(**criteria)
- return containers
-
- return []
-
- def _getFilteredContainers(self, **kwargs):
- return self._getFilteredContainersForStack(None, None, **kwargs)
-
- def _getFilteredContainersForStack(self, machine_definition: "DefinitionContainerInterface" = None, material_metadata: Optional[List[Dict[str, Any]]] = None, **kwargs):
- # Fill in any default values.
- if machine_definition is None:
- machine_definition = Application.getInstance().getGlobalContainerStack().getBottom()
- quality_definition_id = machine_definition.getMetaDataEntry("quality_definition")
- if quality_definition_id is not None:
- machine_definition = ContainerRegistry.getInstance().findDefinitionContainers(id = quality_definition_id)[0]
-
- if not material_metadata:
- active_stacks = ExtruderManager.getInstance().getActiveGlobalAndExtruderStacks()
- if active_stacks:
- material_metadata = [stack.material.getMetaData() for stack in active_stacks]
-
- criteria = kwargs
- filter_by_material = False
-
- machine_definition = self.getParentMachineDefinition(machine_definition)
- criteria["definition"] = machine_definition.getId()
- found_containers_with_machine_definition = ContainerRegistry.getInstance().findInstanceContainersMetadata(**criteria)
- whole_machine_definition = self.getWholeMachineDefinition(machine_definition)
- if whole_machine_definition.getMetaDataEntry("has_machine_quality"):
- definition_id = machine_definition.getMetaDataEntry("quality_definition", whole_machine_definition.getId())
- criteria["definition"] = definition_id
-
- filter_by_material = whole_machine_definition.getMetaDataEntry("has_materials")
- # only fall back to "fdmprinter" when there is no container for this machine
- elif not found_containers_with_machine_definition:
- criteria["definition"] = "fdmprinter"
-
- # Stick the material IDs in a set
- material_ids = set()
-
- for material_instance in material_metadata:
- if material_instance is not None:
- # Add the parent material too.
- for basic_material in self._getBasicMaterialMetadatas(material_instance):
- material_ids.add(basic_material["id"])
- material_ids.add(material_instance["id"])
- containers = ContainerRegistry.getInstance().findInstanceContainers(**criteria)
-
- result = []
- for container in containers:
- # If the machine specifies we should filter by material, exclude containers that do not match any active material.
- if filter_by_material and container.getMetaDataEntry("material") not in material_ids and "global_quality" not in kwargs:
- continue
- result.append(container)
-
- return result
-
- ## Get the parent machine definition of a machine definition.
- #
- # \param machine_definition \type{DefinitionContainer} This may be a normal machine definition or
- # an extruder definition.
- # \return \type{DefinitionContainer} the parent machine definition. If the given machine
- # definition doesn't have a parent then it is simply returned.
- def getParentMachineDefinition(self, machine_definition: "DefinitionContainerInterface") -> "DefinitionContainerInterface":
- container_registry = ContainerRegistry.getInstance()
-
- machine_entry = machine_definition.getMetaDataEntry("machine")
- if machine_entry is None:
- # We have a normal (whole) machine defintion
- quality_definition = machine_definition.getMetaDataEntry("quality_definition")
- if quality_definition is not None:
- parent_machine_definition = container_registry.findDefinitionContainers(id = quality_definition)[0]
- return self.getParentMachineDefinition(parent_machine_definition)
- else:
- return machine_definition
- else:
- # This looks like an extruder. Find the rest of the machine.
- whole_machine = container_registry.findDefinitionContainers(id = machine_entry)[0]
- parent_machine = self.getParentMachineDefinition(whole_machine)
- if whole_machine is parent_machine:
- # This extruder already belongs to a 'parent' machine def.
- return machine_definition
- else:
- # Look up the corresponding extruder definition in the parent machine definition.
- extruder_position = machine_definition.getMetaDataEntry("position")
- parent_extruder_id = parent_machine.getMetaDataEntry("machine_extruder_trains")[extruder_position]
- return container_registry.findDefinitionContainers(id = parent_extruder_id)[0]
-
- ## Get the whole/global machine definition from an extruder definition.
- #
- # \param machine_definition \type{DefinitionContainer} This may be a normal machine definition or
- # an extruder definition.
- # \return \type{DefinitionContainerInterface}
- def getWholeMachineDefinition(self, machine_definition: "DefinitionContainerInterface") -> "DefinitionContainerInterface":
- machine_entry = machine_definition.getMetaDataEntry("machine")
- if machine_entry is None:
- # This already is a 'global' machine definition.
- return machine_definition
- else:
- container_registry = ContainerRegistry.getInstance()
- whole_machine = container_registry.findDefinitionContainers(id = machine_entry)[0]
- return whole_machine
diff --git a/cura/Scene/ConvexHullDecorator.py b/cura/Scene/ConvexHullDecorator.py
index 3a563c2764..66bc8a7fc3 100644
--- a/cura/Scene/ConvexHullDecorator.py
+++ b/cura/Scene/ConvexHullDecorator.py
@@ -1,6 +1,8 @@
# Copyright (c) 2016 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.Math.Polygon import Polygon
from UM.Scene.SceneNodeDecorator import SceneNodeDecorator
@@ -22,6 +24,10 @@ class ConvexHullDecorator(SceneNodeDecorator):
self._global_stack = None
+ # Make sure the timer is created on the main thread
+ self._recompute_convex_hull_timer = None
+ Application.getInstance().callLater(self.createRecomputeConvexHullTimer)
+
self._raft_thickness = 0.0
# For raft thickness, DRY
self._build_volume = Application.getInstance().getBuildVolume()
@@ -33,6 +39,12 @@ class ConvexHullDecorator(SceneNodeDecorator):
self._onGlobalStackChanged()
+ def createRecomputeConvexHullTimer(self):
+ self._recompute_convex_hull_timer = QTimer()
+ self._recompute_convex_hull_timer.setInterval(200)
+ self._recompute_convex_hull_timer.setSingleShot(True)
+ self._recompute_convex_hull_timer.timeout.connect(self.recomputeConvexHull)
+
def setNode(self, node):
previous_node = self._node
# Disconnect from previous node signals
@@ -99,6 +111,12 @@ class ConvexHullDecorator(SceneNodeDecorator):
return self._compute2DConvexHull()
return None
+ def recomputeConvexHullDelayed(self):
+ if self._recompute_convex_hull_timer is not None:
+ self._recompute_convex_hull_timer.start()
+ else:
+ self.recomputeConvexHull()
+
def recomputeConvexHull(self):
controller = Application.getInstance().getController()
root = controller.getScene().getRoot()
@@ -279,7 +297,8 @@ class ConvexHullDecorator(SceneNodeDecorator):
def _onChanged(self, *args):
self._raft_thickness = self._build_volume.getRaftThickness()
- self.recomputeConvexHull()
+ if not args or args[0] == self._node:
+ self.recomputeConvexHullDelayed()
def _onGlobalStackChanged(self):
if self._global_stack:
diff --git a/cura/Scene/ConvexHullNode.py b/cura/Scene/ConvexHullNode.py
index 6c8c201498..1131958627 100644
--- a/cura/Scene/ConvexHullNode.py
+++ b/cura/Scene/ConvexHullNode.py
@@ -68,7 +68,7 @@ class ConvexHullNode(SceneNode):
ConvexHullNode.shader.setUniformValue("u_opacity", 0.6)
if self.getParent():
- if self.getMeshData() and isinstance(self._node, SceneNode) and self._node.callDecoration("getBuildPlateNumber") == Application.getInstance().getBuildPlateModel().activeBuildPlate:
+ if self.getMeshData() and isinstance(self._node, SceneNode) and self._node.callDecoration("getBuildPlateNumber") == Application.getInstance().getMultiBuildPlateModel().activeBuildPlate:
renderer.queueNode(self, transparent = True, shader = ConvexHullNode.shader, backface_cull = True, sort = -8)
if self._convex_hull_head_mesh:
renderer.queueNode(self, shader = ConvexHullNode.shader, transparent = True, mesh = self._convex_hull_head_mesh, backface_cull = True, sort = -8)
diff --git a/cura/Scene/CuraSceneController.py b/cura/Scene/CuraSceneController.py
index a93a8769d0..749c5257a2 100644
--- a/cura/Scene/CuraSceneController.py
+++ b/cura/Scene/CuraSceneController.py
@@ -4,7 +4,7 @@ from PyQt5.QtCore import Qt, pyqtSlot, QObject
from PyQt5.QtWidgets import QApplication
from cura.ObjectsModel import ObjectsModel
-from cura.BuildPlateModel import BuildPlateModel
+from cura.Machines.Models.MultiBuildPlateModel import MultiBuildPlateModel
from UM.Application import Application
from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator
@@ -16,11 +16,11 @@ from UM.Signal import Signal
class CuraSceneController(QObject):
activeBuildPlateChanged = Signal()
- def __init__(self, objects_model: ObjectsModel, build_plate_model: BuildPlateModel):
+ def __init__(self, objects_model: ObjectsModel, multi_build_plate_model: MultiBuildPlateModel):
super().__init__()
self._objects_model = objects_model
- self._build_plate_model = build_plate_model
+ self._multi_build_plate_model = multi_build_plate_model
self._active_build_plate = -1
self._last_selected_index = 0
@@ -41,9 +41,9 @@ class CuraSceneController(QObject):
self._max_build_plate = max_build_plate
changed = True
if changed:
- self._build_plate_model.setMaxBuildPlate(self._max_build_plate)
+ self._multi_build_plate_model.setMaxBuildPlate(self._max_build_plate)
build_plates = [{"name": "Build Plate %d" % (i + 1), "buildPlateNumber": i} for i in range(self._max_build_plate + 1)]
- self._build_plate_model.setItems(build_plates)
+ self._multi_build_plate_model.setItems(build_plates)
if self._active_build_plate > self._max_build_plate:
build_plate_number = 0
if self._last_selected_index >= 0: # go to the buildplate of the item you last selected
@@ -59,6 +59,8 @@ class CuraSceneController(QObject):
for node in DepthFirstIterator(Application.getInstance().getController().getScene().getRoot()):
if node.callDecoration("isSliceable"):
build_plate_number = node.callDecoration("getBuildPlateNumber")
+ if build_plate_number is None:
+ build_plate_number = 0
max_build_plate = max(build_plate_number, max_build_plate)
return max_build_plate
@@ -102,12 +104,12 @@ class CuraSceneController(QObject):
self._active_build_plate = nr
Selection.clear()
- self._build_plate_model.setActiveBuildPlate(nr)
+ self._multi_build_plate_model.setActiveBuildPlate(nr)
self._objects_model.setActiveBuildPlate(nr)
self.activeBuildPlateChanged.emit()
@staticmethod
def createCuraSceneController():
objects_model = Application.getInstance().getObjectsModel()
- build_plate_model = Application.getInstance().getBuildPlateModel()
- return CuraSceneController(objects_model = objects_model, build_plate_model = build_plate_model)
+ multi_build_plate_model = Application.getInstance().getMultiBuildPlateModel()
+ return CuraSceneController(objects_model = objects_model, multi_build_plate_model = multi_build_plate_model)
diff --git a/cura/Scene/CuraSceneNode.py b/cura/Scene/CuraSceneNode.py
index 1635d37b5d..b29108d636 100644
--- a/cura/Scene/CuraSceneNode.py
+++ b/cura/Scene/CuraSceneNode.py
@@ -1,8 +1,13 @@
+# Copyright (c) 2018 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+from copy import deepcopy
+from typing import List
+
from UM.Application import Application
-from UM.Logger import Logger
from UM.Math.AxisAlignedBox import AxisAlignedBox
from UM.Scene.SceneNode import SceneNode
-from copy import deepcopy
+
+from cura.Settings.SettingOverrideDecorator import SettingOverrideDecorator
## Scene nodes that are models are only seen when selecting the corresponding build plate
@@ -10,6 +15,8 @@ from copy import deepcopy
class CuraSceneNode(SceneNode):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
+ if "no_setting_override" not in kwargs:
+ self.addDecorator(SettingOverrideDecorator()) # now we always have a getActiveExtruderPosition, unless explicitly disabled
self._outside_buildarea = False
def setOutsideBuildArea(self, new_value):
@@ -19,14 +26,86 @@ class CuraSceneNode(SceneNode):
return self._outside_buildarea or self.callDecoration("getBuildPlateNumber") < 0
def isVisible(self):
- return super().isVisible() and self.callDecoration("getBuildPlateNumber") == Application.getInstance().getBuildPlateModel().activeBuildPlate
+ return super().isVisible() and self.callDecoration("getBuildPlateNumber") == Application.getInstance().getMultiBuildPlateModel().activeBuildPlate
def isSelectable(self) -> bool:
- return super().isSelectable() and self.callDecoration("getBuildPlateNumber") == Application.getInstance().getBuildPlateModel().activeBuildPlate
+ return super().isSelectable() and self.callDecoration("getBuildPlateNumber") == Application.getInstance().getMultiBuildPlateModel().activeBuildPlate
+
+ ## Get the extruder used to print this node. If there is no active node, then the extruder in position zero is returned
+ # TODO The best way to do it is by adding the setActiveExtruder decorator to every node when is loaded
+ def getPrintingExtruder(self):
+ global_container_stack = Application.getInstance().getGlobalContainerStack()
+ per_mesh_stack = self.callDecoration("getStack")
+ extruders = list(global_container_stack.extruders.values())
+
+ # Use the support extruder instead of the active extruder if this is a support_mesh
+ if per_mesh_stack:
+ if per_mesh_stack.getProperty("support_mesh", "value"):
+ return extruders[int(global_container_stack.getProperty("support_extruder_nr", "value"))]
+
+ # It's only set if you explicitly choose an extruder
+ extruder_id = self.callDecoration("getActiveExtruder")
+
+ for extruder in extruders:
+ # Find out the extruder if we know the id.
+ 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
+ try:
+ if extruder.getMetaDataEntry("position", default = "0") == "0": # Check if the position is zero
+ return extruder
+ except ValueError:
+ continue
+
+ # This point should never be reached
+ return None
+
+ ## Return the color of the material used to print this model
+ def getDiffuseColor(self) -> List[float]:
+ printing_extruder = self.getPrintingExtruder()
+
+ material_color = "#808080" # Fallback color
+ if printing_extruder is not None and printing_extruder.material:
+ material_color = printing_extruder.material.getMetaDataEntry("color_code", default = material_color)
+
+ # Colors are passed as rgb hex strings (eg "#ffffff"), and the shader needs
+ # an rgba list of floats (eg [1.0, 1.0, 1.0, 1.0])
+ return [
+ int(material_color[1:3], 16) / 255,
+ int(material_color[3:5], 16) / 255,
+ int(material_color[5:7], 16) / 255,
+ 1.0
+ ]
+
+ ## Return if the provided bbox collides with the bbox of this scene node
+ def collidesWithBbox(self, check_bbox):
+ bbox = self.getBoundingBox()
+
+ # 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):
+ convex_hull = self.callDecoration("getConvexHull")
+ if convex_hull:
+ if not convex_hull.isValid():
+ return False
+
+ # Check for collisions between disallowed areas and the object
+ for area in areas:
+ overlap = convex_hull.intersectsPolygon(area)
+ if overlap is None:
+ continue
+ return True
+ return False
## Taken from SceneNode, but replaced SceneNode with CuraSceneNode
def __deepcopy__(self, memo):
- copy = CuraSceneNode()
+ copy = CuraSceneNode(no_setting_override = True) # Setting override will be added later
copy.setTransformation(self.getLocalTransformation())
copy.setMeshData(self._mesh_data)
copy.setVisible(deepcopy(self._visible, memo))
diff --git a/cura/Settings/ContainerManager.py b/cura/Settings/ContainerManager.py
index eefc109cbc..7161169b22 100644
--- a/cura/Settings/ContainerManager.py
+++ b/cura/Settings/ContainerManager.py
@@ -1,16 +1,14 @@
# Copyright (c) 2017 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
-import copy
import os.path
-import urllib
+import urllib.parse
import uuid
-from typing import Any, Dict, List, Union
+from typing import Dict, Union
from PyQt5.QtCore import QObject, QUrl, QVariant
from UM.FlameProfiler import pyqtSlot
from PyQt5.QtWidgets import QMessageBox
-from UM.Util import parseBool
from UM.PluginRegistry import PluginRegistry
from UM.SaveFile import SaveFile
@@ -22,7 +20,6 @@ from UM.Application import Application
from UM.Settings.ContainerStack import ContainerStack
from UM.Settings.DefinitionContainer import DefinitionContainer
from UM.Settings.InstanceContainer import InstanceContainer
-from cura.QualityManager import QualityManager
from UM.MimeTypeDatabase import MimeTypeNotFoundError
from UM.Settings.ContainerRegistry import ContainerRegistry
@@ -30,9 +27,11 @@ from UM.Settings.ContainerRegistry import ContainerRegistry
from UM.i18n import i18nCatalog
from cura.Settings.ExtruderManager import ExtruderManager
+from cura.Settings.ExtruderStack import ExtruderStack
catalog = i18nCatalog("cura")
+
## Manager class that contains common actions to deal with containers in Cura.
#
# This is primarily intended as a class to be able to perform certain actions
@@ -42,154 +41,12 @@ class ContainerManager(QObject):
def __init__(self, parent = None):
super().__init__(parent)
+ self._application = Application.getInstance()
self._container_registry = ContainerRegistry.getInstance()
- self._machine_manager = Application.getInstance().getMachineManager()
+ self._machine_manager = self._application.getMachineManager()
+ self._material_manager = self._application.getMaterialManager()
self._container_name_filters = {}
- ## Create a duplicate of the specified container
- #
- # This will create and add a duplicate of the container corresponding
- # to the container ID.
- #
- # \param container_id \type{str} The ID of the container to duplicate.
- #
- # \return The ID of the new container, or an empty string if duplication failed.
- @pyqtSlot(str, result = str)
- def duplicateContainer(self, container_id):
- #TODO: It should be able to duplicate a container of which only the metadata is known.
- containers = self._container_registry.findContainers(id = container_id)
- if not containers:
- Logger.log("w", "Could duplicate container %s because it was not found.", container_id)
- return ""
-
- container = containers[0]
- new_container = self.duplicateContainerInstance(container)
- return new_container.getId()
-
- ## Create a duplicate of the given container instance
- #
- # This will create and add a duplicate of the container that was passed.
- #
- # \param container \type{ContainerInterface} The container to duplicate.
- #
- # \return The duplicated container, or None if duplication failed.
- def duplicateContainerInstance(self, container):
- new_container = None
- new_name = self._container_registry.uniqueName(container.getName())
- # Only InstanceContainer has a duplicate method at the moment.
- # So fall back to serialize/deserialize when no duplicate method exists.
- if hasattr(container, "duplicate"):
- new_container = container.duplicate(new_name)
- else:
- new_container = container.__class__(new_name)
- new_container.deserialize(container.serialize())
- new_container.setName(new_name)
-
- # TODO: we probably don't want to add it to the registry here!
- if new_container:
- self._container_registry.addContainer(new_container)
-
- return new_container
-
- ## Change the name of a specified container to a new name.
- #
- # \param container_id \type{str} The ID of the container to change the name of.
- # \param new_id \type{str} The new ID of the container.
- # \param new_name \type{str} The new name of the specified container.
- #
- # \return True if successful, False if not.
- @pyqtSlot(str, str, str, result = bool)
- def renameContainer(self, container_id, new_id, new_name):
- containers = self._container_registry.findContainers(id = container_id)
- if not containers:
- Logger.log("w", "Could rename container %s because it was not found.", container_id)
- return False
-
- container = containers[0]
- # First, remove the container from the registry. This will clean up any files related to the container.
- self._container_registry.removeContainer(container_id)
-
- # Ensure we have a unique name for the container
- new_name = self._container_registry.uniqueName(new_name)
-
- # Then, update the name and ID of the container
- container.setName(new_name)
- container._id = new_id # TODO: Find a nicer way to set a new, unique ID
-
- # Finally, re-add the container so it will be properly serialized again.
- self._container_registry.addContainer(container)
-
- return True
-
- ## Remove the specified container.
- #
- # \param container_id \type{str} The ID of the container to remove.
- #
- # \return True if the container was successfully removed, False if not.
- @pyqtSlot(str, result = bool)
- def removeContainer(self, container_id):
- containers = self._container_registry.findContainers(id = container_id)
- if not containers:
- Logger.log("w", "Could not remove container %s because it was not found.", container_id)
- return False
-
- self._container_registry.removeContainer(containers[0].getId())
-
- return True
-
- ## Merge a container with another.
- #
- # This will try to merge one container into the other, by going through the container
- # and setting the right properties on the other container.
- #
- # \param merge_into_id \type{str} The ID of the container to merge into.
- # \param merge_id \type{str} The ID of the container to merge.
- #
- # \return True if successfully merged, False if not.
- @pyqtSlot(str, result = bool)
- def mergeContainers(self, merge_into_id, merge_id):
- containers = self._container_registry.findContainers(id = merge_into_id)
- if not containers:
- Logger.log("w", "Could merge into container %s because it was not found.", merge_into_id)
- return False
-
- merge_into = containers[0]
-
- containers = self._container_registry.findContainers(id = merge_id)
- if not containers:
- Logger.log("w", "Could not merge container %s because it was not found", merge_id)
- return False
-
- merge = containers[0]
-
- if not isinstance(merge, type(merge_into)):
- Logger.log("w", "Cannot merge two containers of different types")
- return False
-
- self._performMerge(merge_into, merge)
-
- return True
-
- ## Clear the contents of a container.
- #
- # \param container_id \type{str} The ID of the container to clear.
- #
- # \return True if successful, False if not.
- @pyqtSlot(str, result = bool)
- def clearContainer(self, container_id):
- if self._container_registry.isReadOnly(container_id):
- Logger.log("w", "Cannot clear read-only container %s", container_id)
- return False
-
- containers = self._container_registry.findContainers(id = container_id)
- if not containers:
- Logger.log("w", "Could clear container %s because it was not found.", container_id)
- return False
-
- containers[0].clear()
-
- return True
-
@pyqtSlot(str, str, result=str)
def getContainerMetaDataEntry(self, container_id, entry_name):
metadatas = self._container_registry.findContainersMetadata(id = container_id)
@@ -211,18 +68,15 @@ class ContainerManager(QObject):
# \param entry_value The new value of the entry.
#
# \return True if successful, False if not.
- @pyqtSlot(str, str, str, result = bool)
- def setContainerMetaDataEntry(self, container_id, entry_name, entry_value):
- if self._container_registry.isReadOnly(container_id):
- Logger.log("w", "Cannot set metadata of read-only container %s.", container_id)
+ # TODO: This is ONLY used by MaterialView for material containers. Maybe refactor this.
+ @pyqtSlot("QVariant", str, str)
+ def setContainerMetaDataEntry(self, container_node, entry_name, entry_value):
+ root_material_id = container_node.metadata["base_file"]
+ if self._container_registry.isReadOnly(root_material_id):
+ Logger.log("w", "Cannot set metadata of read-only container %s.", root_material_id)
return False
- containers = self._container_registry.findContainers(id = container_id) #We need the complete container, since we need to know whether the container is read-only or not.
- if not containers:
- Logger.log("w", "Could not set metadata of container %s because it was not found.", container_id)
- return False
-
- container = containers[0]
+ material_group = self._material_manager.getMaterialGroup(root_material_id)
entries = entry_name.split("/")
entry_name = entries.pop()
@@ -230,7 +84,7 @@ class ContainerManager(QObject):
sub_item_changed = False
if entries:
root_name = entries.pop(0)
- root = container.getMetaDataEntry(root_name)
+ root = material_group.root_material_node.metadata.get(root_name)
item = root
for _ in range(len(entries)):
@@ -243,12 +97,11 @@ class ContainerManager(QObject):
entry_name = root_name
entry_value = root
+ container = material_group.root_material_node.getContainer()
container.setMetaDataEntry(entry_name, entry_value)
if sub_item_changed: #If it was only a sub-item that has changed then the setMetaDataEntry won't correctly notice that something changed, and we must manually signal that the metadata changed.
container.metaDataChanged.emit(container)
- return True
-
## Set a setting property of the specified container.
#
# This will set the specified property of the specified setting of the container
@@ -306,60 +159,6 @@ class ContainerManager(QObject):
return container.getProperty(setting_key, property_name)
- ## Set the name of the specified container.
- @pyqtSlot(str, str, result = bool)
- def setContainerName(self, container_id, new_name):
- if self._container_registry.isReadOnly(container_id):
- Logger.log("w", "Cannot set name of read-only container %s.", container_id)
- return False
-
- containers = self._container_registry.findContainers(id = container_id) #We need to get the full container, not just metadata, since we need to know whether it's read-only.
- if not containers:
- Logger.log("w", "Could not set name of container %s because it was not found.", container_id)
- return False
-
- containers[0].setName(new_name)
-
- return True
-
- ## Find instance containers matching certain criteria.
- #
- # This effectively forwards to
- # ContainerRegistry::findInstanceContainersMetadata.
- #
- # \param criteria A dict of key - value pairs to search for.
- #
- # \return A list of container IDs that match the given criteria.
- @pyqtSlot("QVariantMap", result = "QVariantList")
- def findInstanceContainers(self, criteria):
- return [entry["id"] for entry in self._container_registry.findInstanceContainersMetadata(**criteria)]
-
- @pyqtSlot(str, result = bool)
- def isContainerUsed(self, container_id):
- Logger.log("d", "Checking if container %s is currently used", container_id)
- # check if this is a material container. If so, check if any material with the same base is being used by any
- # stacks.
- container_ids_to_check = [container_id]
- container_results = self._container_registry.findInstanceContainersMetadata(id = container_id, type = "material")
- if container_results:
- this_container = container_results[0]
- material_base_file = this_container["id"]
- if "base_file" in this_container:
- material_base_file = this_container["base_file"]
- # check all material container IDs with the same base
- material_containers = self._container_registry.findInstanceContainersMetadata(base_file = material_base_file,
- type = "material")
- if material_containers:
- container_ids_to_check = [container["id"] for container in material_containers]
-
- all_stacks = self._container_registry.findContainerStacks()
- for stack in all_stacks:
- for used_container_id in container_ids_to_check:
- if used_container_id in [child.getId() for child in stack.getContainers()]:
- Logger.log("d", "The container is in use by %s", stack.getId())
- return True
- return False
-
@pyqtSlot(str, result = str)
def makeUniqueName(self, original_name):
return self._container_registry.uniqueName(original_name)
@@ -399,7 +198,7 @@ class ContainerManager(QObject):
@pyqtSlot(str, str, QUrl, result = "QVariantMap")
def exportContainer(self, container_id: str, file_type: str, file_url_or_string: Union[QUrl, str]) -> Dict[str, str]:
if not container_id or not file_type or not file_url_or_string:
- return { "status": "error", "message": "Invalid arguments"}
+ return {"status": "error", "message": "Invalid arguments"}
if isinstance(file_url_or_string, QUrl):
file_url = file_url_or_string.toLocalFile()
@@ -407,20 +206,20 @@ class ContainerManager(QObject):
file_url = file_url_or_string
if not file_url:
- return { "status": "error", "message": "Invalid path"}
+ return {"status": "error", "message": "Invalid path"}
mime_type = None
- if not file_type in self._container_name_filters:
+ if file_type not in self._container_name_filters:
try:
mime_type = MimeTypeDatabase.getMimeTypeForFile(file_url)
except MimeTypeNotFoundError:
- return { "status": "error", "message": "Unknown File Type" }
+ return {"status": "error", "message": "Unknown File Type"}
else:
mime_type = self._container_name_filters[file_type]["mime"]
containers = self._container_registry.findContainers(id = container_id)
if not containers:
- return { "status": "error", "message": "Container not found"}
+ return {"status": "error", "message": "Container not found"}
container = containers[0]
if Platform.isOSX() and "." in file_url:
@@ -437,12 +236,12 @@ class ContainerManager(QObject):
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_url))
if result == QMessageBox.No:
- return { "status": "cancelled", "message": "User cancelled"}
+ return {"status": "cancelled", "message": "User cancelled"}
try:
contents = container.serialize()
except NotImplementedError:
- return { "status": "error", "message": "Unable to serialize container"}
+ return {"status": "error", "message": "Unable to serialize container"}
if contents is None:
return {"status": "error", "message": "Serialization returned None. Unable to write to file"}
@@ -450,7 +249,7 @@ class ContainerManager(QObject):
with SaveFile(file_url, "w") as f:
f.write(contents)
- return { "status": "success", "message": "Succesfully exported container", "path": file_url}
+ return {"status": "success", "message": "Successfully exported container", "path": file_url}
## Imports a profile from a file
#
@@ -459,9 +258,9 @@ class ContainerManager(QObject):
# \return \type{Dict} dict with a 'status' key containing the string 'success' or 'error', and a 'message' key
# containing a message for the user
@pyqtSlot(QUrl, result = "QVariantMap")
- def importContainer(self, file_url_or_string: Union[QUrl, str]) -> Dict[str, str]:
+ def importMaterialContainer(self, file_url_or_string: Union[QUrl, str]) -> Dict[str, str]:
if not file_url_or_string:
- return { "status": "error", "message": "Invalid path"}
+ return {"status": "error", "message": "Invalid path"}
if isinstance(file_url_or_string, QUrl):
file_url = file_url_or_string.toLocalFile()
@@ -469,16 +268,16 @@ class ContainerManager(QObject):
file_url = file_url_or_string
if not file_url or not os.path.exists(file_url):
- return { "status": "error", "message": "Invalid path" }
+ return {"status": "error", "message": "Invalid path"}
try:
mime_type = MimeTypeDatabase.getMimeTypeForFile(file_url)
except MimeTypeNotFoundError:
- return { "status": "error", "message": "Could not determine mime type of file" }
+ return {"status": "error", "message": "Could not determine mime type of file"}
container_type = self._container_registry.getContainerForMimeType(mime_type)
if not container_type:
- return { "status": "error", "message": "Could not find a container to handle the specified file."}
+ return {"status": "error", "message": "Could not find a container to handle the specified file."}
container_id = urllib.parse.unquote_plus(mime_type.stripExtension(os.path.basename(file_url)))
container_id = self._container_registry.uniqueName(container_id)
@@ -486,16 +285,18 @@ class ContainerManager(QObject):
container = container_type(container_id)
try:
- with open(file_url, "rt") as f:
+ with open(file_url, "rt", encoding = "utf-8") as f:
container.deserialize(f.read())
except PermissionError:
- return { "status": "error", "message": "Permission denied when trying to read the file"}
+ return {"status": "error", "message": "Permission denied when trying to read the file"}
+ except Exception as ex:
+ return {"status": "error", "message": str(ex)}
- container.setName(container_id)
+ container.setDirty(True)
self._container_registry.addContainer(container)
- return { "status": "success", "message": "Successfully imported container {0}".format(container.getName()) }
+ return {"status": "success", "message": "Successfully imported container {0}".format(container.getName())}
## Update the current active quality changes container with the settings from the user container.
#
@@ -520,7 +321,7 @@ class ContainerManager(QObject):
self._performMerge(quality_changes, stack.getTop())
- self._machine_manager.activeQualityChanged.emit()
+ self._machine_manager.activeQualityChangesGroupChanged.emit()
return True
@@ -533,414 +334,47 @@ class ContainerManager(QObject):
# Go through global and extruder stacks and clear their topmost container (the user settings).
for stack in ExtruderManager.getInstance().getActiveGlobalAndExtruderStacks():
- container = stack.getTop()
+ container = stack.userChanges
container.clear()
send_emits_containers.append(container)
+ # user changes are possibly added to make the current setup match the current enabled extruders
+ Application.getInstance().getMachineManager().correctExtruderSettings()
+
for container in send_emits_containers:
container.sendPostponedEmits()
- ## Create quality changes containers from the user containers in the active stacks.
- #
- # This will go through the global and extruder stacks and create quality_changes containers from
- # the user containers in each stack. These then replace the quality_changes containers in the
- # stack and clear the user settings.
- #
- # \return \type{bool} True if the operation was successfully, False if not.
- @pyqtSlot(str, result = bool)
- def createQualityChanges(self, base_name):
- global_stack = Application.getInstance().getGlobalContainerStack()
- if not global_stack:
- return False
-
- active_quality_name = self._machine_manager.activeQualityName
- if active_quality_name == "":
- Logger.log("w", "No quality container found in stack %s, cannot create profile", global_stack.getId())
- return False
-
- self._machine_manager.blurSettings.emit()
- if base_name is None or base_name == "":
- base_name = active_quality_name
- unique_name = self._container_registry.uniqueName(base_name)
-
- # Go through the active stacks and create quality_changes containers from the user containers.
- for stack in ExtruderManager.getInstance().getActiveGlobalAndExtruderStacks():
- user_container = stack.getTop()
- quality_container = stack.quality
- quality_changes_container = stack.qualityChanges
- if not quality_container or not quality_changes_container:
- Logger.log("w", "No quality or quality changes container found in stack %s, ignoring it", stack.getId())
- continue
-
- extruder_id = None if stack is global_stack else QualityManager.getInstance().getParentMachineDefinition(stack.getBottom()).getId()
- new_changes = self._createQualityChanges(quality_container, unique_name,
- Application.getInstance().getGlobalContainerStack().getBottom(),
- extruder_id)
- self._performMerge(new_changes, quality_changes_container, clear_settings = False)
- self._performMerge(new_changes, user_container)
-
- self._container_registry.addContainer(new_changes)
- stack.replaceContainer(stack.getContainerIndex(quality_changes_container), new_changes)
-
- self._machine_manager.activeQualityChanged.emit()
- return True
-
- ## Remove all quality changes containers matching a specified name.
- #
- # This will search for quality_changes containers matching the supplied name and remove them.
- # Note that if the machine specifies that qualities should be filtered by machine and/or material
- # only the containers related to the active machine/material are removed.
- #
- # \param quality_name The name of the quality changes to remove.
- #
- # \return \type{bool} True if successful, False if not.
- @pyqtSlot(str, result = bool)
- def removeQualityChanges(self, quality_name):
- Logger.log("d", "Attempting to remove the quality change containers with name %s", quality_name)
- containers_found = False
-
- if not quality_name:
- return containers_found # Without a name we will never find a container to remove.
-
- # If the container that is being removed is the currently active quality, set another quality as the active quality
- activate_quality = quality_name == self._machine_manager.activeQualityName
- activate_quality_type = None
-
- global_stack = Application.getInstance().getGlobalContainerStack()
- if not global_stack or not quality_name:
- return ""
- machine_definition = QualityManager.getInstance().getParentMachineDefinition(global_stack.getBottom())
-
- for container in QualityManager.getInstance().findQualityChangesByName(quality_name, machine_definition):
- containers_found = True
- if activate_quality and not activate_quality_type:
- activate_quality_type = container.getMetaDataEntry("quality")
- self._container_registry.removeContainer(container.getId())
-
- if not containers_found:
- Logger.log("d", "Unable to remove quality containers, as we did not find any by the name of %s", quality_name)
-
- elif activate_quality:
- definition_id = "fdmprinter" if not self._machine_manager.filterQualityByMachine else self._machine_manager.activeDefinitionId
- containers = self._container_registry.findInstanceContainersMetadata(type = "quality", definition = definition_id, quality_type = activate_quality_type)
- if containers:
- self._machine_manager.setActiveQuality(containers[0]["id"])
- self._machine_manager.activeQualityChanged.emit()
-
- return containers_found
-
- ## Rename a set of quality changes containers.
- #
- # This will search for quality_changes containers matching the supplied name and rename them.
- # Note that if the machine specifies that qualities should be filtered by machine and/or material
- # only the containers related to the active machine/material are renamed.
- #
- # \param quality_name The name of the quality changes containers to rename.
- # \param new_name The new name of the quality changes.
- #
- # \return True if successful, False if not.
- @pyqtSlot(str, str, result = bool)
- def renameQualityChanges(self, quality_name, new_name):
- Logger.log("d", "User requested QualityChanges container rename of %s to %s", quality_name, new_name)
- if not quality_name or not new_name:
- return False
-
- if quality_name == new_name:
- Logger.log("w", "Unable to rename %s to %s, because they are the same.", quality_name, new_name)
- return True
-
- global_stack = Application.getInstance().getGlobalContainerStack()
- if not global_stack:
- return False
-
- self._machine_manager.blurSettings.emit()
-
- new_name = self._container_registry.uniqueName(new_name)
-
- container_registry = self._container_registry
-
- containers_to_rename = self._container_registry.findInstanceContainersMetadata(type = "quality_changes", name = quality_name)
-
- for container in containers_to_rename:
- stack_id = global_stack.getId()
- if "extruder" in container:
- stack_id = container["extruder"]
- container_registry.renameContainer(container["id"], new_name, self._createUniqueId(stack_id, new_name))
-
- if not containers_to_rename:
- Logger.log("e", "Unable to rename %s, because we could not find the profile", quality_name)
-
- self._machine_manager.activeQualityChanged.emit()
- return True
-
- ## Duplicate a specified set of quality or quality_changes containers.
- #
- # This will search for containers matching the specified name. If the container is a "quality" type container, a new
- # quality_changes container will be created with the specified quality as base. If the container is a "quality_changes"
- # container, it is simply duplicated and renamed.
- #
- # \param quality_name The name of the quality to duplicate.
- #
- # \return A string containing the name of the duplicated containers, or an empty string if it failed.
- @pyqtSlot(str, str, result = str)
- def duplicateQualityOrQualityChanges(self, quality_name, base_name):
- global_stack = Application.getInstance().getGlobalContainerStack()
- if not global_stack or not quality_name:
- return ""
- machine_definition = global_stack.definition
-
- active_stacks = ExtruderManager.getInstance().getActiveGlobalAndExtruderStacks()
- if active_stacks is None:
- return ""
- material_metadatas = [stack.material.getMetaData() for stack in active_stacks]
-
- result = self._duplicateQualityOrQualityChangesForMachineType(quality_name, base_name,
- QualityManager.getInstance().getParentMachineDefinition(machine_definition),
- material_metadatas)
- return result[0].getName() if result else ""
-
- ## Duplicate a quality or quality changes profile specific to a machine type
- #
- # \param quality_name The name of the quality or quality changes container to duplicate.
- # \param base_name The desired name for the new container.
- # \param machine_definition The machine with the specific machine type.
- # \param material_metadatas Metadata of materials
- # \return List of duplicated quality profiles.
- def _duplicateQualityOrQualityChangesForMachineType(self, quality_name: str, base_name: str, machine_definition: DefinitionContainer, material_metadatas: List[Dict[str, Any]]) -> List[InstanceContainer]:
- Logger.log("d", "Attempting to duplicate the quality %s", quality_name)
-
- if base_name is None:
- base_name = quality_name
- # Try to find a Quality with the name.
- container = QualityManager.getInstance().findQualityByName(quality_name, machine_definition, material_metadatas)
- if container:
- Logger.log("d", "We found a quality to duplicate.")
- return self._duplicateQualityForMachineType(container, base_name, machine_definition)
- Logger.log("d", "We found a quality_changes to duplicate.")
- # Assume it is a quality changes.
- return self._duplicateQualityChangesForMachineType(quality_name, base_name, machine_definition)
-
- # Duplicate a quality profile
- def _duplicateQualityForMachineType(self, quality_container, base_name, machine_definition) -> List[InstanceContainer]:
- if base_name is None:
- base_name = quality_container.getName()
- new_name = self._container_registry.uniqueName(base_name)
-
- new_change_instances = []
-
- # Handle the global stack first.
- global_changes = self._createQualityChanges(quality_container, new_name, machine_definition, None)
- new_change_instances.append(global_changes)
- self._container_registry.addContainer(global_changes)
-
- # Handle the extruders if present.
- extruders = machine_definition.getMetaDataEntry("machine_extruder_trains")
- if extruders:
- for extruder_id in extruders:
- extruder = extruders[extruder_id]
- new_changes = self._createQualityChanges(quality_container, new_name, machine_definition, extruder)
- new_change_instances.append(new_changes)
- self._container_registry.addContainer(new_changes)
-
- return new_change_instances
-
- # Duplicate a quality changes container
- def _duplicateQualityChangesForMachineType(self, quality_changes_name, base_name, machine_definition) -> List[InstanceContainer]:
- new_change_instances = []
- for container in QualityManager.getInstance().findQualityChangesByName(quality_changes_name,
- machine_definition):
- base_id = container.getMetaDataEntry("extruder")
- if not base_id:
- base_id = container.getDefinition().getId()
- new_unique_id = self._createUniqueId(base_id, base_name)
- new_container = container.duplicate(new_unique_id, base_name)
- new_change_instances.append(new_container)
- self._container_registry.addContainer(new_container)
-
- return new_change_instances
-
- ## Create a duplicate of a material, which has the same GUID and base_file metadata
- #
- # \return \type{str} the id of the newly created container.
- @pyqtSlot(str, result = str)
- def duplicateMaterial(self, material_id: str) -> str:
- original = self._container_registry.findContainersMetadata(id = material_id)
- if not original:
- Logger.log("d", "Unable to duplicate the material with id %s, because it doesn't exist.", material_id)
- return ""
- original = original[0]
-
- base_container_id = original.get("base_file")
- base_container = self._container_registry.findContainers(id = base_container_id)
- if not base_container:
- Logger.log("d", "Unable to duplicate the material with id {material_id}, because base_file {base_container_id} doesn't exist.".format(material_id = material_id, base_container_id = base_container_id))
- return ""
- base_container = base_container[0]
-
- #We'll copy all containers with the same base.
- #This way the correct variant and machine still gets assigned when loading the copy of the material.
- containers_to_copy = self._container_registry.findInstanceContainers(base_file = base_container_id)
-
- # Ensure all settings are saved.
- Application.getInstance().saveSettings()
-
- # Create a new ID & container to hold the data.
- new_containers = []
- new_base_id = self._container_registry.uniqueName(base_container.getId())
- new_base_container = copy.deepcopy(base_container)
- new_base_container.getMetaData()["id"] = new_base_id
- new_base_container.getMetaData()["base_file"] = new_base_id
- new_containers.append(new_base_container)
-
- #Clone all of them.
- clone_of_original = None #Keeping track of which one is the clone of the original material, since we need to return that.
- for container_to_copy in containers_to_copy:
- #Create unique IDs for every clone.
- current_id = container_to_copy.getId()
- new_id = new_base_id
- if container_to_copy.getMetaDataEntry("definition") != "fdmprinter":
- new_id += "_" + container_to_copy.getMetaDataEntry("definition")
- if container_to_copy.getMetaDataEntry("variant"):
- variant = self._container_registry.findContainers(id = container_to_copy.getMetaDataEntry("variant"))[0]
- new_id += "_" + variant.getName().replace(" ", "_")
- if current_id == material_id:
- clone_of_original = new_id
-
- new_container = copy.deepcopy(container_to_copy)
- new_container.getMetaData()["id"] = new_id
- new_container.getMetaData()["base_file"] = new_base_id
- new_containers.append(new_container)
-
- for container_to_add in new_containers:
- container_to_add.setDirty(True)
- ContainerRegistry.getInstance().addContainer(container_to_add)
- return self._getMaterialContainerIdForActiveMachine(clone_of_original)
-
- ## Create a duplicate of a material or it's original entry
- #
- # \return \type{str} the id of the newly created container.
- @pyqtSlot(str, result = str)
- def duplicateOriginalMaterial(self, material_id):
-
- # check if the given material has a base file (i.e. was shipped by default)
- base_file = self.getContainerMetaDataEntry(material_id, "base_file")
-
- if base_file == "":
- # there is no base file, so duplicate by ID
- return self.duplicateMaterial(material_id)
- else:
- # there is a base file, so duplicate the original material
- return self.duplicateMaterial(base_file)
-
- ## Create a new material by cloning Generic PLA for the current material diameter and setting the GUID to something unqiue
- #
- # \return \type{str} the id of the newly created container.
- @pyqtSlot(result = str)
- def createMaterial(self) -> str:
- # Ensure all settings are saved.
- Application.getInstance().saveSettings()
-
- global_stack = Application.getInstance().getGlobalContainerStack()
- if not global_stack:
- return ""
-
- approximate_diameter = str(round(global_stack.getProperty("material_diameter", "value")))
- containers = self._container_registry.findInstanceContainersMetadata(id = "generic_pla*", approximate_diameter = approximate_diameter)
- if not containers:
- Logger.log("d", "Unable to create a new material by cloning Generic PLA, because it cannot be found for the material diameter for this machine.")
- return ""
-
- base_file = containers[0].get("base_file")
- containers = self._container_registry.findInstanceContainers(id = base_file)
- if not containers:
- Logger.log("d", "Unable to create a new material by cloning Generic PLA, because the base file for Generic PLA for this machine can not be found.")
- return ""
-
- # Create a new ID & container to hold the data.
- new_id = self._container_registry.uniqueName("custom_material")
- container_type = type(containers[0]) # Always XMLMaterialProfile, since we specifically clone the base_file
- duplicated_container = container_type(new_id)
-
- # Instead of duplicating we load the data from the basefile again.
- # This ensures that the inheritance goes well and all "cut up" subclasses of the xmlMaterial profile
- # are also correctly created.
- with open(containers[0].getPath(), encoding="utf-8") as f:
- duplicated_container.deserialize(f.read())
-
- duplicated_container.setMetaDataEntry("GUID", str(uuid.uuid4()))
- duplicated_container.setMetaDataEntry("brand", catalog.i18nc("@label", "Custom"))
- # We're defaulting to PLA, as machines with material profiles don't like material types they don't know.
- # TODO: This is a hack, the only reason this is in now is to bandaid the problem as we're close to a release!
- duplicated_container.setMetaDataEntry("material", "PLA")
- duplicated_container.setName(catalog.i18nc("@label", "Custom Material"))
-
- self._container_registry.addContainer(duplicated_container)
- return self._getMaterialContainerIdForActiveMachine(new_id)
-
- ## Find the id of a material container based on the new material
- # Utilty function that is shared between duplicateMaterial and createMaterial
- #
- # \param base_file \type{str} the id of the created container.
- def _getMaterialContainerIdForActiveMachine(self, base_file):
- global_stack = Application.getInstance().getGlobalContainerStack()
- if not global_stack:
- return base_file
-
- has_machine_materials = parseBool(global_stack.getMetaDataEntry("has_machine_materials", default = False))
- has_variant_materials = parseBool(global_stack.getMetaDataEntry("has_variant_materials", default = False))
- has_variants = parseBool(global_stack.getMetaDataEntry("has_variants", default = False))
- if has_machine_materials or has_variant_materials:
- if has_variants:
- materials = self._container_registry.findInstanceContainersMetadata(type = "material", base_file = base_file, definition = global_stack.getBottom().getId(), variant = self._machine_manager.activeVariantId)
- else:
- materials = self._container_registry.findInstanceContainersMetadata(type = "material", base_file = base_file, definition = global_stack.getBottom().getId())
-
- if materials:
- return materials[0]["id"]
-
- Logger.log("w", "Unable to find a suitable container based on %s for the current machine.", base_file)
- return "" # do not activate a new material if a container can not be found
-
- return base_file
-
## Get a list of materials that have the same GUID as the reference material
#
# \param material_id \type{str} the id of the material for which to get the linked materials.
# \return \type{list} a list of names of materials with the same GUID
- @pyqtSlot(str, result = "QStringList")
- def getLinkedMaterials(self, material_id: str):
- containers = self._container_registry.findInstanceContainersMetadata(id = material_id)
- if not containers:
- Logger.log("d", "Unable to find materials linked to material with id %s, because it doesn't exist.", material_id)
- return []
+ @pyqtSlot("QVariant", result = "QStringList")
+ def getLinkedMaterials(self, material_node):
+ guid = material_node.metadata["GUID"]
- material_container = containers[0]
- material_base_file = material_container.get("base_file", "")
- material_guid = material_container.get("GUID", "")
- if not material_guid:
- Logger.log("d", "Unable to find materials linked to material with id %s, because it doesn't have a GUID.", material_id)
- return []
+ material_group_list = self._material_manager.getMaterialGroupListByGUID(guid)
- containers = self._container_registry.findInstanceContainersMetadata(type = "material", GUID = material_guid)
linked_material_names = []
- for container in containers:
- if container["id"] in [material_id, material_base_file] or container.get("base_file") != container["id"]:
- continue
-
- linked_material_names.append(container["name"])
+ if material_group_list:
+ for material_group in material_group_list:
+ linked_material_names.append(material_group.root_material_node.metadata["name"])
return linked_material_names
## Unlink a material from all other materials by creating a new GUID
# \param material_id \type{str} the id of the material to create a new GUID for.
- @pyqtSlot(str)
- def unlinkMaterial(self, material_id: str):
- containers = self._container_registry.findInstanceContainers(id=material_id)
- if not containers:
- Logger.log("d", "Unable to make the material with id %s unique, because it doesn't exist.", material_id)
- return ""
+ @pyqtSlot("QVariant")
+ def unlinkMaterial(self, material_node):
+ # Get the material group
+ material_group = self._material_manager.getMaterialGroup(material_node.metadata["base_file"])
- containers[0].setMetaDataEntry("GUID", str(uuid.uuid4()))
+ # Generate a new GUID
+ new_guid = str(uuid.uuid4())
+ # Update the GUID
+ # NOTE: We only need to set the root material container because XmlMaterialProfile.setMetaDataEntry() will
+ # take care of the derived containers too
+ container = material_group.root_material_node.getContainer()
+ container.setMetaDataEntry("GUID", new_guid)
## Get the singleton instance for this class.
@classmethod
@@ -958,8 +392,6 @@ class ContainerManager(QObject):
return ContainerManager.getInstance()
def _performMerge(self, merge_into, merge, clear_settings = True):
- assert isinstance(merge, type(merge_into))
-
if merge == merge_into:
return
@@ -1013,81 +445,6 @@ class ContainerManager(QObject):
name_filter = "{0} ({1})".format(mime_type.comment, suffix_list)
self._container_name_filters[name_filter] = entry
- ## Creates a unique ID for a container by prefixing the name with the stack ID.
- #
- # This method creates a unique ID for a container by prefixing it with a specified stack ID.
- # This is done to ensure we have an easily identified ID for quality changes, which have the
- # same name across several stacks.
- #
- # \param stack_id The ID of the stack to prepend.
- # \param container_name The name of the container that we are creating a unique ID for.
- #
- # \return Container name prefixed with stack ID, in lower case with spaces replaced by underscores.
- def _createUniqueId(self, stack_id, container_name):
- result = stack_id + "_" + container_name
- result = result.lower()
- result.replace(" ", "_")
- return result
-
- ## Create a quality changes container for a specified quality container.
- #
- # \param quality_container The quality container to create a changes container for.
- # \param new_name The name of the new quality_changes container.
- # \param machine_definition The machine definition this quality changes container is specific to.
- # \param extruder_id
- #
- # \return A new quality_changes container with the specified container as base.
- def _createQualityChanges(self, quality_container, new_name, machine_definition, extruder_id):
- base_id = machine_definition.getId() if extruder_id is None else extruder_id
-
- # Create a new quality_changes container for the quality.
- quality_changes = InstanceContainer(self._createUniqueId(base_id, new_name))
- quality_changes.setName(new_name)
- quality_changes.addMetaDataEntry("type", "quality_changes")
- quality_changes.addMetaDataEntry("quality_type", quality_container.getMetaDataEntry("quality_type"))
-
- # If we are creating a container for an extruder, ensure we add that to the container
- if extruder_id is not None:
- quality_changes.addMetaDataEntry("extruder", extruder_id)
-
- # If the machine specifies qualities should be filtered, ensure we match the current criteria.
- if not machine_definition.getMetaDataEntry("has_machine_quality"):
- quality_changes.setDefinition("fdmprinter")
- else:
- quality_changes.setDefinition(QualityManager.getInstance().getParentMachineDefinition(machine_definition).getId())
-
- from cura.CuraApplication import CuraApplication
- quality_changes.addMetaDataEntry("setting_version", CuraApplication.SettingVersion)
- return quality_changes
-
-
- ## Import profiles from a list of file_urls.
- # Each QUrl item must end with .curaprofile, or it will not be imported.
- #
- # \param QVariant, essentially a list with QUrl objects.
- # \return Dict with keys status, text
- @pyqtSlot("QVariantList", result="QVariantMap")
- def importProfiles(self, file_urls):
- status = "ok"
- results = {"ok": [], "error": []}
- for file_url in file_urls:
- if not file_url.isValid():
- continue
- path = file_url.toLocalFile()
- if not path:
- continue
- if not path.endswith(".curaprofile"):
- continue
-
- single_result = self._container_registry.importProfile(path)
- if single_result["status"] == "error":
- status = "error"
- results[single_result["status"]].append(single_result["message"])
-
- return {
- "status": status,
- "message": "\n".join(results["ok"] + results["error"])}
-
## Import single profile, file_url does not have to end with curaprofile
@pyqtSlot(QUrl, result="QVariantMap")
def importProfile(self, file_url):
@@ -1098,11 +455,13 @@ class ContainerManager(QObject):
return
return self._container_registry.importProfile(path)
- @pyqtSlot("QVariantList", QUrl, str)
- def exportProfile(self, instance_id: str, file_url: QUrl, file_type: str) -> None:
+ @pyqtSlot(QObject, QUrl, str)
+ def exportQualityChangesGroup(self, quality_changes_group, file_url: QUrl, file_type: str):
if not file_url.isValid():
return
path = file_url.toLocalFile()
if not path:
return
- self._container_registry.exportProfile(instance_id, path, file_type)
+
+ container_list = [n.getContainer() for n in quality_changes_group.getAllNodes()]
+ self._container_registry.exportQualityProfile(container_list, path, file_type)
diff --git a/cura/Settings/ContainerSettingsModel.py b/cura/Settings/ContainerSettingsModel.py
deleted file mode 100644
index 2c4bef6464..0000000000
--- a/cura/Settings/ContainerSettingsModel.py
+++ /dev/null
@@ -1,97 +0,0 @@
-# Copyright (c) 2016 Ultimaker B.V.
-# Cura is released under the terms of the LGPLv3 or higher.
-
-from UM.Application import Application
-from UM.Qt.ListModel import ListModel
-
-from PyQt5.QtCore import pyqtProperty, Qt, pyqtSignal, pyqtSlot, QUrl
-
-from UM.Settings.ContainerRegistry import ContainerRegistry
-from UM.Settings.InstanceContainer import InstanceContainer
-from UM.Settings.SettingFunction import SettingFunction
-
-class ContainerSettingsModel(ListModel):
- LabelRole = Qt.UserRole + 1
- CategoryRole = Qt.UserRole + 2
- UnitRole = Qt.UserRole + 3
- ValuesRole = Qt.UserRole + 4
-
- def __init__(self, parent = None):
- super().__init__(parent)
- self.addRoleName(self.LabelRole, "label")
- self.addRoleName(self.CategoryRole, "category")
- self.addRoleName(self.UnitRole, "unit")
- self.addRoleName(self.ValuesRole, "values")
-
- self._container_ids = []
- self._containers = []
-
- def _onPropertyChanged(self, key, property_name):
- if property_name == "value":
- self._update()
-
- def _update(self):
- items = []
-
- if len(self._container_ids) == 0:
- return
-
- keys = []
- for container in self._containers:
- keys = keys + list(container.getAllKeys())
-
- keys = list(set(keys)) # remove duplicate keys
-
- for key in keys:
- definition = None
- category = None
- values = []
- for container in self._containers:
- instance = container.getInstance(key)
- if instance:
- definition = instance.definition
-
- # Traverse up to find the category
- category = definition
- while category.type != "category":
- category = category.parent
-
- value = container.getProperty(key, "value")
- if type(value) == SettingFunction:
- values.append("=\u0192")
- else:
- values.append(container.getProperty(key, "value"))
- else:
- values.append("")
-
- items.append({
- "key": key,
- "values": values,
- "label": definition.label,
- "unit": definition.unit,
- "category": category.label
- })
- items.sort(key = lambda k: (k["category"], k["key"]))
- self.setItems(items)
-
- ## Set the ids of the containers which have the settings this model should list.
- # Also makes sure the model updates when the containers have property changes
- def setContainers(self, container_ids):
- for container in self._containers:
- container.propertyChanged.disconnect(self._onPropertyChanged)
-
- self._container_ids = container_ids
- self._containers = []
-
- for container_id in self._container_ids:
- containers = ContainerRegistry.getInstance().findContainers(id = container_id)
- if containers:
- containers[0].propertyChanged.connect(self._onPropertyChanged)
- self._containers.append(containers[0])
-
- self._update()
-
- containersChanged = pyqtSignal()
- @pyqtProperty("QVariantList", fset = setContainers, notify = containersChanged)
- def containers(self):
- return self.container_ids
diff --git a/cura/Settings/CuraContainerRegistry.py b/cura/Settings/CuraContainerRegistry.py
index b945ec0609..0cf1c7399f 100644
--- a/cura/Settings/CuraContainerRegistry.py
+++ b/cura/Settings/CuraContainerRegistry.py
@@ -25,14 +25,16 @@ from UM.Resources import Resources
from . import ExtruderStack
from . import GlobalStack
-from .ContainerManager import ContainerManager
from .ExtruderManager import ExtruderManager
from cura.CuraApplication import CuraApplication
+from cura.Machines.QualityManager import getMachineDefinitionIDForQualitySearch
+from cura.ProfileReader import NoProfileException
from UM.i18n import i18nCatalog
catalog = i18nCatalog("cura")
+
class CuraContainerRegistry(ContainerRegistry):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
@@ -102,7 +104,7 @@ 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 exportProfile(self, instance_ids, file_name, file_type):
+ def exportQualityProfile(self, container_list, file_name, file_type):
# 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.
@@ -121,31 +123,10 @@ class CuraContainerRegistry(ContainerRegistry):
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
- found_containers = []
- extruder_positions = []
- for instance_id in instance_ids:
- containers = ContainerRegistry.getInstance().findInstanceContainers(id = instance_id)
- if containers:
- found_containers.append(containers[0])
-
- # Determine the position of the extruder of this container
- extruder_id = containers[0].getMetaDataEntry("extruder", "")
- if extruder_id == "":
- # Global stack
- extruder_positions.append(-1)
- else:
- extruder_containers = ContainerRegistry.getInstance().findDefinitionContainersMetadata(id = extruder_id)
- if extruder_containers:
- extruder_positions.append(int(extruder_containers[0].get("position", 0)))
- else:
- extruder_positions.append(0)
- # Ensure the profiles are always exported in order (global, extruder 0, extruder 1, ...)
- found_containers = [containers for (positions, containers) in sorted(zip(extruder_positions, found_containers))]
profile_writer = self._findProfileWriter(extension, description)
-
try:
- success = profile_writer.write(file_name, found_containers)
+ success = profile_writer.write(file_name, container_list)
except Exception as e:
Logger.log("e", "Failed to export profile to %s: %s", file_name, str(e))
m = Message(catalog.i18nc("@info:status Don't translate the XML tags or !", "Failed to export profile to {0}: {1}", file_name, str(e)),
@@ -205,12 +186,60 @@ class CuraContainerRegistry(ContainerRegistry):
profile_reader = 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:
+ return { "status": "ok", "message": catalog.i18nc("@info:status Don't translate the XML tags or !", "No custom profile to import in file {0}", file_name)}
except Exception as e:
# Note that this will fail quickly. That is, if any profile reader throws an exception, it will stop reading. It will only continue reading if the reader returned None.
Logger.log("e", "Failed to import profile from %s: %s while using profile reader. Got exception %s", file_name,profile_reader.getPluginId(), str(e))
- return { "status": "error", "message": catalog.i18nc("@info:status Don't translate the XML tags or !", "Failed to import profile from {0}: {1}", file_name, str(e))}
+ return { "status": "error", "message": catalog.i18nc("@info:status Don't translate the XML tags or !", "Failed to import profile from {0}: {1}", file_name, "\n" + str(e))}
if profile_or_list:
+ # Ensure it is always a list of profiles
+ if not isinstance(profile_or_list, list):
+ profile_or_list = [profile_or_list]
+
+ # First check if this profile is suitable for this machine
+ global_profile = None
+ if len(profile_or_list) == 1:
+ global_profile = profile_or_list[0]
+ else:
+ for profile in profile_or_list:
+ if not profile.getMetaDataEntry("position"):
+ global_profile = profile
+ break
+ if not global_profile:
+ Logger.log("e", "Incorrect profile [%s]. Could not find global profile", file_name)
+ return { "status": "error",
+ "message": catalog.i18nc("@info:status Don't translate the XML tags or !", "This profile {0} contains incorrect data, could not import it.", file_name)}
+ profile_definition = global_profile.getMetaDataEntry("definition")
+
+ # 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:
+ 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 or !", "This profile {0} contains incorrect data, could not import it.", file_name)
+ }
+ machine_definition = machine_definition[0]
+
+ # Get the expected machine definition.
+ # i.e.: We expect gcode for a UM2 Extended to be defined as normal UM2 gcode...
+ profile_definition = getMachineDefinitionIDForQualitySearch(machine_definition)
+ expected_machine_definition = getMachineDefinitionIDForQualitySearch(global_container_stack.definition)
+
+ # And check if the profile_definition matches either one (showing error if not):
+ if profile_definition != expected_machine_definition:
+ Logger.log("e", "Profile [%s] is for machine [%s] but the current active machine is [%s]. Will not import the profile", file_name, profile_definition, expected_machine_definition)
+ return { "status": "error",
+ "message": catalog.i18nc("@info:status Don't translate the XML tags or !", "The machine defined in profile {0} ({1}) doesn't match with your current machine ({2}), could not import it.", file_name, profile_definition, expected_machine_definition)}
+
+ # Fix the global quality profile's definition field in case it's not correct
+ global_profile.setMetaDataEntry("definition", expected_machine_definition)
+ quality_name = global_profile.getName()
+ quality_type = global_profile.getMetaDataEntry("quality_type")
+
name_seed = os.path.splitext(os.path.basename(file_name))[0]
new_name = self.uniqueName(name_seed)
@@ -218,6 +247,41 @@ class CuraContainerRegistry(ContainerRegistry):
if type(profile_or_list) is not list:
profile_or_list = [profile_or_list]
+ # Make sure that there are also extruder stacks' quality_changes, not just one for the global stack
+ if len(profile_or_list) == 1:
+ global_profile = profile_or_list[0]
+ extruder_profiles = []
+ for idx, extruder in enumerate(global_container_stack.extruders.values()):
+ profile_id = ContainerRegistry.getInstance().uniqueName(global_container_stack.getId() + "_extruder_" + str(idx + 1))
+ profile = InstanceContainer(profile_id)
+ profile.setName(quality_name)
+ profile.addMetaDataEntry("setting_version", CuraApplication.SettingVersion)
+ profile.addMetaDataEntry("type", "quality_changes")
+ profile.addMetaDataEntry("definition", expected_machine_definition)
+ profile.addMetaDataEntry("quality_type", quality_type)
+ profile.addMetaDataEntry("position", "0")
+ profile.setDirty(True)
+ if idx == 0:
+ # move all per-extruder settings to the first extruder's quality_changes
+ for qc_setting_key in global_profile.getAllKeys():
+ settable_per_extruder = global_container_stack.getProperty(qc_setting_key,
+ "settable_per_extruder")
+ if settable_per_extruder:
+ setting_value = global_profile.getProperty(qc_setting_key, "value")
+
+ setting_definition = global_container_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)
+
+ global_profile.removeInstance(qc_setting_key, postpone_emit=True)
+ extruder_profiles.append(profile)
+
+ for profile in extruder_profiles:
+ profile_or_list.append(profile)
+
# Import all profiles
for profile_index, profile in enumerate(profile_or_list):
if profile_index == 0:
@@ -226,17 +290,18 @@ class CuraContainerRegistry(ContainerRegistry):
elif profile_index < len(machine_extruders) + 1:
# This is assumed to be an extruder profile
- extruder_id = Application.getInstance().getMachineManager().getQualityDefinitionId(machine_extruders[profile_index - 1].getBottom())
- if not profile.getMetaDataEntry("extruder"):
- profile.addMetaDataEntry("extruder", extruder_id)
+ extruder_id = machine_extruders[profile_index - 1].definition.getId()
+ extruder_position = str(profile_index - 1)
+ if not profile.getMetaDataEntry("position"):
+ profile.addMetaDataEntry("position", extruder_position)
else:
- profile.setMetaDataEntry("extruder", extruder_id)
+ 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.
- result = self._configureProfile(profile, profile_id, new_name)
+ result = self._configureProfile(profile, profile_id, new_name, expected_machine_definition)
if result is not None:
return {"status": "error", "message": catalog.i18nc(
"@info:status Don't translate the XML tags or !",
@@ -245,6 +310,9 @@ class CuraContainerRegistry(ContainerRegistry):
return {"status": "ok", "message": catalog.i18nc("@info:status", "Successfully imported profile {0}", profile_or_list[0].getName())}
+ # This message is throw when the profile reader doesn't find any profile in the file
+ return {"status": "error", "message": catalog.i18nc("@info:status", "File {0} does not contain any valid profile.", file_name)}
+
# If it hasn't returned by now, none of the plugins loaded the profile successfully.
return {"status": "error", "message": catalog.i18nc("@info:status", "Profile {0} has an unknown file type or is corrupted.", file_name)}
@@ -261,16 +329,17 @@ class CuraContainerRegistry(ContainerRegistry):
# \param new_name The new name for the profile.
#
# \return None if configuring was successful or an error message if an error occurred.
- def _configureProfile(self, profile: InstanceContainer, id_seed: str, new_name: str) -> Optional[str]:
+ def _configureProfile(self, profile: InstanceContainer, id_seed: str, new_name: str, machine_definition_id: str) -> Optional[str]:
profile.setDirty(True) # Ensure the profiles are correctly saved
new_id = self.createUniqueName("quality_changes", "", id_seed, catalog.i18nc("@label", "Custom profile"))
- profile._id = new_id
+ profile.setMetaDataEntry("id", new_id)
profile.setName(new_name)
# Set the unique Id to the profile, so it's generating a new one even if the user imports the same profile
# It also solves an issue with importing profiles from G-Codes
profile.setMetaDataEntry("id", new_id)
+ profile.setMetaDataEntry("definition", machine_definition_id)
if "type" in profile.getMetaData():
profile.setMetaDataEntry("type", "quality_changes")
@@ -281,40 +350,16 @@ class CuraContainerRegistry(ContainerRegistry):
if not quality_type:
return catalog.i18nc("@info:status", "Profile is missing a quality type.")
- quality_type_criteria = {"quality_type": quality_type}
- if self._machineHasOwnQualities():
- profile.setDefinition(self._activeQualityDefinition().getId())
- if self._machineHasOwnMaterials():
- active_material_id = self._activeMaterialId()
- if active_material_id and active_material_id != "empty": # only update if there is an active material
- profile.addMetaDataEntry("material", active_material_id)
- quality_type_criteria["material"] = active_material_id
-
- quality_type_criteria["definition"] = profile.getDefinition().getId()
-
- else:
- profile.setDefinition("fdmprinter")
- quality_type_criteria["definition"] = "fdmprinter"
-
- machine_definition = Application.getInstance().getGlobalContainerStack().getBottom()
- del quality_type_criteria["definition"]
-
- # materials = None
-
- if "material" in quality_type_criteria:
- # materials = ContainerRegistry.getInstance().findInstanceContainers(id = quality_type_criteria["material"])
- del quality_type_criteria["material"]
-
- # Do not filter quality containers here with materials because we are trying to import a profile, so it should
- # NOT be restricted by the active materials on the current machine.
- materials = None
+ global_stack = Application.getInstance().getGlobalContainerStack()
+ definition_id = getMachineDefinitionIDForQualitySearch(global_stack.definition)
+ profile.setDefinition(definition_id)
# Check to make sure the imported profile actually makes sense in context of the current configuration.
# This prevents issues where importing a "draft" profile for a machine without "draft" qualities would report as
# successfully imported but then fail to show up.
- from cura.QualityManager import QualityManager
- qualities = QualityManager.getInstance()._getFilteredContainersForStack(machine_definition, materials, **quality_type_criteria)
- if not qualities:
+ quality_manager = CuraApplication.getInstance()._quality_manager
+ quality_group_dict = quality_manager.getQualityGroupsForMachineDefinition(global_stack)
+ if quality_type not in quality_group_dict:
return catalog.i18nc("@info:status", "Could not find a quality type {0} for the current configuration.", quality_type)
ContainerRegistry.getInstance().addContainer(profile)
@@ -334,18 +379,6 @@ class CuraContainerRegistry(ContainerRegistry):
result.append( (plugin_id, meta_data) )
return result
- ## Get the definition to use to select quality profiles for the active machine
- # \return the active quality definition object or None if there is no quality definition
- def _activeQualityDefinition(self):
- global_container_stack = Application.getInstance().getGlobalContainerStack()
- if global_container_stack:
- definition_id = Application.getInstance().getMachineManager().getQualityDefinitionId(global_container_stack.getBottom())
- definition = self.findDefinitionContainers(id = definition_id)[0]
-
- if definition:
- return definition
- return None
-
## Returns true if the current machine requires its own materials
# \return True if the current machine requires its own materials
def _machineHasOwnMaterials(self):
@@ -418,7 +451,14 @@ class CuraContainerRegistry(ContainerRegistry):
if not extruder_stacks:
self.addExtruderStackForSingleExtrusionMachine(container, "fdmextruder")
- def addExtruderStackForSingleExtrusionMachine(self, machine, extruder_id):
+ #
+ # new_global_quality_changes is optional. It is only used in project loading for a scenario like this:
+ # - override the current machine
+ # - create new for custom quality profile
+ # new_global_quality_changes is the new global quality changes container in this scenario.
+ # create_new_ids indicates if new unique ids must be created
+ #
+ def addExtruderStackForSingleExtrusionMachine(self, machine, extruder_id, new_global_quality_changes = None, create_new_ids = True):
new_extruder_id = extruder_id
extruder_definitions = self.findDefinitionContainers(id = new_extruder_id)
@@ -427,17 +467,15 @@ class CuraContainerRegistry(ContainerRegistry):
return
extruder_definition = extruder_definitions[0]
- unique_name = self.uniqueName(machine.getName() + " " + new_extruder_id)
+ unique_name = self.uniqueName(machine.getName() + " " + new_extruder_id) if create_new_ids else machine.getName() + " " + new_extruder_id
extruder_stack = ExtruderStack.ExtruderStack(unique_name)
extruder_stack.setName(extruder_definition.getName())
extruder_stack.setDefinition(extruder_definition)
extruder_stack.addMetaDataEntry("position", extruder_definition.getMetaDataEntry("position"))
- from cura.CuraApplication import CuraApplication
-
# create a new definition_changes container for the extruder stack
- definition_changes_id = self.uniqueName(extruder_stack.getId() + "_settings")
+ definition_changes_id = self.uniqueName(extruder_stack.getId() + "_settings") if create_new_ids else extruder_stack.getId() + "_settings"
definition_changes_name = definition_changes_id
definition_changes = InstanceContainer(definition_changes_id)
definition_changes.setName(definition_changes_name)
@@ -464,14 +502,15 @@ class CuraContainerRegistry(ContainerRegistry):
extruder_stack.setDefinitionChanges(definition_changes)
# create empty user changes container otherwise
- user_container_id = self.uniqueName(extruder_stack.getId() + "_user")
+ user_container_id = self.uniqueName(extruder_stack.getId() + "_user") if create_new_ids else extruder_stack.getId() + "_user"
user_container_name = user_container_id
user_container = InstanceContainer(user_container_id)
user_container.setName(user_container_name)
user_container.addMetaDataEntry("type", "user")
- user_container.addMetaDataEntry("machine", extruder_stack.getId())
+ user_container.addMetaDataEntry("machine", machine.getId())
user_container.addMetaDataEntry("setting_version", CuraApplication.SettingVersion)
user_container.setDefinition(machine.definition.getId())
+ user_container.setMetaDataEntry("extruder", extruder_stack.getId())
if machine.userChanges:
# for the newly created extruder stack, we need to move all "per-extruder" settings to the user changes
@@ -493,63 +532,73 @@ class CuraContainerRegistry(ContainerRegistry):
self.addContainer(user_container)
extruder_stack.setUserChanges(user_container)
- variant_id = "default"
+ application = CuraApplication.getInstance()
+ empty_variant = application.empty_variant_container
+ empty_material = application.empty_material_container
+ empty_quality = application.empty_quality_container
+
if machine.variant.getId() not in ("empty", "empty_variant"):
- variant_id = machine.variant.getId()
+ variant = machine.variant
else:
- variant_id = "empty_variant"
- extruder_stack.setVariantById(variant_id)
+ variant = empty_variant
+ extruder_stack.variant = variant
- material_id = "default"
if machine.material.getId() not in ("empty", "empty_material"):
- material_id = machine.material.getId()
+ material = machine.material
else:
- material_id = "empty_material"
- extruder_stack.setMaterialById(material_id)
+ material = empty_material
+ extruder_stack.material = material
- quality_id = "default"
if machine.quality.getId() not in ("empty", "empty_quality"):
- quality_id = machine.quality.getId()
+ quality = machine.quality
else:
- quality_id = "empty_quality"
- extruder_stack.setQualityById(quality_id)
+ quality = empty_quality
+ extruder_stack.quality = quality
- if machine.qualityChanges.getId() not in ("empty", "empty_quality_changes"):
- extruder_quality_changes_container = self.findInstanceContainers(name = machine.qualityChanges.getName(), extruder = extruder_id)
+ machine_quality_changes = machine.qualityChanges
+ if new_global_quality_changes is not None:
+ machine_quality_changes = new_global_quality_changes
+
+ if machine_quality_changes.getId() not in ("empty", "empty_quality_changes"):
+ extruder_quality_changes_container = self.findInstanceContainers(name = machine_quality_changes.getName(), extruder = extruder_id)
if extruder_quality_changes_container:
extruder_quality_changes_container = extruder_quality_changes_container[0]
quality_changes_id = extruder_quality_changes_container.getId()
- extruder_stack.setQualityChangesById(quality_changes_id)
+ extruder_stack.qualityChanges = self.findInstanceContainers(id = quality_changes_id)[0]
else:
# Some extruder quality_changes containers can be created at runtime as files in the qualities
# folder. Those files won't be loaded in the registry immediately. So we also need to search
# the folder to see if the quality_changes exists.
- extruder_quality_changes_container = self._findQualityChangesContainerInCuraFolder(machine.qualityChanges.getName())
+ extruder_quality_changes_container = self._findQualityChangesContainerInCuraFolder(machine_quality_changes.getName())
if extruder_quality_changes_container:
quality_changes_id = extruder_quality_changes_container.getId()
- extruder_stack.setQualityChangesById(quality_changes_id)
+ extruder_quality_changes_container.addMetaDataEntry("extruder", extruder_stack.definition.getId())
+ 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
- container_id = self.uniqueName(extruder_stack.getId() + "_user")
- container_name = machine.qualityChanges.getName()
+ container_name = machine_quality_changes.getName()
+ container_id = self.uniqueName(extruder_stack.getId() + "_qc_" + container_name)
extruder_quality_changes_container = InstanceContainer(container_id)
extruder_quality_changes_container.setName(container_name)
extruder_quality_changes_container.addMetaDataEntry("type", "quality_changes")
extruder_quality_changes_container.addMetaDataEntry("setting_version", CuraApplication.SettingVersion)
extruder_quality_changes_container.addMetaDataEntry("extruder", extruder_stack.definition.getId())
- extruder_quality_changes_container.addMetaDataEntry("quality_type", machine.qualityChanges.getMetaDataEntry("quality_type"))
- extruder_quality_changes_container.setDefinition(machine.qualityChanges.getDefinition().getId())
+ extruder_quality_changes_container.addMetaDataEntry("quality_type", machine_quality_changes.getMetaDataEntry("quality_type"))
+ extruder_quality_changes_container.setDefinition(machine_quality_changes.getDefinition().getId())
+
+ self.addContainer(extruder_quality_changes_container)
+ extruder_stack.qualityChanges = extruder_quality_changes_container
if not extruder_quality_changes_container:
Logger.log("w", "Could not find quality_changes named [%s] for extruder [%s]",
- machine.qualityChanges.getName(), extruder_stack.getId())
+ machine_quality_changes.getName(), extruder_stack.getId())
else:
# move all per-extruder settings to the extruder's quality changes
- for qc_setting_key in machine.qualityChanges.getAllKeys():
+ for qc_setting_key in machine_quality_changes.getAllKeys():
settable_per_extruder = machine.getProperty(qc_setting_key, "settable_per_extruder")
if settable_per_extruder:
- setting_value = machine.qualityChanges.getProperty(qc_setting_key, "value")
+ setting_value = machine_quality_changes.getProperty(qc_setting_key, "value")
setting_definition = machine.getSettingDefinition(qc_setting_key)
new_instance = SettingInstance(setting_definition, definition_changes)
@@ -558,16 +607,16 @@ class CuraContainerRegistry(ContainerRegistry):
extruder_quality_changes_container.addInstance(new_instance)
extruder_quality_changes_container.setDirty(True)
- machine.qualityChanges.removeInstance(qc_setting_key, postpone_emit=True)
+ machine_quality_changes.removeInstance(qc_setting_key, postpone_emit=True)
else:
- extruder_stack.setQualityChangesById("empty_quality_changes")
+ extruder_stack.qualityChanges = self.findInstanceContainers(id = "empty_quality_changes")[0]
self.addContainer(extruder_stack)
# Also need to fix the other qualities that are suitable for this machine. Those quality changes may still have
# per-extruder settings in the container for the machine instead of the extruder.
- if machine.qualityChanges.getId() not in ("empty", "empty_quality_changes"):
- quality_changes_machine_definition_id = machine.qualityChanges.getDefinition().getId()
+ if machine_quality_changes.getId() not in ("empty", "empty_quality_changes"):
+ quality_changes_machine_definition_id = machine_quality_changes.getDefinition().getId()
else:
whole_machine_definition = machine.definition
machine_entry = machine.definition.getMetaDataEntry("machine")
@@ -587,7 +636,7 @@ class CuraContainerRegistry(ContainerRegistry):
qc_groups[qc_name] = []
qc_groups[qc_name].append(qc)
# try to find from the quality changes cura directory too
- quality_changes_container = self._findQualityChangesContainerInCuraFolder(machine.qualityChanges.getName())
+ quality_changes_container = self._findQualityChangesContainerInCuraFolder(machine_quality_changes.getName())
if quality_changes_container:
qc_groups[qc_name].append(quality_changes_container)
@@ -630,7 +679,7 @@ class CuraContainerRegistry(ContainerRegistry):
if not os.path.isfile(file_path):
continue
- parser = configparser.ConfigParser()
+ parser = configparser.ConfigParser(interpolation=None)
try:
parser.read([file_path])
except:
@@ -648,7 +697,7 @@ class CuraContainerRegistry(ContainerRegistry):
continue
instance_container = InstanceContainer(container_id)
- with open(file_path, "r") as f:
+ with open(file_path, "r", encoding = "utf-8") as f:
serialized = f.read()
instance_container.deserialize(serialized, file_path)
self.addContainer(instance_container)
diff --git a/cura/Settings/CuraContainerStack.py b/cura/Settings/CuraContainerStack.py
index b97bb3314e..00db4f57c7 100755
--- a/cura/Settings/CuraContainerStack.py
+++ b/cura/Settings/CuraContainerStack.py
@@ -83,20 +83,6 @@ class CuraContainerStack(ContainerStack):
def setQualityChanges(self, new_quality_changes: InstanceContainer, postpone_emit = False) -> None:
self.replaceContainer(_ContainerIndexes.QualityChanges, new_quality_changes, postpone_emit = postpone_emit)
- ## Set the quality changes container by an ID.
- #
- # This will search for the specified container and set it. If no container was found, an error will be raised.
- #
- # \param new_quality_changes_id The ID of the new quality changes container.
- #
- # \throws Exceptions.InvalidContainerError Raised when no container could be found with the specified ID.
- def setQualityChangesById(self, new_quality_changes_id: str) -> None:
- quality_changes = ContainerRegistry.getInstance().findInstanceContainers(id = new_quality_changes_id)
- if quality_changes:
- self.setQualityChanges(quality_changes[0])
- else:
- raise Exceptions.InvalidContainerError("Could not find container with id {id}".format(id = new_quality_changes_id))
-
## Get the quality changes container.
#
# \return The quality changes container. Should always be a valid container, but can be equal to the empty InstanceContainer.
@@ -110,31 +96,6 @@ class CuraContainerStack(ContainerStack):
def setQuality(self, new_quality: InstanceContainer, postpone_emit = False) -> None:
self.replaceContainer(_ContainerIndexes.Quality, new_quality, postpone_emit = postpone_emit)
- ## Set the quality container by an ID.
- #
- # This will search for the specified container and set it. If no container was found, an error will be raised.
- # There is a special value for ID, which is "default". The "default" value indicates the quality should be set
- # to whatever the machine definition specifies as "preferred" container, or a fallback value. See findDefaultQuality
- # for details.
- #
- # \param new_quality_id The ID of the new quality container.
- #
- # \throws Exceptions.InvalidContainerError Raised when no container could be found with the specified ID.
- def setQualityById(self, new_quality_id: str) -> None:
- quality = self._empty_quality
- if new_quality_id == "default":
- new_quality = self.findDefaultQuality()
- if new_quality:
- quality = new_quality
- else:
- qualities = ContainerRegistry.getInstance().findInstanceContainers(id = new_quality_id)
- if qualities:
- quality = qualities[0]
- else:
- raise Exceptions.InvalidContainerError("Could not find container with id {id}".format(id = new_quality_id))
-
- self.setQuality(quality)
-
## Get the quality container.
#
# \return The quality container. Should always be a valid container, but can be equal to the empty InstanceContainer.
@@ -148,31 +109,6 @@ class CuraContainerStack(ContainerStack):
def setMaterial(self, new_material: InstanceContainer, postpone_emit = False) -> None:
self.replaceContainer(_ContainerIndexes.Material, new_material, postpone_emit = postpone_emit)
- ## Set the material container by an ID.
- #
- # This will search for the specified container and set it. If no container was found, an error will be raised.
- # There is a special value for ID, which is "default". The "default" value indicates the quality should be set
- # to whatever the machine definition specifies as "preferred" container, or a fallback value. See findDefaultMaterial
- # for details.
- #
- # \param new_material_id The ID of the new material container.
- #
- # \throws Exceptions.InvalidContainerError Raised when no container could be found with the specified ID.
- def setMaterialById(self, new_material_id: str) -> None:
- material = self._empty_material
- if new_material_id == "default":
- new_material = self.findDefaultMaterial()
- if new_material:
- material = new_material
- else:
- materials = ContainerRegistry.getInstance().findInstanceContainers(id = new_material_id)
- if materials:
- material = materials[0]
- else:
- raise Exceptions.InvalidContainerError("Could not find container with id {id}".format(id = new_material_id))
-
- self.setMaterial(material)
-
## Get the material container.
#
# \return The material container. Should always be a valid container, but can be equal to the empty InstanceContainer.
@@ -186,31 +122,6 @@ class CuraContainerStack(ContainerStack):
def setVariant(self, new_variant: InstanceContainer) -> None:
self.replaceContainer(_ContainerIndexes.Variant, new_variant)
- ## Set the variant container by an ID.
- #
- # This will search for the specified container and set it. If no container was found, an error will be raised.
- # There is a special value for ID, which is "default". The "default" value indicates the quality should be set
- # to whatever the machine definition specifies as "preferred" container, or a fallback value. See findDefaultVariant
- # for details.
- #
- # \param new_variant_id The ID of the new variant container.
- #
- # \throws Exceptions.InvalidContainerError Raised when no container could be found with the specified ID.
- def setVariantById(self, new_variant_id: str) -> None:
- variant = self._empty_variant
- if new_variant_id == "default":
- new_variant = self.findDefaultVariantBuildplate() if self.getMetaDataEntry("type") == "machine" else self.findDefaultVariant()
- if new_variant:
- variant = new_variant
- else:
- variants = ContainerRegistry.getInstance().findInstanceContainers(id = new_variant_id)
- if variants:
- variant = variants[0]
- else:
- raise Exceptions.InvalidContainerError("Could not find container with id {id}".format(id = new_variant_id))
-
- self.setVariant(variant)
-
## Get the variant container.
#
# \return The variant container. Should always be a valid container, but can be equal to the empty InstanceContainer.
@@ -224,18 +135,6 @@ class CuraContainerStack(ContainerStack):
def setDefinitionChanges(self, new_definition_changes: InstanceContainer) -> None:
self.replaceContainer(_ContainerIndexes.DefinitionChanges, new_definition_changes)
- ## Set the definition changes container by an ID.
- #
- # \param new_definition_changes_id The ID of the new definition changes container.
- #
- # \throws Exceptions.InvalidContainerError Raised when no container could be found with the specified ID.
- def setDefinitionChangesById(self, new_definition_changes_id: str) -> None:
- new_definition_changes = ContainerRegistry.getInstance().findInstanceContainers(id = new_definition_changes_id)
- if new_definition_changes:
- self.setDefinitionChanges(new_definition_changes[0])
- else:
- raise Exceptions.InvalidContainerError("Could not find container with id {id}".format(id = new_definition_changes_id))
-
## Get the definition changes container.
#
# \return The definition changes container. Should always be a valid container, but can be equal to the empty InstanceContainer.
@@ -249,18 +148,6 @@ class CuraContainerStack(ContainerStack):
def setDefinition(self, new_definition: DefinitionContainerInterface) -> None:
self.replaceContainer(_ContainerIndexes.Definition, new_definition)
- ## Set the definition container by an ID.
- #
- # \param new_definition_id The ID of the new definition container.
- #
- # \throws Exceptions.InvalidContainerError Raised when no container could be found with the specified ID.
- def setDefinitionById(self, new_definition_id: str) -> None:
- new_definition = ContainerRegistry.getInstance().findDefinitionContainers(id = new_definition_id)
- if new_definition:
- self.setDefinition(new_definition[0])
- else:
- raise Exceptions.InvalidContainerError("Could not find container with id {id}".format(id = new_definition_id))
-
## Get the definition container.
#
# \return The definition container. Should always be a valid container, but can be equal to the empty InstanceContainer.
@@ -348,6 +235,10 @@ class CuraContainerStack(ContainerStack):
elif container != self._empty_instance_container and container.getMetaDataEntry("type") != expected_type:
raise Exceptions.InvalidContainerError("Cannot replace container at index {index} with a container that is not of {type} type, but {actual_type} type.".format(index = index, type = expected_type, actual_type = container.getMetaDataEntry("type")))
+ current_container = self._containers[index]
+ if current_container.getId() == container.getId():
+ return
+
super().replaceContainer(index, container, postpone_emit)
## Overridden from ContainerStack
@@ -391,243 +282,6 @@ class CuraContainerStack(ContainerStack):
self._containers = new_containers
- ## Find the variant that should be used as "default" variant.
- #
- # This will search for variants that match the current definition and pick the preferred one,
- # if specified by the machine definition.
- #
- # The following criteria are used to find the default variant:
- # - If the machine definition does not have a metadata entry "has_variants" set to True, return None
- # - The definition of the variant should be the same as the machine definition for this stack.
- # - The container should have a metadata entry "type" with value "variant".
- # - If the machine definition has a metadata entry "preferred_variant", filter the variant IDs based on that.
- #
- # \return The container that should be used as default, or None if nothing was found or the machine does not use variants.
- #
- # \note This method assumes the stack has a valid machine definition.
- def findDefaultVariant(self) -> Optional[ContainerInterface]:
- definition = self._getMachineDefinition()
- # has_variants can be overridden in other containers and stacks.
- # In the case of UM2, it is overridden in the GlobalStack
- if not self.getMetaDataEntry("has_variants"):
- # If the machine does not use variants, we should never set a variant.
- return None
-
- # First add any variant. Later, overwrite with preference if the preference is valid.
- variant = None
- definition_id = self._findInstanceContainerDefinitionId(definition)
- variants = ContainerRegistry.getInstance().findInstanceContainers(definition = definition_id, type = "variant")
- if variants:
- variant = variants[0]
-
- preferred_variant_id = definition.getMetaDataEntry("preferred_variant")
- if preferred_variant_id:
- preferred_variants = ContainerRegistry.getInstance().findInstanceContainers(id = preferred_variant_id, definition = definition_id, type = "variant")
- if preferred_variants:
- variant = preferred_variants[0]
- else:
- Logger.log("w", "The preferred variant \"{variant}\" of stack {stack} does not exist or is not a variant.", variant = preferred_variant_id, stack = self.id)
- # And leave it at the default variant.
-
- if variant:
- return variant
-
- Logger.log("w", "Could not find a valid default variant for stack {stack}", stack = self.id)
- return None
-
- ## Find the global variant that should be used as "default". This is used for the buildplates.
- #
- # This will search for variants that match the current definition and pick the preferred one,
- # if specified by the machine definition.
- #
- # The following criteria are used to find the default global variant:
- # - If the machine definition does not have a metadata entry "has_variant_buildplates" set to True, return None
- # - The definition of the variant should be the same as the machine definition for this stack.
- # - The container should have a metadata entry "type" with value "variant" and "hardware_type" with value "buildplate".
- # - If the machine definition has a metadata entry "preferred_variant_buildplate", filter the variant IDs based on that.
- #
- # \return The container that should be used as default, or None if nothing was found or the machine does not use variants.
- #
- # \note This method assumes the stack has a valid machine definition.
- def findDefaultVariantBuildplate(self) -> Optional[ContainerInterface]:
- definition = self._getMachineDefinition()
- # has_variant_buildplates can be overridden in other containers and stacks.
- # In the case of UM2, it is overridden in the GlobalStack
- if not self.getMetaDataEntry("has_variant_buildplates"):
- # If the machine does not use variants, we should never set a variant.
- return None
-
- # First add any variant. Later, overwrite with preference if the preference is valid.
- variant = None
- definition_id = self._findInstanceContainerDefinitionId(definition)
- variants = ContainerRegistry.getInstance().findInstanceContainers(definition = definition_id, type = "variant", hardware_type = "buildplate")
- if variants:
- variant = variants[0]
-
- preferred_variant_buildplate_id = definition.getMetaDataEntry("preferred_variant_buildplate")
- if preferred_variant_buildplate_id:
- preferred_variant_buildplates = ContainerRegistry.getInstance().findInstanceContainers(id = preferred_variant_buildplate_id, definition = definition_id, type = "variant")
- if preferred_variant_buildplates:
- variant = preferred_variant_buildplates[0]
- else:
- Logger.log("w", "The preferred variant buildplate \"{variant}\" of stack {stack} does not exist or is not a variant.",
- variant = preferred_variant_buildplate_id, stack = self.id)
- # And leave it at the default variant.
-
- if variant:
- return variant
-
- Logger.log("w", "Could not find a valid default buildplate variant for stack {stack}", stack = self.id)
- return None
-
- ## Find the material that should be used as "default" material.
- #
- # This will search for materials that match the current definition and pick the preferred one,
- # if specified by the machine definition.
- #
- # The following criteria are used to find the default material:
- # - If the machine definition does not have a metadata entry "has_materials" set to True, return None
- # - If the machine definition has a metadata entry "has_machine_materials", the definition of the material should
- # be the same as the machine definition for this stack. Otherwise, the definition should be "fdmprinter".
- # - The container should have a metadata entry "type" with value "material".
- # - The material should have an approximate diameter that matches the machine
- # - If the machine definition has a metadata entry "has_variants" and set to True, the "variant" metadata entry of
- # the material should be the same as the ID of the variant in the stack. Only applies if "has_machine_materials" is also True.
- # - If the stack currently has a material set, try to find a material that matches the current material by name.
- # - Otherwise, if the machine definition has a metadata entry "preferred_material", try to find a material that matches the specified ID.
- #
- # \return The container that should be used as default, or None if nothing was found or the machine does not use materials.
- def findDefaultMaterial(self) -> Optional[ContainerInterface]:
- definition = self._getMachineDefinition()
- if not definition.getMetaDataEntry("has_materials"):
- # Machine does not use materials, never try to set it.
- return None
-
- search_criteria = {"type": "material"}
- if definition.getMetaDataEntry("has_machine_materials"):
- search_criteria["definition"] = self._findInstanceContainerDefinitionId(definition)
-
- if definition.getMetaDataEntry("has_variants"):
- search_criteria["variant"] = self.variant.id
- else:
- search_criteria["definition"] = "fdmprinter"
-
- if self.material != self._empty_material:
- search_criteria["name"] = self.material.name
- else:
- preferred_material = definition.getMetaDataEntry("preferred_material")
- if preferred_material:
- search_criteria["id"] = preferred_material
-
- approximate_material_diameter = str(round(self.getProperty("material_diameter", "value")))
- search_criteria["approximate_diameter"] = approximate_material_diameter
-
- materials = ContainerRegistry.getInstance().findInstanceContainers(**search_criteria)
- if not materials:
- Logger.log("w", "The preferred material \"{material}\" could not be found for stack {stack}", material = preferred_material, stack = self.id)
- # We failed to find any materials matching the specified criteria, drop some specific criteria and try to find
- # a material that sort-of matches what we want.
- search_criteria.pop("variant", None)
- search_criteria.pop("id", None)
- search_criteria.pop("name", None)
- materials = ContainerRegistry.getInstance().findInstanceContainers(**search_criteria)
-
- if not materials:
- Logger.log("w", "Could not find a valid material for stack {stack}", stack = self.id)
- return None
-
- for material in materials:
- # Prefer a read-only material
- if ContainerRegistry.getInstance().isReadOnly(material.getId()):
- return material
-
- return materials[0]
-
-
- ## Find the quality that should be used as "default" quality.
- #
- # This will search for qualities that match the current definition and pick the preferred one,
- # if specified by the machine definition.
- #
- # \return The container that should be used as default, or None if nothing was found.
- def findDefaultQuality(self) -> Optional[ContainerInterface]:
- definition = self._getMachineDefinition()
- registry = ContainerRegistry.getInstance()
- material_container = self.material if self.material.getId() not in (self._empty_material.getId(), self._empty_instance_container.getId()) else None
-
- search_criteria = {"type": "quality"}
-
- if definition.getMetaDataEntry("has_machine_quality"):
- search_criteria["definition"] = self._findInstanceContainerDefinitionId(definition)
-
- if definition.getMetaDataEntry("has_materials") and material_container:
- search_criteria["material"] = material_container.id
- else:
- search_criteria["definition"] = "fdmprinter"
-
- if self.quality != self._empty_quality:
- search_criteria["name"] = self.quality.name
- else:
- preferred_quality = definition.getMetaDataEntry("preferred_quality")
- if preferred_quality:
- search_criteria["id"] = preferred_quality
-
- containers = registry.findInstanceContainers(**search_criteria)
- if containers:
- return containers[0]
-
- if "material" in search_criteria:
- # First check if we can solve our material not found problem by checking if we can find quality containers
- # that are assigned to the parents of this material profile.
- try:
- inherited_files = material_container.getInheritedFiles()
- except AttributeError: # Material_container does not support inheritance.
- inherited_files = []
-
- if inherited_files:
- for inherited_file in inherited_files:
- # Extract the ID from the path we used to load the file.
- search_criteria["material"] = os.path.basename(inherited_file).split(".")[0]
- containers = registry.findInstanceContainers(**search_criteria)
- if containers:
- return containers[0]
-
- # We still weren't able to find a quality for this specific material.
- # Try to find qualities for a generic version of the material.
- material_search_criteria = {"type": "material", "material": material_container.getMetaDataEntry("material"), "color_name": "Generic"}
- if definition.getMetaDataEntry("has_machine_quality"):
- if self.material != self._empty_instance_container:
- material_search_criteria["definition"] = material_container.getMetaDataEntry("definition")
-
- if definition.getMetaDataEntry("has_variants"):
- material_search_criteria["variant"] = material_container.getMetaDataEntry("variant")
- else:
- material_search_criteria["definition"] = self._findInstanceContainerDefinitionId(definition)
-
- if definition.getMetaDataEntry("has_variants") and self.variant != self._empty_instance_container:
- material_search_criteria["variant"] = self.variant.id
- else:
- material_search_criteria["definition"] = "fdmprinter"
- material_containers = registry.findInstanceContainersMetadata(**material_search_criteria)
- # Try all materials to see if there is a quality profile available.
- for material_container in material_containers:
- search_criteria["material"] = material_container["id"]
-
- containers = registry.findInstanceContainers(**search_criteria)
- if containers:
- return containers[0]
-
- if "name" in search_criteria or "id" in search_criteria:
- # If a quality by this name can not be found, try a wider set of search criteria
- search_criteria.pop("name", None)
- search_criteria.pop("id", None)
-
- containers = registry.findInstanceContainers(**search_criteria)
- if containers:
- return containers[0]
-
- return None
-
## protected:
# Helper to make sure we emit a PyQt signal on container changes.
diff --git a/cura/Settings/CuraStackBuilder.py b/cura/Settings/CuraStackBuilder.py
index 8d2d66ea87..a8234b9de9 100644
--- a/cura/Settings/CuraStackBuilder.py
+++ b/cura/Settings/CuraStackBuilder.py
@@ -1,15 +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.Logger import Logger
+from typing import Optional
+from UM.Logger import Logger
from UM.Settings.Interfaces import DefinitionContainerInterface
from UM.Settings.InstanceContainer import InstanceContainer
from UM.Settings.ContainerRegistry import ContainerRegistry
+from UM.Settings.SettingFunction import SettingFunction
+from UM.Util import parseBool
+from cura.Machines.VariantManager import VariantType
from .GlobalStack import GlobalStack
from .ExtruderStack import ExtruderStack
-from typing import Optional
## Contains helper functions to create new machines.
@@ -22,7 +25,13 @@ class CuraStackBuilder:
# \return The new global stack or None if an error occurred.
@classmethod
def createMachine(cls, name: str, definition_id: str) -> Optional[GlobalStack]:
+ from cura.CuraApplication import CuraApplication
+ application = CuraApplication.getInstance()
+ variant_manager = application.getVariantManager()
+ material_manager = application.getMaterialManager()
+ quality_manager = application.getQualityManager()
registry = ContainerRegistry.getInstance()
+
definitions = registry.findDefinitionContainers(id = definition_id)
if not definitions:
Logger.log("w", "Definition {definition} was not found!", definition = definition_id)
@@ -30,7 +39,21 @@ class CuraStackBuilder:
machine_definition = definitions[0]
- generated_name = registry.createUniqueName("machine", "", name, machine_definition.name)
+ # get variant container for the global stack
+ global_variant_container = application.empty_variant_container
+ global_variant_node = variant_manager.getDefaultVariantNode(machine_definition, VariantType.BUILD_PLATE)
+ if global_variant_node:
+ global_variant_container = global_variant_node.getContainer()
+
+ # get variant container for extruders
+ extruder_variant_container = application.empty_variant_container
+ extruder_variant_node = variant_manager.getDefaultVariantNode(machine_definition, VariantType.NOZZLE)
+ extruder_variant_name = None
+ if extruder_variant_node:
+ extruder_variant_container = extruder_variant_node.getContainer()
+ extruder_variant_name = extruder_variant_container.getName()
+
+ generated_name = registry.createUniqueName("machine", "", name, machine_definition.getName())
# Make sure the new name does not collide with any definition or (quality) profile
# createUniqueName() only looks at other stacks, but not at definitions or quality profiles
# Note that we don't go for uniqueName() immediately because that function matches with ignore_case set to true
@@ -40,47 +63,59 @@ class CuraStackBuilder:
new_global_stack = cls.createGlobalStack(
new_stack_id = generated_name,
definition = machine_definition,
- quality = "default",
- material = "default",
- variant = "default",
+ variant_container = global_variant_container,
+ material_container = application.empty_material_container,
+ quality_container = application.empty_quality_container,
)
-
new_global_stack.setName(generated_name)
- extruder_definition = registry.findDefinitionContainers(machine = machine_definition.getId())
+ # get material container for extruders
+ material_container = application.empty_material_container
+ material_node = material_manager.getDefaultMaterial(new_global_stack, extruder_variant_name)
+ if material_node:
+ material_container = material_node.getContainer()
- if not extruder_definition:
- # create extruder stack for single extrusion machines that have no separate extruder definition files
- extruder_definition = registry.findDefinitionContainers(id = "fdmextruder")[0]
- new_extruder_id = registry.uniqueName(machine_definition.getName() + " " + extruder_definition.id)
+ # Create ExtruderStacks
+ extruder_dict = machine_definition.getMetaDataEntry("machine_extruder_trains")
+
+ for position, extruder_definition_id in extruder_dict.items():
+ # Sanity check: make sure that the positions in the extruder definitions are same as in the machine
+ # definition
+ extruder_definition = registry.findDefinitionContainers(id = extruder_definition_id)[0]
+ position_in_extruder_def = extruder_definition.getMetaDataEntry("position")
+ if position_in_extruder_def != position:
+ raise RuntimeError("Extruder position [%s] defined in extruder definition [%s] is not the same as in machine definition [%s] position [%s]" %
+ (position_in_extruder_def, extruder_definition_id, definition_id, position))
+
+ new_extruder_id = registry.uniqueName(extruder_definition_id)
new_extruder = cls.createExtruderStack(
new_extruder_id,
- definition = extruder_definition,
- machine_definition_id = machine_definition.getId(),
- quality = "default",
- material = "default",
- variant = "default",
- next_stack = new_global_stack
+ extruder_definition = extruder_definition,
+ machine_definition_id = definition_id,
+ position = position,
+ variant_container = extruder_variant_container,
+ material_container = material_container,
+ quality_container = application.empty_quality_container,
+ global_stack = new_global_stack,
)
+ new_extruder.setNextStack(new_global_stack)
new_global_stack.addExtruder(new_extruder)
- else:
- # create extruder stack for each found extruder definition
- for extruder_definition in registry.findDefinitionContainers(machine = machine_definition.id):
- position = extruder_definition.getMetaDataEntry("position", None)
- if not position:
- Logger.log("w", "Extruder definition %s specifies no position metadata entry.", extruder_definition.id)
+ registry.addContainer(new_extruder)
- new_extruder_id = registry.uniqueName(extruder_definition.id)
- new_extruder = cls.createExtruderStack(
- new_extruder_id,
- definition = extruder_definition,
- machine_definition_id = machine_definition.getId(),
- quality = "default",
- material = "default",
- variant = "default",
- next_stack = new_global_stack
- )
- new_global_stack.addExtruder(new_extruder)
+ preferred_quality_type = machine_definition.getMetaDataEntry("preferred_quality_type")
+ quality_group_dict = quality_manager.getQualityGroups(new_global_stack)
+ quality_group = quality_group_dict.get(preferred_quality_type)
+
+ new_global_stack.quality = quality_group.node_for_global.getContainer()
+ for position, extruder_stack in new_global_stack.extruders.items():
+ if position in quality_group.nodes_for_extruders:
+ extruder_stack.quality = quality_group.nodes_for_extruders[position].getContainer()
+ else:
+ extruder_stack.quality = application.empty_quality_container
+
+ # Register the global stack after the extruder stacks are created. This prevents the registry from adding another
+ # extruder stack because the global stack didn't have one yet (which is enforced since Cura 3.1).
+ registry.addContainer(new_global_stack)
return new_global_stack
@@ -94,50 +129,32 @@ class CuraStackBuilder:
#
# \return A new Global stack instance with the specified parameters.
@classmethod
- def createExtruderStack(cls, new_stack_id: str, definition: DefinitionContainerInterface, machine_definition_id: str, **kwargs) -> ExtruderStack:
- stack = ExtruderStack(new_stack_id)
- stack.setName(definition.getName())
- stack.setDefinition(definition)
- stack.addMetaDataEntry("position", definition.getMetaDataEntry("position"))
-
- if "next_stack" in kwargs:
- # Add stacks before containers are added, since they may trigger a setting update.
- stack.setNextStack(kwargs["next_stack"])
-
- user_container = InstanceContainer(new_stack_id + "_user")
- user_container.addMetaDataEntry("type", "user")
- user_container.addMetaDataEntry("extruder", new_stack_id)
+ def createExtruderStack(cls, new_stack_id: str, extruder_definition: DefinitionContainerInterface, machine_definition_id: str,
+ position: int,
+ variant_container, material_container, quality_container, global_stack) -> ExtruderStack:
from cura.CuraApplication import CuraApplication
- user_container.addMetaDataEntry("setting_version", CuraApplication.SettingVersion)
- user_container.setDefinition(machine_definition_id)
+ application = CuraApplication.getInstance()
- stack.setUserChanges(user_container)
+ stack = ExtruderStack(new_stack_id, parent = global_stack)
+ stack.setName(extruder_definition.getName())
+ stack.setDefinition(extruder_definition)
- # Important! The order here matters, because that allows the stack to
- # assume the material and variant have already been set.
- if "definition_changes" in kwargs:
- stack.setDefinitionChangesById(kwargs["definition_changes"])
- else:
- stack.setDefinitionChanges(cls.createDefinitionChangesContainer(stack, new_stack_id + "_settings"))
+ stack.addMetaDataEntry("position", position)
- if "variant" in kwargs:
- stack.setVariantById(kwargs["variant"])
+ user_container = cls.createUserChangesContainer(new_stack_id + "_user", machine_definition_id, new_stack_id,
+ is_global_stack = False)
- if "material" in kwargs:
- stack.setMaterialById(kwargs["material"])
-
- if "quality" in kwargs:
- stack.setQualityById(kwargs["quality"])
-
- if "quality_changes" in kwargs:
- stack.setQualityChangesById(kwargs["quality_changes"])
+ stack.definitionChanges = cls.createDefinitionChangesContainer(stack, new_stack_id + "_settings")
+ stack.variant = variant_container
+ stack.material = material_container
+ stack.quality = quality_container
+ stack.qualityChanges = application.empty_quality_changes_container
+ stack.userChanges = user_container
# Only add the created containers to the registry after we have set all the other
# properties. This makes the create operation more transactional, since any problems
# setting properties will not result in incomplete containers being added.
- registry = ContainerRegistry.getInstance()
- registry.addContainer(stack)
- registry.addContainer(user_container)
+ ContainerRegistry.getInstance().addContainer(user_container)
return stack
@@ -149,46 +166,48 @@ class CuraStackBuilder:
#
# \return A new Global stack instance with the specified parameters.
@classmethod
- def createGlobalStack(cls, new_stack_id: str, definition: DefinitionContainerInterface, **kwargs) -> GlobalStack:
+ def createGlobalStack(cls, new_stack_id: str, definition: DefinitionContainerInterface,
+ variant_container, material_container, quality_container) -> GlobalStack:
+ from cura.CuraApplication import CuraApplication
+ application = CuraApplication.getInstance()
+
stack = GlobalStack(new_stack_id)
stack.setDefinition(definition)
- user_container = InstanceContainer(new_stack_id + "_user")
- user_container.addMetaDataEntry("type", "user")
- user_container.addMetaDataEntry("machine", new_stack_id)
- from cura.CuraApplication import CuraApplication
- user_container.addMetaDataEntry("setting_version", CuraApplication.SettingVersion)
- user_container.setDefinition(definition.getId())
+ # Create user container
+ user_container = cls.createUserChangesContainer(new_stack_id + "_user", definition.getId(), new_stack_id,
+ is_global_stack = True)
- stack.setUserChanges(user_container)
+ stack.definitionChanges = cls.createDefinitionChangesContainer(stack, new_stack_id + "_settings")
+ stack.variant = variant_container
+ stack.material = material_container
+ stack.quality = quality_container
+ stack.qualityChanges = application.empty_quality_changes_container
+ stack.userChanges = user_container
- # Important! The order here matters, because that allows the stack to
- # assume the material and variant have already been set.
- if "definition_changes" in kwargs:
- stack.setDefinitionChangesById(kwargs["definition_changes"])
- else:
- stack.setDefinitionChanges(cls.createDefinitionChangesContainer(stack, new_stack_id + "_settings"))
-
- if "variant" in kwargs:
- stack.setVariantById(kwargs["variant"])
-
- if "material" in kwargs:
- stack.setMaterialById(kwargs["material"])
-
- if "quality" in kwargs:
- stack.setQualityById(kwargs["quality"])
-
- if "quality_changes" in kwargs:
- stack.setQualityChangesById(kwargs["quality_changes"])
-
- registry = ContainerRegistry.getInstance()
- registry.addContainer(stack)
- registry.addContainer(user_container)
+ ContainerRegistry.getInstance().addContainer(user_container)
return stack
@classmethod
- def createDefinitionChangesContainer(cls, container_stack, container_name, container_index = None):
+ def createUserChangesContainer(cls, container_name: str, definition_id: str, stack_id: str,
+ is_global_stack: bool) -> "InstanceContainer":
+ from cura.CuraApplication import CuraApplication
+
+ unique_container_name = ContainerRegistry.getInstance().uniqueName(container_name)
+
+ container = InstanceContainer(unique_container_name)
+ container.setDefinition(definition_id)
+ container.addMetaDataEntry("type", "user")
+ container.addMetaDataEntry("setting_version", CuraApplication.SettingVersion)
+
+ metadata_key_to_add = "machine" if is_global_stack else "extruder"
+ container.addMetaDataEntry(metadata_key_to_add, stack_id)
+
+ return container
+
+ @classmethod
+ def createDefinitionChangesContainer(cls, container_stack, container_name):
from cura.CuraApplication import CuraApplication
unique_container_name = ContainerRegistry.getInstance().uniqueName(container_name)
diff --git a/cura/Settings/ExtruderManager.py b/cura/Settings/ExtruderManager.py
index b5f9a35914..2b422ec406 100755
--- a/cura/Settings/ExtruderManager.py
+++ b/cura/Settings/ExtruderManager.py
@@ -12,6 +12,7 @@ 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.SettingFunction import SettingFunction
+from UM.Settings.SettingInstance import SettingInstance
from UM.Settings.ContainerStack import ContainerStack
from UM.Settings.PropertyEvaluationContext import PropertyEvaluationContext
from typing import Optional, List, TYPE_CHECKING, Union
@@ -30,28 +31,22 @@ class ExtruderManager(QObject):
def __init__(self, parent = None):
super().__init__(parent)
+ self._application = Application.getInstance()
+
self._extruder_trains = {} # Per machine, a dictionary of extruder container stack IDs. Only for separately defined extruders.
self._active_extruder_index = -1 # Indicates the index of the active extruder stack. -1 means no active extruder stack
self._selected_object_extruders = []
- self._global_container_stack_definition_id = None
self._addCurrentMachineExtruders()
- Application.getInstance().globalContainerStackChanged.connect(self.__globalContainerStackChanged)
+ #Application.getInstance().globalContainerStackChanged.connect(self._globalContainerStackChanged)
Selection.selectionChanged.connect(self.resetSelectedObjectExtruders)
## Signal to notify other components when the list of extruders for a machine definition changes.
extrudersChanged = pyqtSignal(QVariant)
- ## Signal to notify other components when the global container stack is switched to a definition
- # that has different extruders than the previous global container stack
- globalContainerStackDefinitionChanged = pyqtSignal()
-
## Notify when the user switches the currently active extruder.
activeExtruderChanged = pyqtSignal()
- ## The signal notifies subscribers if extruders are added
- extrudersAdded = pyqtSignal()
-
## Gets the unique identifier of the currently active extruder stack.
#
# The currently active extruder stack is the stack that is currently being
@@ -184,6 +179,7 @@ class ExtruderManager(QObject):
self._selected_object_extruders = []
self.selectedObjectExtrudersChanged.emit()
+ @pyqtSlot(result = QObject)
def getActiveExtruderStack(self) -> Optional["ExtruderStack"]:
global_container_stack = Application.getInstance().getGlobalContainerStack()
@@ -245,6 +241,13 @@ class ExtruderManager(QObject):
result.append(extruder_stack.getProperty(setting_key, prop))
return result
+ def extruderValueWithDefault(self, value):
+ machine_manager = self._application.getMachineManager()
+ if value == "-1":
+ return machine_manager.defaultExtruderPosition
+ else:
+ return value
+
## Gets the extruder stacks that are actually being used at the moment.
#
# An extruder stack is being used if it is the extruder to print any mesh
@@ -256,7 +259,7 @@ class ExtruderManager(QObject):
#
# \return A list of extruder stacks.
def getUsedExtruderStacks(self) -> List["ContainerStack"]:
- global_stack = Application.getInstance().getGlobalContainerStack()
+ global_stack = self._application.getGlobalContainerStack()
container_registry = ContainerRegistry.getInstance()
used_extruder_stack_ids = set()
@@ -306,16 +309,19 @@ class ExtruderManager(QObject):
# Check support extruders
if support_enabled:
- used_extruder_stack_ids.add(self.extruderIds[str(global_stack.getProperty("support_infill_extruder_nr", "value"))])
- used_extruder_stack_ids.add(self.extruderIds[str(global_stack.getProperty("support_extruder_nr_layer_0", "value"))])
+ used_extruder_stack_ids.add(self.extruderIds[self.extruderValueWithDefault(str(global_stack.getProperty("support_infill_extruder_nr", "value")))])
+ used_extruder_stack_ids.add(self.extruderIds[self.extruderValueWithDefault(str(global_stack.getProperty("support_extruder_nr_layer_0", "value")))])
if support_bottom_enabled:
- used_extruder_stack_ids.add(self.extruderIds[str(global_stack.getProperty("support_bottom_extruder_nr", "value"))])
+ used_extruder_stack_ids.add(self.extruderIds[self.extruderValueWithDefault(str(global_stack.getProperty("support_bottom_extruder_nr", "value")))])
if support_roof_enabled:
- used_extruder_stack_ids.add(self.extruderIds[str(global_stack.getProperty("support_roof_extruder_nr", "value"))])
+ 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":
- used_extruder_stack_ids.add(self.extruderIds[str(global_stack.getProperty("adhesion_extruder_nr", "value"))])
+ extruder_nr = str(global_stack.getProperty("adhesion_extruder_nr", "value"))
+ if extruder_nr == "-1":
+ extruder_nr = Application.getInstance().getMachineManager().defaultExtruderPosition
+ used_extruder_stack_ids.add(self.extruderIds[extruder_nr])
try:
return [container_registry.findContainerStacks(id = stack_id)[0] for stack_id in used_extruder_stack_ids]
@@ -371,12 +377,7 @@ class ExtruderManager(QObject):
return result[:machine_extruder_count]
- def __globalContainerStackChanged(self) -> None:
- global_container_stack = Application.getInstance().getGlobalContainerStack()
- if global_container_stack and global_container_stack.getBottom() and global_container_stack.getBottom().getId() != self._global_container_stack_definition_id:
- self._global_container_stack_definition_id = global_container_stack.getBottom().getId()
- self.globalContainerStackDefinitionChanged.emit()
-
+ def _globalContainerStackChanged(self) -> None:
# If the global container changed, the machine changed and might have extruders that were not registered yet
self._addCurrentMachineExtruders()
@@ -384,7 +385,7 @@ class ExtruderManager(QObject):
## Adds the extruders of the currently active machine.
def _addCurrentMachineExtruders(self) -> None:
- global_stack = Application.getInstance().getGlobalContainerStack()
+ global_stack = self._application.getGlobalContainerStack()
extruders_changed = False
if global_stack:
@@ -404,14 +405,82 @@ class ExtruderManager(QObject):
self._extruder_trains[global_stack_id][extruder_train.getMetaDataEntry("position")] = extruder_train
# regardless of what the next stack is, we have to set it again, because of signal routing. ???
+ extruder_train.setParent(global_stack)
extruder_train.setNextStack(global_stack)
extruders_changed = True
+ self._fixMaterialDiameterAndNozzleSize(global_stack, extruder_trains)
if extruders_changed:
self.extrudersChanged.emit(global_stack_id)
- self.extrudersAdded.emit()
self.setActiveExtruderIndex(0)
+ #
+ # This function tries to fix the problem with per-extruder-settable nozzle size and material diameter problems
+ # in early versions (3.0 - 3.2.1).
+ #
+ # In earlier versions, "nozzle size" and "material diameter" are only applicable to the complete machine, so all
+ # extruders share the same values. In this case, "nozzle size" and "material diameter" are saved in the
+ # GlobalStack's DefinitionChanges container.
+ #
+ # Later, we could have different "nozzle size" for each extruder, but "material diameter" could only be set for
+ # the entire machine. In this case, "nozzle size" should be saved in each ExtruderStack's DefinitionChanges, but
+ # "material diameter" still remains in the GlobalStack's DefinitionChanges.
+ #
+ # Lateer, both "nozzle size" and "material diameter" are settable per-extruder, and both settings should be saved
+ # in the ExtruderStack's DefinitionChanges.
+ #
+ # There were some bugs in upgrade so the data weren't saved correct as described above. This function tries fix
+ # this.
+ #
+ # One more thing is about material diameter and single-extrusion machines. Most single-extrusion machines don't
+ # specifically define their extruder definition, so they reuse "fdmextruder", but for those machines, they may
+ # define "material diameter = 1.75" in their machine definition, but in "fdmextruder", it's still "2.85". This
+ # causes a problem with incorrect default values.
+ #
+ # This is also fixed here in this way: If no "material diameter" is specified, it will look for the default value
+ # in both the Extruder's definition and the Global's definition. If 2 values don't match, we will use the value
+ # from the Global definition by setting it in the Extruder's DefinitionChanges container.
+ #
+ def _fixMaterialDiameterAndNozzleSize(self, global_stack, extruder_stack_list):
+ keys_to_copy = ["material_diameter", "machine_nozzle_size"] # these will be copied over to all extruders
+
+ extruder_positions_to_update = set()
+ for extruder_stack in extruder_stack_list:
+ for key in keys_to_copy:
+ # Only copy the value when this extruder doesn't have the value.
+ if extruder_stack.definitionChanges.hasProperty(key, "value"):
+ continue
+
+ setting_value_in_global_def_changes = global_stack.definitionChanges.getProperty(key, "value")
+ setting_value_in_global_def = global_stack.definition.getProperty(key, "value")
+ setting_value = setting_value_in_global_def
+ if setting_value_in_global_def_changes is not None:
+ setting_value = setting_value_in_global_def_changes
+ if setting_value == extruder_stack.definition.getProperty(key, "value"):
+ continue
+
+ setting_definition = global_stack.getSettingDefinition(key)
+ new_instance = SettingInstance(setting_definition, extruder_stack.definitionChanges)
+ new_instance.setProperty("value", setting_value)
+ new_instance.resetState() # Ensure that the state is not seen as a user state.
+ extruder_stack.definitionChanges.addInstance(new_instance)
+ extruder_stack.definitionChanges.setDirty(True)
+
+ # Make sure the material diameter is up to date for the extruder stack.
+ if key == "material_diameter":
+ position = int(extruder_stack.getMetaDataEntry("position"))
+ extruder_positions_to_update.add(position)
+
+ # We have to remove those settings here because we know that those values have been copied to all
+ # the extruders at this point.
+ for key in keys_to_copy:
+ if global_stack.definitionChanges.hasProperty(key, "value"):
+ global_stack.definitionChanges.removeInstance(key, postpone_emit = True)
+
+ # Update material diameter for extruders
+ for position in extruder_positions_to_update:
+ self.updateMaterialForDiameter(position, global_stack = global_stack)
+
## Get all extruder values for a certain setting.
#
# This is exposed to SettingFunction so it can be used in value functions.
@@ -426,6 +495,8 @@ class ExtruderManager(QObject):
result = []
for extruder in ExtruderManager.getInstance().getMachineExtruders(global_stack.getId()):
+ if not extruder.isEnabled:
+ continue
# only include values from extruders that are "active" for the current machine instance
if int(extruder.getMetaDataEntry("position")) >= global_stack.getProperty("machine_extruder_count", "value"):
continue
@@ -496,6 +567,96 @@ class ExtruderManager(QObject):
def getInstanceExtruderValues(self, key):
return ExtruderManager.getExtruderValues(key)
+ ## Updates the material container to a material that matches the material diameter set for the printer
+ def updateMaterialForDiameter(self, extruder_position: int, global_stack = None):
+ if not global_stack:
+ global_stack = Application.getInstance().getGlobalContainerStack()
+ if not global_stack:
+ return
+
+ if not global_stack.getMetaDataEntry("has_materials", False):
+ return
+
+ extruder_stack = global_stack.extruders[str(extruder_position)]
+
+ material_diameter = extruder_stack.material.getProperty("material_diameter", "value")
+ if not material_diameter:
+ # in case of "empty" material
+ material_diameter = 0
+
+ material_approximate_diameter = str(round(material_diameter))
+ material_diameter = extruder_stack.definitionChanges.getProperty("material_diameter", "value")
+ setting_provider = extruder_stack
+ if not material_diameter:
+ if extruder_stack.definition.hasProperty("material_diameter", "value"):
+ material_diameter = extruder_stack.definition.getProperty("material_diameter", "value")
+ else:
+ material_diameter = global_stack.definition.getProperty("material_diameter", "value")
+ setting_provider = global_stack
+
+ if isinstance(material_diameter, SettingFunction):
+ material_diameter = material_diameter(setting_provider)
+
+ machine_approximate_diameter = str(round(material_diameter))
+
+ if material_approximate_diameter != machine_approximate_diameter:
+ Logger.log("i", "The the currently active material(s) do not match the diameter set for the printer. Finding alternatives.")
+
+ if global_stack.getMetaDataEntry("has_machine_materials", False):
+ materials_definition = global_stack.definition.getId()
+ has_material_variants = global_stack.getMetaDataEntry("has_variants", False)
+ else:
+ materials_definition = "fdmprinter"
+ has_material_variants = False
+
+ old_material = extruder_stack.material
+ search_criteria = {
+ "type": "material",
+ "approximate_diameter": machine_approximate_diameter,
+ "material": old_material.getMetaDataEntry("material", "value"),
+ "brand": old_material.getMetaDataEntry("brand", "value"),
+ "supplier": old_material.getMetaDataEntry("supplier", "value"),
+ "color_name": old_material.getMetaDataEntry("color_name", "value"),
+ "definition": materials_definition
+ }
+ if has_material_variants:
+ search_criteria["variant"] = extruder_stack.variant.getId()
+
+ container_registry = Application.getInstance().getContainerRegistry()
+ empty_material = container_registry.findInstanceContainers(id = "empty_material")[0]
+
+ if old_material == empty_material:
+ search_criteria.pop("material", None)
+ search_criteria.pop("supplier", None)
+ search_criteria.pop("brand", None)
+ search_criteria.pop("definition", None)
+ search_criteria["id"] = extruder_stack.getMetaDataEntry("preferred_material")
+
+ materials = container_registry.findInstanceContainers(**search_criteria)
+ if not materials:
+ # Same material with new diameter is not found, search for generic version of the same material type
+ search_criteria.pop("supplier", None)
+ search_criteria.pop("brand", None)
+ search_criteria["color_name"] = "Generic"
+ materials = container_registry.findInstanceContainers(**search_criteria)
+ if not materials:
+ # Generic material with new diameter is not found, search for preferred material
+ search_criteria.pop("color_name", None)
+ search_criteria.pop("material", None)
+ search_criteria["id"] = extruder_stack.getMetaDataEntry("preferred_material")
+ materials = container_registry.findInstanceContainers(**search_criteria)
+ if not materials:
+ # Preferred material with new diameter is not found, search for any material
+ search_criteria.pop("id", None)
+ materials = container_registry.findInstanceContainers(**search_criteria)
+ if not materials:
+ # Just use empty material as a final fallback
+ materials = [empty_material]
+
+ Logger.log("i", "Selecting new material: %s", materials[0].getId())
+
+ extruder_stack.material = materials[0]
+
## Get the value for a setting from a specific extruder.
#
# This is exposed to SettingFunction to use in value functions.
@@ -507,6 +668,8 @@ class ExtruderManager(QObject):
# global stack if not found.
@staticmethod
def getExtruderValue(extruder_index, key):
+ if extruder_index == -1:
+ extruder_index = int(Application.getInstance().getMachineManager().defaultExtruderPosition)
extruder = ExtruderManager.getInstance().getExtruderStack(extruder_index)
if extruder:
diff --git a/cura/Settings/ExtruderStack.py b/cura/Settings/ExtruderStack.py
index 6dffeda6c2..5cdcba68b0 100644
--- a/cura/Settings/ExtruderStack.py
+++ b/cura/Settings/ExtruderStack.py
@@ -3,25 +3,23 @@
from typing import Any, TYPE_CHECKING, Optional
+from PyQt5.QtCore import pyqtProperty, pyqtSignal
+
from UM.Decorators import override
from UM.MimeTypeDatabase import MimeType, MimeTypeDatabase
from UM.Settings.ContainerStack import ContainerStack
from UM.Settings.ContainerRegistry import ContainerRegistry
from UM.Settings.Interfaces import ContainerInterface, PropertyEvaluationContext
-from UM.Settings.SettingInstance import SettingInstance
+from UM.Util import parseBool
from . import Exceptions
-from .CuraContainerStack import CuraContainerStack
+from .CuraContainerStack import CuraContainerStack, _ContainerIndexes
from .ExtruderManager import ExtruderManager
if TYPE_CHECKING:
from cura.Settings.GlobalStack import GlobalStack
-_EXTRUDER_SPECIFIC_DEFINITION_CHANGES_SETTINGS = ["machine_nozzle_size",
- "material_diameter"]
-
-
## Represents an Extruder and its related containers.
#
#
@@ -33,11 +31,13 @@ class ExtruderStack(CuraContainerStack):
self.propertiesChanged.connect(self._onPropertiesChanged)
+ enabledChanged = pyqtSignal()
+
## Overridden from ContainerStack
#
# This will set the next stack and ensure that we register this stack as an extruder.
@override(ContainerStack)
- def setNextStack(self, stack: ContainerStack) -> None:
+ def setNextStack(self, stack: CuraContainerStack) -> None:
super().setNextStack(stack)
stack.addExtruder(self)
self.addMetaDataEntry("machine", stack.id)
@@ -45,37 +45,47 @@ class ExtruderStack(CuraContainerStack):
# For backward compatibility: Register the extruder with the Extruder Manager
ExtruderManager.getInstance().registerExtruder(self, stack.id)
- # Now each machine will have at least one extruder stack. If this is the first extruder, the extruder-specific
- # settings such as nozzle size and material diameter should be moved from the machine's definition_changes to
- # the this extruder's definition_changes.
- #
- # We do this here because it is tooooo expansive to do it in the version upgrade: During the version upgrade,
- # when we are upgrading a definition_changes container file, there is NO guarantee that other files such as
- # machine an extruder stack files are upgraded before this, so we cannot read those files assuming they are in
- # the latest format.
- if self.getMetaDataEntry("position") == "0":
- for key in _EXTRUDER_SPECIFIC_DEFINITION_CHANGES_SETTINGS:
- setting_value = stack.definitionChanges.getProperty(key, "value")
- if setting_value is None:
- continue
-
- setting_definition = stack.getSettingDefinition(key)
- new_instance = SettingInstance(setting_definition, self.definitionChanges)
- new_instance.setProperty("value", setting_value)
- new_instance.resetState() # Ensure that the state is not seen as a user state.
- self.definitionChanges.addInstance(new_instance)
- self.definitionChanges.setDirty(True)
-
- stack.definitionChanges.removeInstance(key, postpone_emit = True)
-
@override(ContainerStack)
def getNextStack(self) -> Optional["GlobalStack"]:
return super().getNextStack()
+ def setEnabled(self, enabled):
+ if "enabled" not in self._metadata:
+ self.addMetaDataEntry("enabled", "True")
+ self.setMetaDataEntry("enabled", str(enabled))
+ self.enabledChanged.emit()
+
+ @pyqtProperty(bool, notify = enabledChanged)
+ def isEnabled(self):
+ return parseBool(self.getMetaDataEntry("enabled", "True"))
+
@classmethod
def getLoadingPriority(cls) -> int:
return 3
+ ## 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:
+ context = PropertyEvaluationContext(self)
+ context.context["evaluate_from_container_index"] = _ContainerIndexes.Variant
+
+ return self.getProperty("material_diameter", "value", context = context)
+
+ ## Return the approximate filament diameter that the machine requires.
+ #
+ # The approximate material diameter is the material diameter rounded to
+ # the nearest millimetre.
+ #
+ # 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))
+
## Overridden from ContainerStack
#
# It will perform a few extra checks when trying to get properties.
@@ -144,11 +154,6 @@ class ExtruderStack(CuraContainerStack):
if has_global_dependencies:
self.getNextStack().propertiesChanged.emit(key, properties)
- def findDefaultVariant(self):
- # The default variant is defined in the machine stack and/or definition, so use the machine stack to find
- # the default variant.
- return self.getNextStack().findDefaultVariant()
-
extruder_stack_mime = MimeType(
name = "application/x-cura-extruderstack",
diff --git a/cura/Settings/ExtrudersModel.py b/cura/Settings/ExtrudersModel.py
index 5139b9885d..4ee5ab3c3b 100644
--- a/cura/Settings/ExtrudersModel.py
+++ b/cura/Settings/ExtrudersModel.py
@@ -1,7 +1,7 @@
# Copyright (c) 2017 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
-from PyQt5.QtCore import Qt, pyqtSignal, pyqtProperty, QTimer
+from PyQt5.QtCore import Qt, pyqtSignal, pyqtSlot, pyqtProperty, QTimer
from typing import Iterable
from UM.i18n import i18nCatalog
@@ -24,6 +24,8 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel):
## 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
@@ -43,6 +45,7 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel):
# The variant of the extruder.
VariantRole = Qt.UserRole + 7
+ StackRole = Qt.UserRole + 8
## List of colours to display if there is no material or the material has no known
# colour.
@@ -57,11 +60,13 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel):
self.addRoleName(self.IdRole, "id")
self.addRoleName(self.NameRole, "name")
+ self.addRoleName(self.EnabledRole, "enabled")
self.addRoleName(self.ColorRole, "color")
self.addRoleName(self.IndexRole, "index")
self.addRoleName(self.DefinitionRole, "definition")
self.addRoleName(self.MaterialRole, "material")
self.addRoleName(self.VariantRole, "variant")
+ self.addRoleName(self.StackRole, "stack")
self._update_extruder_timer = QTimer()
self._update_extruder_timer.setInterval(100)
@@ -183,11 +188,13 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel):
item = {
"id": extruder.getId(),
"name": extruder.getName(),
+ "enabled": extruder.isEnabled,
"color": color,
"index": position,
"definition": extruder.getBottom().getId(),
"material": extruder.material.getName() if extruder.material else "",
"variant": extruder.variant.getName() if extruder.variant else "", # e.g. print core
+ "stack": extruder,
}
items.append(item)
diff --git a/cura/Settings/GlobalStack.py b/cura/Settings/GlobalStack.py
index dae1c103b4..ae1f1370ed 100755
--- a/cura/Settings/GlobalStack.py
+++ b/cura/Settings/GlobalStack.py
@@ -1,6 +1,8 @@
# Copyright (c) 2017 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
+from collections import defaultdict
+import threading
from typing import Any, Dict, Optional
from PyQt5.QtCore import pyqtProperty
@@ -30,7 +32,8 @@ class GlobalStack(CuraContainerStack):
# This property is used to track which settings we are calculating the "resolve" for
# and if so, to bypass the resolve to prevent an infinite recursion that would occur
# if the resolve function tried to access the same property it is a resolve for.
- self._resolving_settings = set()
+ # Per thread we have our own resolving_settings, or strange things sometimes occur.
+ self._resolving_settings = defaultdict(set) # keys are thread names
## Get the list of extruders of this stack.
#
@@ -91,9 +94,10 @@ class GlobalStack(CuraContainerStack):
# Handle the "resolve" property.
if self._shouldResolve(key, property_name, context):
- self._resolving_settings.add(key)
+ current_thread = threading.current_thread()
+ self._resolving_settings[current_thread.name].add(key)
resolve = super().getProperty(key, "resolve", context)
- self._resolving_settings.remove(key)
+ self._resolving_settings[current_thread.name].remove(key)
if resolve is not None:
return resolve
@@ -121,21 +125,6 @@ class GlobalStack(CuraContainerStack):
def setNextStack(self, next_stack: ContainerStack) -> None:
raise Exceptions.InvalidOperationError("Global stack cannot have a next stack!")
- ## Gets the approximate filament diameter that the machine requires.
- #
- # The approximate material diameter is the material diameter rounded to
- # the nearest millimetre.
- #
- # If the machine has no requirement for the diameter, -1 is returned.
- #
- # \return The approximate filament diameter for the printer, as a string.
- @pyqtProperty(str)
- def approximateMaterialDiameter(self) -> str:
- material_diameter = self.definition.getProperty("material_diameter", "value")
- if material_diameter is None:
- return "-1"
- return str(round(float(material_diameter))) #Round, then convert back to string.
-
# protected:
# Determine whether or not we should try to get the "resolve" property instead of the
@@ -145,7 +134,8 @@ class GlobalStack(CuraContainerStack):
# Do not try to resolve anything but the "value" property
return False
- if key in self._resolving_settings:
+ current_thread = threading.current_thread()
+ if key in self._resolving_settings[current_thread.name]:
# To prevent infinite recursion, if getProperty is called with the same key as
# we are already trying to resolve, we should not try to resolve again. Since
# this can happen multiple times when trying to resolve a value, we need to
diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py
index 309f27b6d7..c79d352dcb 100755
--- a/cura/Settings/MachineManager.py
+++ b/cura/Settings/MachineManager.py
@@ -1,30 +1,34 @@
# Copyright (c) 2017 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
+import collections
+import time
#Type hinting.
-from typing import Union, List, Dict
+from typing import List, Dict, TYPE_CHECKING, Optional
+
+from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator
from UM.Signal import Signal
from PyQt5.QtCore import QObject, pyqtProperty, pyqtSignal, QTimer
+import UM.FlameProfiler
from UM.FlameProfiler import pyqtSlot
-from PyQt5.QtWidgets import QMessageBox
from UM import Util
from UM.Application import Application
from UM.Preferences import Preferences
from UM.Logger import Logger
from UM.Message import Message
-from UM.Decorators import deprecated
from UM.Settings.ContainerRegistry import ContainerRegistry
-from UM.Settings.ContainerStack import ContainerStack
-from UM.Settings.InstanceContainer import InstanceContainer
from UM.Settings.SettingFunction import SettingFunction
from UM.Signal import postponeSignals, CompressTechnique
-import UM.FlameProfiler
-from cura.QualityManager import QualityManager
+from cura.Machines.QualityManager import getMachineDefinitionIDForQualitySearch
+from cura.Machines.VariantManager import VariantType
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.Settings.ExtruderManager import ExtruderManager
from .CuraStackBuilder import CuraStackBuilder
@@ -32,49 +36,47 @@ from .CuraStackBuilder import CuraStackBuilder
from UM.i18n import i18nCatalog
catalog = i18nCatalog("cura")
-from cura.Settings.ProfilesModel import ProfilesModel
-from typing import TYPE_CHECKING, Optional
-
if TYPE_CHECKING:
- from UM.Settings.DefinitionContainer import DefinitionContainer
from cura.Settings.CuraContainerStack import CuraContainerStack
from cura.Settings.GlobalStack import GlobalStack
class MachineManager(QObject):
+
def __init__(self, parent = None):
super().__init__(parent)
self._active_container_stack = None # type: CuraContainerStack
self._global_container_stack = None # type: GlobalStack
- # Used to store the new containers until after confirming the dialog
- self._new_variant_container = None
- self._new_buildplate_container = None
- self._new_material_container = None
- self._new_quality_containers = []
+ self._current_root_material_id = {}
+ self._current_quality_group = None
+ self._current_quality_changes_group = None
- self._error_check_timer = QTimer()
- self._error_check_timer.setInterval(250)
- self._error_check_timer.setSingleShot(True)
- self._error_check_timer.timeout.connect(self._updateStacksHaveErrors)
+ self._default_extruder_position = "0" # to be updated when extruders are switched on and off
+
+ self.machine_extruder_material_update_dict = collections.defaultdict(list)
self._instance_container_timer = QTimer()
self._instance_container_timer.setInterval(250)
self._instance_container_timer.setSingleShot(True)
self._instance_container_timer.timeout.connect(self.__emitChangedSignals)
- Application.getInstance().globalContainerStackChanged.connect(self._onGlobalContainerChanged)
- Application.getInstance().getContainerRegistry().containerLoadComplete.connect(self._onInstanceContainersChanged)
- self._connected_to_profiles_model = False
+ self._application = Application.getInstance()
+ self._application.globalContainerStackChanged.connect(self._onGlobalContainerChanged)
+ self._application.getContainerRegistry().containerLoadComplete.connect(self._onInstanceContainersChanged)
## 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)
- self._stacks_have_errors = None
+ self.globalContainerChanged.connect(self.activeQualityChangesGroupChanged)
+ self.globalContainerChanged.connect(self.activeQualityGroupChanged)
+ self._stacks_have_errors = None # type:Optional[bool]
+
+ self._empty_definition_changes_container = ContainerRegistry.getInstance().findContainers(id = "empty_definition_changes")[0]
self._empty_variant_container = ContainerRegistry.getInstance().findContainers(id = "empty_variant")[0]
self._empty_material_container = ContainerRegistry.getInstance().findContainers(id = "empty_material")[0]
self._empty_quality_container = ContainerRegistry.getInstance().findContainers(id = "empty_quality")[0]
@@ -94,28 +96,22 @@ class MachineManager(QObject):
ExtruderManager.getInstance().activeExtruderChanged.connect(self.activeStackChanged)
self.activeStackChanged.connect(self.activeStackValueChanged)
- # when a user closed dialog check if any delayed material or variant changes need to be applied
- Application.getInstance().onDiscardOrKeepProfileChangesClosed.connect(self._executeDelayedActiveContainerStackChanges)
-
Preferences.getInstance().addPreference("cura/active_machine", "")
self._global_event_keys = set()
- active_machine_id = Preferences.getInstance().getValue("cura/active_machine")
-
self._printer_output_devices = []
Application.getInstance().getOutputDeviceManager().outputDevicesChanged.connect(self._onOutputDevicesChanged)
# There might already be some output devices by the time the signal is connected
self._onOutputDevicesChanged()
- if active_machine_id != "" and ContainerRegistry.getInstance().findContainerStacksMetadata(id = active_machine_id):
- # An active machine was saved, so restore it.
- self.setActiveMachine(active_machine_id)
- # Make sure _active_container_stack is properly initiated
- ExtruderManager.getInstance().setActiveExtruderIndex(0)
+ self._current_printer_configuration = ConfigurationModel() # Indicates the current configuration setup in this printer
+ self.activeMaterialChanged.connect(self._onCurrentConfigurationChanged)
+ self.activeVariantChanged.connect(self._onCurrentConfigurationChanged)
+ # Force to compute the current configuration
+ self._onCurrentConfigurationChanged()
- self._auto_materials_changed = {}
- self._auto_hotends_changed = {}
+ 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."),
@@ -125,11 +121,27 @@ class MachineManager(QObject):
if containers:
containers[0].nameChanged.connect(self._onMaterialNameChanged)
+ self._material_manager = self._application.getMaterialManager()
+ self._variant_manager = self._application.getVariantManager()
+ self._quality_manager = self._application.getQualityManager()
+
+ # When the materials lookup table gets updated, it can mean that a material has its name changed, which should
+ # be reflected on the GUI. This signal emission makes sure that it happens.
+ self._material_manager.materialsUpdated.connect(self.rootMaterialChanged)
+ # When the materials get updated, it can be that an activated material's diameter gets changed. In that case,
+ # a material update should be triggered to make sure that the machine still has compatible materials activated.
+ self._material_manager.materialsUpdated.connect(self._updateUponMaterialMetadataChange)
+ self.rootMaterialChanged.connect(self._onRootMaterialChanged)
+
+ activeQualityGroupChanged = pyqtSignal()
+ activeQualityChangesGroupChanged = pyqtSignal()
+
globalContainerChanged = pyqtSignal() # Emitted whenever the global stack is changed (ie: when changing between printers, changing a global profile, but not when changing a value)
activeMaterialChanged = pyqtSignal()
activeVariantChanged = pyqtSignal()
activeQualityChanged = pyqtSignal()
activeStackChanged = pyqtSignal() # Emitted whenever the active stack is changed (ie: when changing between extruders, changing a profile, but not when changing a value)
+ extruderChanged = pyqtSignal()
globalValueChanged = pyqtSignal() # Emitted whenever a value inside global container is changed.
activeStackValueChanged = pyqtSignal() # Emitted whenever a value inside the active stack is changed.
@@ -139,32 +151,58 @@ 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
+
+ rootMaterialChanged = pyqtSignal()
+
+ def setInitialActiveMachine(self):
+ active_machine_id = Preferences.getInstance().getValue("cura/active_machine")
+ if active_machine_id != "" and ContainerRegistry.getInstance().findContainerStacksMetadata(id = active_machine_id):
+ # An active machine was saved, so restore it.
+ self.setActiveMachine(active_machine_id)
+ # Make sure _active_container_stack is properly initiated
+ ExtruderManager.getInstance().setActiveExtruderIndex(0)
def _onOutputDevicesChanged(self) -> None:
- for printer_output_device in self._printer_output_devices:
- printer_output_device.hotendIdChanged.disconnect(self._onHotendIdChanged)
- printer_output_device.materialIdChanged.disconnect(self._onMaterialIdChanged)
-
self._printer_output_devices = []
for printer_output_device in Application.getInstance().getOutputDeviceManager().getOutputDevices():
if isinstance(printer_output_device, PrinterOutputDevice):
self._printer_output_devices.append(printer_output_device)
- printer_output_device.hotendIdChanged.connect(self._onHotendIdChanged)
- printer_output_device.materialIdChanged.connect(self._onMaterialIdChanged)
self.outputDevicesChanged.emit()
- @property
- def newVariant(self):
- return self._new_variant_container
+ @pyqtProperty(QObject, notify = currentConfigurationChanged)
+ def currentConfiguration(self):
+ return self._current_printer_configuration
- @property
- def newBuildplate(self):
- return self._new_buildplate_container
+ def _onCurrentConfigurationChanged(self) -> None:
+ if not self._global_container_stack:
+ return
- @property
- def newMaterial(self):
- return self._new_material_container
+ # Create the configuration model with the current data in Cura
+ self._current_printer_configuration.printerType = self._global_container_stack.definition.getName()
+ self._current_printer_configuration.extruderConfigurations = []
+ for extruder in self._global_container_stack.extruders.values():
+ extruder_configuration = ExtruderConfigurationModel()
+ # 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
+ 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
+ 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
+ self.currentConfigurationChanged.emit()
+
+ @pyqtSlot(QObject, result = bool)
+ def matchesConfiguration(self, configuration: ConfigurationModel) -> bool:
+ return self._current_printer_configuration == configuration
@pyqtProperty("QVariantList", notify = outputDevicesChanged)
def printerOutputDevices(self):
@@ -174,115 +212,7 @@ class MachineManager(QObject):
def totalNumberOfSettings(self) -> int:
return len(ContainerRegistry.getInstance().findDefinitionContainers(id = "fdmprinter")[0].getAllKeys())
- def _onHotendIdChanged(self):
- if not self._global_container_stack or not self._printer_output_devices:
- return
-
- active_printer_model = self._printer_output_devices[0].activePrinter
- if not active_printer_model:
- return
-
- change_found = False
- machine_id = self.activeMachineId
- extruders = sorted(ExtruderManager.getInstance().getMachineExtruders(machine_id),
- key=lambda k: k.getMetaDataEntry("position"))
-
- for extruder_model, extruder in zip(active_printer_model.extruders, extruders):
- containers = ContainerRegistry.getInstance().findInstanceContainersMetadata(type="variant",
- definition=self._global_container_stack.definition.getId(),
- name=extruder_model.hotendID)
- if containers:
- # The hotend ID is known.
- machine_id = self.activeMachineId
- if extruder.variant.getName() != extruder_model.hotendID:
- change_found = True
- self._auto_hotends_changed[extruder.getMetaDataEntry("position")] = containers[0]["id"]
-
- if change_found:
- # A change was found, let the output device handle this.
- self._printer_output_devices[0].materialHotendChangedMessage(self._materialHotendChangedCallback)
-
- def _onMaterialIdChanged(self):
- if not self._global_container_stack or not self._printer_output_devices:
- return
-
- active_printer_model = self._printer_output_devices[0].activePrinter
- if not active_printer_model:
- return
-
- change_found = False
- machine_id = self.activeMachineId
- extruders = sorted(ExtruderManager.getInstance().getMachineExtruders(machine_id),
- key=lambda k: k.getMetaDataEntry("position"))
-
- for extruder_model, extruder in zip(active_printer_model.extruders, extruders):
- if extruder_model.activeMaterial is None:
- continue
- containers = ContainerRegistry.getInstance().findInstanceContainersMetadata(type="material",
- definition=self._global_container_stack.definition.getId(),
- GUID=extruder_model.activeMaterial.guid)
- if containers:
- # The material is known.
- if extruder.material.getMetaDataEntry("GUID") != extruder_model.activeMaterial.guid:
- change_found = True
- if self._global_container_stack.definition.getMetaDataEntry("has_variants") and extruder.variant:
- variant_id = self.getQualityVariantId(self._global_container_stack.definition,
- extruder.variant)
- for container in containers:
- if container.get("variant") == variant_id:
- self._auto_materials_changed[extruder.getMetaDataEntry("position")] = container["id"]
- break
- else:
- # Just use the first result we found.
- self._auto_materials_changed[extruder.getMetaDataEntry("position")] = containers[0]["id"]
- if change_found:
- # A change was found, let the output device handle this.
- self._printer_output_devices[0].materialHotendChangedMessage(self._materialHotendChangedCallback)
-
- def _materialHotendChangedCallback(self, button):
- if button == QMessageBox.No:
- self._auto_materials_changed = {}
- self._auto_hotends_changed = {}
- return
- self._autoUpdateMaterials()
- self._autoUpdateHotends()
-
- def _autoUpdateMaterials(self):
- extruder_manager = ExtruderManager.getInstance()
- for position in self._auto_materials_changed:
- material_id = self._auto_materials_changed[position]
- old_index = extruder_manager.activeExtruderIndex
-
- if old_index != int(position):
- extruder_manager.setActiveExtruderIndex(int(position))
- else:
- old_index = None
-
- Logger.log("d", "Setting material of hotend %s to %s" % (position, material_id))
- self.setActiveMaterial(material_id)
-
- if old_index is not None:
- extruder_manager.setActiveExtruderIndex(old_index)
- self._auto_materials_changed = {} #Processed all of them now.
-
- def _autoUpdateHotends(self):
- extruder_manager = ExtruderManager.getInstance()
- for position in self._auto_hotends_changed:
- hotend_id = self._auto_hotends_changed[position]
- old_index = extruder_manager.activeExtruderIndex
-
- if old_index != int(position):
- extruder_manager.setActiveExtruderIndex(int(position))
- else:
- old_index = None
- Logger.log("d", "Setting hotend variant of hotend %s to %s" % (position, hotend_id))
- self.setActiveVariant(hotend_id)
-
- if old_index is not None:
- extruder_manager.setActiveExtruderIndex(old_index)
- self._auto_hotends_changed = {} # Processed all of them now.
-
- def _onGlobalContainerChanged(self):
+ def _onGlobalContainerChanged(self) -> None:
if self._global_container_stack:
try:
self._global_container_stack.nameChanged.disconnect(self._onMachineNameChanged)
@@ -301,9 +231,11 @@ class MachineManager(QObject):
extruder_stack.propertyChanged.disconnect(self._onPropertyChanged)
extruder_stack.containersChanged.disconnect(self._onInstanceContainersChanged)
- # update the local global container stack reference
+ # Update the local global container stack reference
self._global_container_stack = Application.getInstance().getGlobalContainerStack()
-
+ if self._global_container_stack:
+ self.updateDefaultExtruder()
+ self.updateNumberExtrudersEnabled()
self.globalContainerChanged.emit()
# after switching the global stack we reconnect all the signals and set the variant and material references
@@ -330,70 +262,94 @@ class MachineManager(QObject):
extruder_stack.propertyChanged.connect(self._onPropertyChanged)
extruder_stack.containersChanged.connect(self._onInstanceContainersChanged)
- self._error_check_timer.start()
+ 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()]:
+ Application.getInstance().callLater(func)
+ del self.machine_extruder_material_update_dict[self._global_container_stack.getId()]
- ## Update self._stacks_valid according to _checkStacksForErrors and emit if change.
- def _updateStacksHaveErrors(self):
- old_stacks_have_errors = self._stacks_have_errors
- self._stacks_have_errors = self._checkStacksHaveErrors()
- if old_stacks_have_errors != self._stacks_have_errors:
- self.stacksValidationChanged.emit()
- Application.getInstance().stacksValidationFinished.emit()
+ self.activeQualityGroupChanged.emit()
- def _onActiveExtruderStackChanged(self):
+ 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()
- self._error_check_timer.start()
-
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):
+ def __emitChangedSignals(self) -> None:
self.activeQualityChanged.emit()
self.activeVariantChanged.emit()
self.activeMaterialChanged.emit()
- self._updateStacksHaveErrors() # Prevents unwanted re-slices after changing machine
- self._error_check_timer.start()
- def _onProfilesModelChanged(self, *args):
- self.__emitChangedSignals()
-
- def _onInstanceContainersChanged(self, container):
- # This should not trigger the ProfilesModel to be created, or there will be an infinite recursion
- if not self._connected_to_profiles_model and ProfilesModel.hasInstance():
- # This triggers updating the qualityModel in SidebarSimple whenever ProfilesModel is updated
- Logger.log("d", "Connecting profiles model...")
- ProfilesModel.getInstance().itemsChanged.connect(self._onProfilesModelChanged)
- self._connected_to_profiles_model = True
+ self.rootMaterialChanged.emit()
+ def _onInstanceContainersChanged(self, container) -> None:
self._instance_container_timer.start()
- def _onPropertyChanged(self, key: str, property_name: str):
+ def _onPropertyChanged(self, key: str, property_name: str) -> None:
if property_name == "value":
# Notify UI items, such as the "changed" star in profile pull down menu.
self.activeStackValueChanged.emit()
- elif property_name == "validationState":
- self._error_check_timer.start()
+ ## Given a global_stack, make sure that it's all valid by searching for this quality group and applying it again
+ def _initMachineState(self, global_stack):
+ material_dict = {}
+ for position, extruder in global_stack.extruders.items():
+ material_dict[position] = extruder.material.getMetaDataEntry("base_file")
+ self._current_root_material_id = material_dict
+ global_quality = global_stack.quality
+ quality_type = global_quality.getMetaDataEntry("quality_type")
+ global_quality_changes = global_stack.qualityChanges
+ global_quality_changes_name = global_quality_changes.getName()
+
+ if global_quality_changes.getId() != "empty_quality_changes":
+ quality_changes_groups = self._application._quality_manager.getQualityChangesGroups(global_stack)
+ if global_quality_changes_name in quality_changes_groups:
+ new_quality_changes_group = quality_changes_groups[global_quality_changes_name]
+ self._setQualityChangesGroup(new_quality_changes_group)
+ else:
+ quality_groups = self._application._quality_manager.getQualityGroups(global_stack)
+ if quality_type not in quality_groups:
+ Logger.log("w", "Quality type [%s] not found in available qualities [%s]", quality_type, str(quality_groups.values()))
+ self._setEmptyQuality()
+ return
+ new_quality_group = quality_groups[quality_type]
+ self._setQualityGroup(new_quality_group, empty_quality_changes = True)
@pyqtSlot(str)
def setActiveMachine(self, stack_id: str) -> None:
self.blurSettings.emit() # Ensure no-one has focus.
- self._cancelDelayedActiveContainerStackChanges()
container_registry = ContainerRegistry.getInstance()
containers = container_registry.findContainerStacks(id = stack_id)
if containers:
- Application.getInstance().setGlobalContainerStack(containers[0])
+ global_stack = containers[0]
+ ExtruderManager.getInstance().setActiveExtruderIndex(0) # Switch to first extruder
+ self._global_container_stack = global_stack
+ Application.getInstance().setGlobalContainerStack(global_stack)
+ ExtruderManager.getInstance()._globalContainerStackChanged()
+ self._initMachineState(containers[0])
+ self._onGlobalContainerChanged()
self.__emitChangedSignals()
+ ## Given a definition id, return the machine with this id.
+ # Optional: add a list of keys and values to filter the list of machines with the given definition id
+ # \param definition_id \type{str} definition id that needs to look for
+ # \param metadata_filter \type{dict} list of metadata keys and values used for filtering
+ @staticmethod
+ def getMachine(definition_id: str, metadata_filter: Dict[str, str] = None) -> Optional["GlobalStack"]:
+ machines = ContainerRegistry.getInstance().findContainerStacks(type = "machine", **metadata_filter)
+ for machine in machines:
+ if machine.definition.getId() == definition_id:
+ return machine
+ return None
+
@pyqtSlot(str, str)
def addMachine(self, name: str, definition_id: str) -> None:
new_stack = CuraStackBuilder.createMachine(name, definition_id)
@@ -404,27 +360,30 @@ class MachineManager(QObject):
Logger.log("w", "Failed creating a new machine!")
def _checkStacksHaveErrors(self) -> bool:
+ time_start = time.time()
if self._global_container_stack is None: #No active machine.
return False
if self._global_container_stack.hasErrors():
+ Logger.log("d", "Checking global stack for errors took %0.2f s and we found an error" % (time.time() - time_start))
return True
- for stack in ExtruderManager.getInstance().getMachineExtruders(self._global_container_stack.getId()):
+
+ # 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().getMachineExtruders(self._global_container_stack.getId())
+ 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:
+ continue
+ count += 1
if stack.hasErrors():
+ Logger.log("d", "Checking %s stacks for errors took %.2f s and we found an error in stack [%s]" % (count, time.time() - time_start, str(stack)))
return True
+ Logger.log("d", "Checking %s stacks for errors took %.2f s" % (count, time.time() - time_start))
return False
- ## Remove all instances from the top instanceContainer (effectively removing all user-changed settings)
- @pyqtSlot()
- def clearUserSettings(self):
- if not self._active_container_stack:
- return
-
- self.blurSettings.emit()
- user_settings = self._active_container_stack.getTop()
- user_settings.clear()
-
## Check if the global_container has instances in the user container
@pyqtProperty(bool, notify = activeStackValueChanged)
def hasUserSettings(self) -> bool:
@@ -455,7 +414,7 @@ class MachineManager(QObject):
## 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):
+ def clearUserSettingAllCurrentStacks(self, key: str) -> None:
if not self._global_container_stack:
return
@@ -490,25 +449,34 @@ class MachineManager(QObject):
def stacksHaveErrors(self) -> bool:
return bool(self._stacks_have_errors)
- @pyqtProperty(str, notify = activeStackChanged)
- def activeUserProfileId(self) -> str:
- if self._active_container_stack:
- return self._active_container_stack.getTop().getId()
-
+ @pyqtProperty(str, notify = globalContainerChanged)
+ def activeMachineDefinitionName(self) -> str:
+ if self._global_container_stack:
+ return self._global_container_stack.definition.getName()
return ""
@pyqtProperty(str, notify = globalContainerChanged)
def activeMachineName(self) -> str:
if self._global_container_stack:
return self._global_container_stack.getName()
-
return ""
@pyqtProperty(str, notify = globalContainerChanged)
def activeMachineId(self) -> str:
if self._global_container_stack:
return self._global_container_stack.getId()
+ return ""
+ @pyqtProperty(str, notify = outputDevicesChanged)
+ def activeMachineNetworkKey(self) -> str:
+ if self._global_container_stack:
+ return self._global_container_stack.getMetaDataEntry("um_network_key")
+ return ""
+
+ @pyqtProperty(str, notify = outputDevicesChanged)
+ def activeMachineNetworkGroupName(self) -> str:
+ if self._global_container_stack:
+ return self._global_container_stack.getMetaDataEntry("connect_group_name")
return ""
@pyqtProperty(QObject, notify = globalContainerChanged)
@@ -519,42 +487,11 @@ class MachineManager(QObject):
def activeStackId(self) -> str:
if self._active_container_stack:
return self._active_container_stack.getId()
-
return ""
- @pyqtProperty(str, notify = activeMaterialChanged)
- def activeMaterialName(self) -> str:
- if self._active_container_stack:
- material = self._active_container_stack.material
- if material:
- return material.getName()
-
- return ""
-
- @pyqtProperty("QVariantList", notify=activeVariantChanged)
- def activeVariantNames(self) -> List[str]:
- result = []
-
- active_stacks = ExtruderManager.getInstance().getActiveGlobalAndExtruderStacks()
- if active_stacks is not None:
- for stack in active_stacks:
- variant_container = stack.variant
- if variant_container and variant_container != self._empty_variant_container:
- result.append(variant_container.getName())
-
- return result
-
- @pyqtProperty("QVariantList", notify = activeMaterialChanged)
- def activeMaterialNames(self) -> List[str]:
- result = []
-
- active_stacks = ExtruderManager.getInstance().getActiveGlobalAndExtruderStacks()
- if active_stacks is not None:
- for stack in active_stacks:
- material_container = stack.material
- if material_container and material_container != self._empty_material_container:
- result.append(material_container.getName())
- return result
+ @pyqtProperty(QObject, notify = activeStackChanged)
+ def activeStack(self) -> Optional["ExtruderStack"]:
+ return self._active_container_stack
@pyqtProperty(str, notify=activeMaterialChanged)
def activeMaterialId(self) -> str:
@@ -562,24 +499,8 @@ class MachineManager(QObject):
material = self._active_container_stack.material
if material:
return material.getId()
-
return ""
- @pyqtProperty("QVariantMap", notify = activeVariantChanged)
- def allActiveVariantIds(self) -> Dict[str, str]:
- result = {}
-
- active_stacks = ExtruderManager.getInstance().getActiveExtruderStacks()
- if active_stacks is not None: #If we have a global stack.
- for stack in active_stacks:
- variant_container = stack.variant
- if not variant_container:
- continue
-
- result[stack.getId()] = variant_container.getId()
-
- return result
-
## Gets a dict with the active materials ids set in all extruder stacks and the global stack
# (when there is one extruder, the material is set in the global stack)
#
@@ -604,106 +525,45 @@ class MachineManager(QObject):
#
# \return The layer height of the currently active quality profile. If
# there is no quality profile, this returns 0.
- @pyqtProperty(float, notify=activeQualityChanged)
+ @pyqtProperty(float, notify = activeQualityGroupChanged)
def activeQualityLayerHeight(self) -> float:
if not self._global_container_stack:
return 0
-
- quality_changes = self._global_container_stack.qualityChanges
- if quality_changes:
- value = self._global_container_stack.getRawProperty("layer_height", "value", skip_until_container = quality_changes.getId())
+ if self._current_quality_changes_group:
+ value = self._global_container_stack.getRawProperty("layer_height", "value", skip_until_container = self._global_container_stack.qualityChanges.getId())
if isinstance(value, SettingFunction):
value = value(self._global_container_stack)
return value
- quality = self._global_container_stack.quality
- if quality:
- value = self._global_container_stack.getRawProperty("layer_height", "value", skip_until_container = quality.getId())
+ elif self._current_quality_group:
+ value = self._global_container_stack.getRawProperty("layer_height", "value", skip_until_container = self._global_container_stack.quality.getId())
if isinstance(value, SettingFunction):
value = value(self._global_container_stack)
return value
+ return 0
- return 0 # No quality profile.
-
- ## Get the Material ID associated with the currently active material
- # \returns MaterialID (string) if found, empty string otherwise
- @pyqtProperty(str, notify=activeQualityChanged)
- def activeQualityMaterialId(self) -> str:
- if self._active_container_stack:
- quality = self._active_container_stack.quality
- if quality:
- material_id = quality.getMetaDataEntry("material")
- if material_id:
- # if the currently active machine inherits its qualities from a different machine
- # definition, make sure to return a material that is relevant to that machine definition
- definition_id = self.activeDefinitionId
- quality_definition_id = self.activeQualityDefinitionId
- if definition_id != quality_definition_id:
- material_id = material_id.replace(definition_id, quality_definition_id, 1)
-
- return material_id
- return ""
-
- @pyqtProperty(str, notify=activeQualityChanged)
- def activeQualityName(self) -> str:
- if self._active_container_stack and self._global_container_stack:
- quality = self._global_container_stack.qualityChanges
- if quality and not isinstance(quality, type(self._empty_quality_changes_container)):
- return quality.getName()
- quality = self._active_container_stack.quality
- if quality:
- return quality.getName()
- return ""
-
- @pyqtProperty(str, notify=activeQualityChanged)
- def activeQualityId(self) -> str:
- if self._active_container_stack:
- quality = self._active_container_stack.quality
- if isinstance(quality, type(self._empty_quality_container)):
- return ""
- quality_changes = self._active_container_stack.qualityChanges
- if quality and quality_changes:
- if isinstance(quality_changes, type(self._empty_quality_changes_container)):
- # It's a built-in profile
- return quality.getId()
- else:
- # Custom profile
- return quality_changes.getId()
- return ""
-
- @pyqtProperty(str, notify=activeQualityChanged)
- def globalQualityId(self) -> str:
- if self._global_container_stack:
- quality = self._global_container_stack.qualityChanges
- if quality and not isinstance(quality, type(self._empty_quality_changes_container)):
- return quality.getId()
- quality = self._global_container_stack.quality
- if quality:
- return quality.getId()
- return ""
-
- @pyqtProperty(str, notify=activeVariantChanged)
- def globalVariantId(self) -> str:
+ @pyqtProperty(str, notify = activeVariantChanged)
+ 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)):
- return variant.getId()
+ return variant.getName()
return ""
- @pyqtProperty(str, notify = activeQualityChanged)
+ @pyqtProperty(str, notify = activeQualityGroupChanged)
def activeQualityType(self) -> str:
+ quality_type = ""
if self._active_container_stack:
- quality = self._active_container_stack.quality
- if quality:
- return quality.getMetaDataEntry("quality_type")
- return ""
+ if self._current_quality_group:
+ quality_type = self._current_quality_group.quality_type
+ return quality_type
- @pyqtProperty(bool, notify = activeQualityChanged)
+ @pyqtProperty(bool, notify = activeQualityGroupChanged)
def isActiveQualitySupported(self) -> bool:
- if self._active_container_stack:
- quality = self._active_container_stack.quality
- if quality:
- return Util.parseBool(quality.getMetaDataEntry("supported", True))
- return False
+ is_supported = False
+ if self._global_container_stack:
+ if self._current_quality_group:
+ is_supported = self._current_quality_group.is_available
+ return is_supported
## Returns whether there is anything unsupported in the current set-up.
#
@@ -722,29 +582,6 @@ class MachineManager(QObject):
return False
return True
- ## Get the Quality ID associated with the currently active extruder
- # Note that this only returns the "quality", not the "quality_changes"
- # \returns QualityID (string) if found, empty string otherwise
- # \sa activeQualityId()
- # \todo Ideally, this method would be named activeQualityId(), and the other one
- # would be named something like activeQualityOrQualityChanges() for consistency
- @pyqtProperty(str, notify = activeQualityChanged)
- def activeQualityContainerId(self) -> str:
- # We're using the active stack instead of the global stack in case the list of qualities differs per extruder
- if self._global_container_stack:
- quality = self._active_container_stack.quality
- if quality:
- return quality.getId()
- return ""
-
- @pyqtProperty(str, notify = activeQualityChanged)
- def activeQualityChangesId(self) -> str:
- if self._active_container_stack:
- quality_changes = self._active_container_stack.qualityChanges
- if quality_changes and not isinstance(quality_changes, type(self._empty_quality_changes_container)):
- return quality_changes.getId()
- return ""
-
## Check if a container is read_only
@pyqtSlot(str, result = bool)
def isReadOnly(self, container_id: str) -> bool:
@@ -761,389 +598,6 @@ class MachineManager(QObject):
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
- ## Set the active material by switching out a container
- # Depending on from/to material+current variant, a quality profile is chosen and set.
- @pyqtSlot(str)
- def setActiveMaterial(self, material_id: str, always_discard_changes = False):
- with postponeSignals(*self._getContainerChangedSignals(), compress = CompressTechnique.CompressPerParameterValue):
- containers = ContainerRegistry.getInstance().findInstanceContainers(id = material_id)
- if not containers or not self._active_container_stack:
- return
- material_container = containers[0]
-
- Logger.log("d", "Attempting to change the active material to %s", material_id)
-
- old_material = self._active_container_stack.material
- old_quality = self._active_container_stack.quality
- old_quality_type = None
- if old_quality and old_quality.getId() != self._empty_quality_container.getId():
- old_quality_type = old_quality.getMetaDataEntry("quality_type")
- old_quality_changes = self._active_container_stack.qualityChanges
- if not old_material:
- Logger.log("w", "While trying to set the active material, no material was found to replace it.")
- return
-
- if old_quality_changes and isinstance(old_quality_changes, type(self._empty_quality_changes_container)):
- old_quality_changes = None
-
- self.blurSettings.emit()
- old_material.nameChanged.disconnect(self._onMaterialNameChanged)
-
- self._new_material_container = material_container # self._active_container_stack will be updated with a delay
- Logger.log("d", "Active material changed")
-
- material_container.nameChanged.connect(self._onMaterialNameChanged)
-
- if material_container.getMetaDataEntry("compatible") == False:
- self._material_incompatible_message.show()
- else:
- self._material_incompatible_message.hide()
-
- quality_type = None
- new_quality_id = None
- if old_quality:
- new_quality_id = old_quality.getId()
- quality_type = old_quality.getMetaDataEntry("quality_type")
- if old_quality_changes:
- quality_type = old_quality_changes.getMetaDataEntry("quality_type")
- new_quality_id = old_quality_changes.getId()
-
- global_stack = Application.getInstance().getGlobalContainerStack()
- if global_stack:
- quality_manager = QualityManager.getInstance()
-
- candidate_quality = None
- if quality_type:
- candidate_quality = quality_manager.findQualityByQualityType(quality_type,
- quality_manager.getWholeMachineDefinition(global_stack.definition),
- [material_container.getMetaData()])
-
- if not candidate_quality or candidate_quality.getId() == self._empty_quality_changes_container:
- Logger.log("d", "Attempting to find fallback quality")
- # Fall back to a quality (which must be compatible with all other extruders)
- new_qualities = quality_manager.findAllUsableQualitiesForMachineAndExtruders(
- self._global_container_stack, ExtruderManager.getInstance().getExtruderStacks())
-
- quality_types = sorted([q.getMetaDataEntry("quality_type") for q in new_qualities], reverse = True)
- quality_type_to_use = None
- if quality_types:
- # try to use the same quality as before, otherwise the first one in the quality_types
- quality_type_to_use = quality_types[0]
- if old_quality_type is not None and old_quality_type in quality_type_to_use:
- quality_type_to_use = old_quality_type
-
- new_quality = None
- for q in new_qualities:
- if quality_type_to_use is not None and q.getMetaDataEntry("quality_type") == quality_type_to_use:
- new_quality = q
- break
-
- if new_quality is not None:
- new_quality_id = new_quality.getId() # Just pick the first available one
- else:
- Logger.log("w", "No quality profile found that matches the current machine and extruders.")
- else:
- if not old_quality_changes:
- new_quality_id = candidate_quality.getId()
-
- self.setActiveQuality(new_quality_id, always_discard_changes = always_discard_changes)
-
- @pyqtSlot(str)
- def setActiveVariant(self, variant_id: str, always_discard_changes = False):
- with postponeSignals(*self._getContainerChangedSignals(), compress = CompressTechnique.CompressPerParameterValue):
- containers = ContainerRegistry.getInstance().findInstanceContainers(id = variant_id)
- if not containers or not self._active_container_stack:
- return
- Logger.log("d", "Attempting to change the active variant to %s", variant_id)
- old_variant = self._active_container_stack.variant
- old_material = self._active_container_stack.material
- if old_variant:
- self.blurSettings.emit()
- self._new_variant_container = containers[0] # self._active_container_stack will be updated with a delay
- Logger.log("d", "Active variant changed to {active_variant_id}".format(active_variant_id = containers[0].getId()))
- preferred_material_name = None
- if old_material:
- preferred_material_name = old_material.getName()
- preferred_material_id = self._updateMaterialContainer(self._global_container_stack.definition, self._global_container_stack, containers[0], preferred_material_name).id
- self.setActiveMaterial(preferred_material_id, always_discard_changes = always_discard_changes)
- else:
- Logger.log("w", "While trying to set the active variant, no variant was found to replace.")
-
- @pyqtSlot(str)
- def setActiveVariantBuildplate(self, variant_buildplate_id: str):
- with postponeSignals(*self._getContainerChangedSignals(), compress = CompressTechnique.CompressPerParameterValue):
- containers = ContainerRegistry.getInstance().findInstanceContainers(id = variant_buildplate_id)
- if not containers or not self._global_container_stack:
- return
- Logger.log("d", "Attempting to change the active buildplate to %s", variant_buildplate_id)
- old_buildplate = self._global_container_stack.variant
- if old_buildplate:
- self.blurSettings.emit()
- self._new_buildplate_container = containers[0] # self._active_container_stack will be updated with a delay
- Logger.log("d", "Active buildplate changed to {active_variant_buildplate_id}".format(active_variant_buildplate_id = containers[0].getId()))
-
- # Force set the active quality as it is so the values are updated
- self.setActiveMaterial(self._active_container_stack.material.getId())
- else:
- Logger.log("w", "While trying to set the active buildplate, no buildplate was found to replace.")
-
- ## set the active quality
- # \param quality_id The quality_id of either a quality or a quality_changes
- @pyqtSlot(str)
- def setActiveQuality(self, quality_id: str, always_discard_changes = False):
- with postponeSignals(*self._getContainerChangedSignals(), compress = CompressTechnique.CompressPerParameterValue):
- self.blurSettings.emit()
-
- Logger.log("d", "Attempting to change the active quality to %s", quality_id)
-
- containers = ContainerRegistry.getInstance().findInstanceContainersMetadata(id = quality_id)
- if not containers or not self._global_container_stack:
- return
-
- # Quality profile come in two flavours: type=quality and type=quality_changes
- # If we found a quality_changes profile then look up its parent quality profile.
- container_type = containers[0].get("type")
- quality_name = containers[0]["name"]
- quality_type = containers[0].get("quality_type")
-
- # Get quality container and optionally the quality_changes container.
- if container_type == "quality":
- new_quality_settings_list = self.determineQualityAndQualityChangesForQualityType(quality_type)
- elif container_type == "quality_changes":
- new_quality_settings_list = self._determineQualityAndQualityChangesForQualityChanges(quality_name)
- else:
- Logger.log("e", "Tried to set quality to a container that is not of the right type: {container_id}".format(container_id = containers[0]["id"]))
- return
-
- # Check if it was at all possible to find new settings
- if new_quality_settings_list is None:
- return
-
- # check if any of the stacks have a not supported profile
- # if that is the case, all stacks should have a not supported state (otherwise it will show quality_type normal)
- has_not_supported_quality = False
-
- # check all stacks for not supported
- for setting_info in new_quality_settings_list:
- if setting_info["quality"].getMetaDataEntry("quality_type") == "not_supported":
- has_not_supported_quality = True
- break
-
- # set all stacks to not supported if that's the case
- if has_not_supported_quality:
- for setting_info in new_quality_settings_list:
- setting_info["quality"] = self._empty_quality_container
-
- self._new_quality_containers.clear()
-
- # store the upcoming quality profile changes per stack for later execution
- # this prevents re-slicing before the user has made a choice in the discard or keep dialog
- # (see _executeDelayedActiveContainerStackChanges)
- for setting_info in new_quality_settings_list:
- stack = setting_info["stack"]
- stack_quality = setting_info["quality"]
- stack_quality_changes = setting_info["quality_changes"]
-
- self._new_quality_containers.append({
- "stack": stack,
- "quality": stack_quality,
- "quality_changes": stack_quality_changes
- })
-
- Logger.log("d", "Active quality changed")
-
- # show the keep/discard dialog after the containers have been switched. Otherwise, the default values on
- # the dialog will be the those before the switching.
- self._executeDelayedActiveContainerStackChanges()
-
- if self.hasUserSettings and Preferences.getInstance().getValue("cura/active_mode") == 1 and not always_discard_changes:
- Application.getInstance().discardOrKeepProfileChanges()
-
- ## Used to update material and variant in the active container stack with a delay.
- # This delay prevents the stack from triggering a lot of signals (eventually resulting in slicing)
- # before the user decided to keep or discard any of their changes using the dialog.
- # The Application.onDiscardOrKeepProfileChangesClosed signal triggers this method.
- def _executeDelayedActiveContainerStackChanges(self):
-
- Logger.log("d", "Applying configuration changes...")
-
- if self._new_variant_container is not None:
- self._active_container_stack.variant = self._new_variant_container
- self._new_variant_container = None
-
- if self._new_buildplate_container is not None:
- self._global_container_stack.variant = self._new_buildplate_container
- self._new_buildplate_container = None
-
- if self._new_material_container is not None:
- self._active_container_stack.material = self._new_material_container
- self._new_material_container = None
-
- # apply the new quality to all stacks
- if self._new_quality_containers:
- for new_quality in self._new_quality_containers:
- self._replaceQualityOrQualityChangesInStack(new_quality["stack"], new_quality["quality"], postpone_emit = True)
- self._replaceQualityOrQualityChangesInStack(new_quality["stack"], new_quality["quality_changes"], postpone_emit = True)
-
- for new_quality in self._new_quality_containers:
- new_quality["stack"].nameChanged.connect(self._onQualityNameChanged)
- new_quality["stack"].sendPostponedEmits() # Send the signals that were postponed in _replaceQualityOrQualityChangesInStack
-
- self._new_quality_containers.clear()
-
- Logger.log("d", "New configuration applied")
-
- ## Cancel set changes for material and variant in the active container stack.
- # Used for ignoring any changes when switching between printers (setActiveMachine)
- def _cancelDelayedActiveContainerStackChanges(self):
- self._new_material_container = None
- self._new_buildplate_container = None
- self._new_variant_container = None
-
- ## Determine the quality and quality changes settings for the current machine for a quality name.
- #
- # \param quality_name \type{str} the name of the quality.
- # \return \type{List[Dict]} with keys "stack", "quality" and "quality_changes".
- @UM.FlameProfiler.profile
- def determineQualityAndQualityChangesForQualityType(self, quality_type: str) -> List[Dict[str, Union["CuraContainerStack", InstanceContainer]]]:
- quality_manager = QualityManager.getInstance()
- result = []
- empty_quality_changes = self._empty_quality_changes_container
- global_container_stack = self._global_container_stack
- if not global_container_stack:
- return []
-
- global_machine_definition = quality_manager.getParentMachineDefinition(global_container_stack.definition)
- extruder_stacks = ExtruderManager.getInstance().getActiveExtruderStacks()
-
- # find qualities for extruders
- for extruder_stack in extruder_stacks:
- material_metadata = extruder_stack.material.getMetaData()
-
- # TODO: fix this
- if self._new_material_container and extruder_stack.getId() == self._active_container_stack.getId():
- material_metadata = self._new_material_container.getMetaData()
-
- quality = quality_manager.findQualityByQualityType(quality_type, global_machine_definition, [material_metadata])
-
- if not quality:
- # No quality profile is found for this quality type.
- quality = self._empty_quality_container
-
- result.append({
- "stack": extruder_stack,
- "quality": quality,
- "quality_changes": empty_quality_changes
- })
-
- # also find a global quality for the machine
- global_quality = quality_manager.findQualityByQualityType(quality_type, global_machine_definition, [], global_quality = "True")
-
- # if there is not global quality but we're using a single extrusion machine, copy the quality of the first extruder - CURA-4482
- if not global_quality and len(extruder_stacks) == 1:
- global_quality = result[0]["quality"]
-
- # if there is still no global quality, set it to empty (not supported)
- if not global_quality:
- global_quality = self._empty_quality_container
-
- result.append({
- "stack": global_container_stack,
- "quality": global_quality,
- "quality_changes": empty_quality_changes
- })
-
- return result
-
- ## Determine the quality and quality changes settings for the current machine for a quality changes name.
- #
- # \param quality_changes_name \type{str} the name of the quality changes.
- # \return \type{List[Dict]} with keys "stack", "quality" and "quality_changes".
- def _determineQualityAndQualityChangesForQualityChanges(self, quality_changes_name: str) -> Optional[List[Dict[str, Union["CuraContainerStack", InstanceContainer]]]]:
- result = []
- quality_manager = QualityManager.getInstance()
-
- global_container_stack = self._global_container_stack
- global_machine_definition = quality_manager.getParentMachineDefinition(global_container_stack.definition)
- quality_changes_profiles = quality_manager.findQualityChangesByName(quality_changes_name, global_machine_definition)
-
- global_quality_changes = [qcp for qcp in quality_changes_profiles if qcp.getMetaDataEntry("extruder") is None]
- if global_quality_changes:
- global_quality_changes = global_quality_changes[0]
- else:
- Logger.log("e", "Could not find the global quality changes container with name %s", quality_changes_name)
- return None
-
- # For the global stack, find a quality which matches the quality_type in
- # the quality changes profile and also satisfies any material constraints.
- quality_type = global_quality_changes.getMetaDataEntry("quality_type")
-
- extruder_stacks = ExtruderManager.getInstance().getActiveExtruderStacks()
-
- # append the extruder quality changes
- for extruder_stack in extruder_stacks:
- extruder_definition = quality_manager.getParentMachineDefinition(extruder_stack.definition)
-
- quality_changes_list = [qcp for qcp in quality_changes_profiles if qcp.getMetaDataEntry("extruder") == extruder_definition.getId()]
-
- if quality_changes_list:
- quality_changes = quality_changes_list[0]
- else:
- quality_changes = global_quality_changes
- if not quality_changes:
- quality_changes = self._empty_quality_changes_container
-
- material_metadata = extruder_stack.material.getMetaData()
-
- if self._new_material_container and self._active_container_stack.getId() == extruder_stack.getId():
- material_metadata = self._new_material_container.getMetaData()
-
- quality = quality_manager.findQualityByQualityType(quality_type, global_machine_definition, [material_metadata])
-
- if not quality:
- # No quality profile found for this quality type.
- quality = self._empty_quality_container
-
- result.append({
- "stack": extruder_stack,
- "quality": quality,
- "quality_changes": quality_changes
- })
-
- # append the global quality changes
- global_quality = quality_manager.findQualityByQualityType(quality_type, global_machine_definition, global_quality = "True")
-
- # if there is not global quality but we're using a single extrusion machine, copy the quality of the first extruder - CURA-4482
- if not global_quality and len(extruder_stacks) == 1:
- global_quality = result[0]["quality"]
-
- # if still no global quality changes are found we set it to empty (not supported)
- if not global_quality:
- global_quality = self._empty_quality_container
-
- result.append({
- "stack": global_container_stack,
- "quality": global_quality,
- "quality_changes": global_quality_changes
- })
-
- return result
-
- def _replaceQualityOrQualityChangesInStack(self, stack: "CuraContainerStack", container: "InstanceContainer", postpone_emit = False):
- # Disconnect the signal handling from the old container.
- container_type = container.getMetaDataEntry("type")
- if container_type == "quality":
- stack.quality.nameChanged.disconnect(self._onQualityNameChanged)
- stack.setQuality(container, postpone_emit = postpone_emit)
- stack.quality.nameChanged.connect(self._onQualityNameChanged)
- elif container_type == "quality_changes" or container_type is None:
- # If the container is an empty container, we need to change the quality_changes.
- # Quality can never be set to empty.
- stack.qualityChanges.nameChanged.disconnect(self._onQualityNameChanged)
- stack.setQualityChanges(container, postpone_emit = postpone_emit)
- stack.qualityChanges.nameChanged.connect(self._onQualityNameChanged)
- self._onQualityNameChanged()
-
@pyqtProperty(str, notify = activeVariantChanged)
def activeVariantName(self) -> str:
if self._active_container_stack:
@@ -1153,15 +607,6 @@ class MachineManager(QObject):
return ""
- @pyqtProperty(str, notify = activeVariantChanged)
- def activeVariantId(self) -> str:
- if self._active_container_stack:
- variant = self._active_container_stack.variant
- if variant:
- return variant.getId()
-
- return ""
-
@pyqtProperty(str, notify = activeVariantChanged)
def activeVariantBuildplateName(self) -> str:
if self._global_container_stack:
@@ -1178,55 +623,14 @@ class MachineManager(QObject):
return ""
- @pyqtProperty(str, notify=globalContainerChanged)
- def activeDefinitionName(self) -> str:
- if self._global_container_stack:
- return self._global_container_stack.definition.getName()
-
- return ""
-
## Get the Definition ID to use to select quality profiles for the currently active machine
# \returns DefinitionID (string) if found, empty string otherwise
- # \sa getQualityDefinitionId
@pyqtProperty(str, notify = globalContainerChanged)
def activeQualityDefinitionId(self) -> str:
if self._global_container_stack:
- return self.getQualityDefinitionId(self._global_container_stack.definition)
+ return getMachineDefinitionIDForQualitySearch(self._global_container_stack.definition)
return ""
- ## Get the Definition ID to use to select quality profiles for machines of the specified definition
- # This is normally the id of the definition itself, but machines can specify a different definition to inherit qualities from
- # \param definition (DefinitionContainer) machine definition
- # \returns DefinitionID (string) if found, empty string otherwise
- def getQualityDefinitionId(self, definition: "DefinitionContainer") -> str:
- return QualityManager.getInstance().getParentMachineDefinition(definition).getId()
-
- ## Get the Variant ID to use to select quality profiles for the currently active variant
- # \returns VariantID (string) if found, empty string otherwise
- # \sa getQualityVariantId
- @pyqtProperty(str, notify = activeVariantChanged)
- def activeQualityVariantId(self) -> str:
- if self._active_container_stack:
- variant = self._active_container_stack.variant
- if variant:
- return self.getQualityVariantId(self._global_container_stack.definition, variant)
- return ""
-
- ## Get the Variant ID to use to select quality profiles for variants of the specified definitions
- # This is normally the id of the variant itself, but machines can specify a different definition
- # to inherit qualities from, which has consequences for the variant to use as well
- # \param definition (DefinitionContainer) machine definition
- # \param variant (InstanceContainer) variant definition
- # \returns VariantID (string) if found, empty string otherwise
- def getQualityVariantId(self, definition: "DefinitionContainer", variant: "InstanceContainer") -> str:
- variant_id = variant.getId()
- definition_id = definition.getId()
- quality_definition_id = self.getQualityDefinitionId(definition)
-
- if definition_id != quality_definition_id:
- variant_id = variant_id.replace(definition_id, quality_definition_id, 1)
- return variant_id
-
## Gets how the active definition calls variants
# Caveat: per-definition-variant-title is currently not translated (though the fallback is)
@pyqtProperty(str, notify = globalContainerChanged)
@@ -1291,6 +695,8 @@ class MachineManager(QObject):
buildplate_compatible = True # It is compatible by default
extruder_stacks = self._global_container_stack.extruders.values()
for stack in extruder_stacks:
+ if not stack.isEnabled:
+ continue
material_container = stack.material
if material_container == self._empty_material_container:
continue
@@ -1348,47 +754,155 @@ class MachineManager(QObject):
if containers:
return containers[0].definition.getId()
- @staticmethod
- def createMachineManager():
- return MachineManager()
+ def getIncompatibleSettingsOnEnabledExtruders(self, container):
+ extruder_count = self._global_container_stack.getProperty("machine_extruder_count", "value")
+ result = []
+ 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
- @deprecated("Use ExtruderStack.material = ... and it won't be necessary", "2.7")
- def _updateMaterialContainer(self, definition: "DefinitionContainer", stack: "ContainerStack", variant_container: Optional["InstanceContainer"] = None, preferred_material_name: Optional[str] = None) -> InstanceContainer:
- if not definition.getMetaDataEntry("has_materials"):
- return self._empty_material_container
+ if not self._global_container_stack.getProperty(setting_key, "type") in ("extruder", "optional_extruder"):
+ continue
- approximate_material_diameter = str(round(stack.getProperty("material_diameter", "value")))
- search_criteria = { "type": "material", "approximate_diameter": approximate_material_diameter }
+ old_value = container.getProperty(setting_key, "value")
+ if int(old_value) >= extruder_count or not self._global_container_stack.extruders[str(old_value)].isEnabled:
+ result.append(setting_key)
+ Logger.log("d", "Reset setting [%s] in [%s] because its old value [%s] is no longer valid", setting_key, container, old_value)
+ return result
- if definition.getMetaDataEntry("has_machine_materials"):
- search_criteria["definition"] = self.getQualityDefinitionId(definition)
+ ## Update extruder number to a valid value when the number of extruders are changed, or when an extruder is changed
+ def correctExtruderSettings(self):
+ for setting_key in self.getIncompatibleSettingsOnEnabledExtruders(self._global_container_stack.userChanges):
+ self._global_container_stack.userChanges.removeInstance(setting_key)
+ add_user_changes = self.getIncompatibleSettingsOnEnabledExtruders(self._global_container_stack.qualityChanges)
+ for setting_key in add_user_changes:
+ # 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,
+ title = catalog.i18nc("@info:title", "Settings updated"))
+ caution_message.show()
- if definition.getMetaDataEntry("has_variants") and variant_container:
- search_criteria["variant"] = self.getQualityVariantId(definition, variant_container)
- else:
- search_criteria["definition"] = "fdmprinter"
+ ## Set the amount of extruders on the active machine (global stack)
+ # \param extruder_count int the number of extruders to set
+ def setActiveMachineExtruderCount(self, extruder_count):
+ extruder_manager = Application.getInstance().getExtruderManager()
- if preferred_material_name:
- search_criteria["name"] = preferred_material_name
- else:
- preferred_material = definition.getMetaDataEntry("preferred_material")
- if preferred_material:
- search_criteria["id"] = preferred_material
+ definition_changes_container = self._global_container_stack.definitionChanges
+ if not self._global_container_stack or definition_changes_container == self._empty_definition_changes_container:
+ return
- containers = ContainerRegistry.getInstance().findInstanceContainers(**search_criteria)
- if containers:
- return containers[0]
+ previous_extruder_count = self._global_container_stack.getProperty("machine_extruder_count", "value")
+ if extruder_count == previous_extruder_count:
+ return
- if "variant" in search_criteria or "id" in search_criteria:
- # If a material by this name can not be found, try a wider set of search criteria
- search_criteria.pop("variant", None)
- search_criteria.pop("id", None)
+ definition_changes_container.setProperty("machine_extruder_count", "value", extruder_count)
- containers = ContainerRegistry.getInstance().findInstanceContainers(**search_criteria)
- if containers:
- return containers[0]
- Logger.log("w", "Unable to find a material container with provided criteria, returning an empty one instead.")
- return self._empty_material_container
+ self.updateDefaultExtruder()
+ self.updateNumberExtrudersEnabled()
+ self.correctExtruderSettings()
+
+ # Check to see if any objects are set to print with an extruder that will no longer exist
+ root_node = Application.getInstance().getController().getScene().getRoot()
+ for node in DepthFirstIterator(root_node):
+ if node.getMeshData():
+ extruder_nr = node.callDecoration("getActiveExtruderPosition")
+
+ if extruder_nr is not None and int(extruder_nr) > extruder_count - 1:
+ node.callDecoration("setActiveExtruder", extruder_manager.getExtruderStack(extruder_count - 1).getId())
+
+ # Make sure one of the extruder stacks is active
+ extruder_manager.setActiveExtruderIndex(0)
+
+ # Move settable_per_extruder values out of the global container
+ # 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 = []
+
+ 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"))
+ global_user_container.removeInstance(setting_key)
+
+ # Signal that the global stack has changed
+ Application.getInstance().globalContainerStackChanged.emit()
+ self.forceUpdateAllSettings()
+
+ @pyqtSlot(int, result = QObject)
+ def getExtruder(self, position: int):
+ extruder = None
+ if self._global_container_stack:
+ extruder = self._global_container_stack.extruders.get(str(position))
+ return extruder
+
+ def updateDefaultExtruder(self):
+ extruder_items = sorted(self._global_container_stack.extruders.items())
+ old_position = self._default_extruder_position
+ new_default_position = "0"
+ for position, extruder in extruder_items:
+ if extruder.isEnabled:
+ new_default_position = position
+ break
+ if new_default_position != old_position:
+ self._default_extruder_position = new_default_position
+ self.extruderChanged.emit()
+
+ def updateNumberExtrudersEnabled(self):
+ definition_changes_container = self._global_container_stack.definitionChanges
+ extruder_count = 0
+ for position, extruder in self._global_container_stack.extruders.items():
+ if extruder.isEnabled:
+ extruder_count += 1
+ definition_changes_container.setProperty("extruders_enabled_count", "value", extruder_count)
+
+ @pyqtProperty(str, notify = extruderChanged)
+ def defaultExtruderPosition(self):
+ return self._default_extruder_position
+
+ ## This will fire the propertiesChanged for all settings so they will be updated in the front-end
+ @pyqtSlot()
+ def forceUpdateAllSettings(self):
+ with postponeSignals(*self._getContainerChangedSignals(), compress = CompressTechnique.CompressPerParameterValue):
+ property_names = ["value", "resolve", "validationState"]
+ for container in [self._global_container_stack] + list(self._global_container_stack.extruders.values()):
+ for setting_key in container.getAllKeys():
+ container.propertiesChanged.emit(setting_key, property_names)
+
+ @pyqtSlot(int, bool)
+ def setExtruderEnabled(self, position: int, enabled) -> None:
+ extruder = self.getExtruder(position)
+ extruder.setEnabled(enabled)
+ self.updateDefaultExtruder()
+ self.updateNumberExtrudersEnabled()
+ self.correctExtruderSettings()
+ # 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
+ self.activeQualityGroupChanged.emit()
+ # update items in SettingExtruder
+ ExtruderManager.getInstance().extrudersChanged.emit(self._global_container_stack.getId())
+ # Make sure the front end reflects changes
+ self.forceUpdateAllSettings()
def _onMachineNameChanged(self):
self.globalContainerChanged.emit()
@@ -1403,3 +917,345 @@ class MachineManager(QObject):
stacks = ExtruderManager.getInstance().getActiveExtruderStacks()
stacks.append(self._global_container_stack)
return [ s.containersChanged for s in stacks ]
+
+ @pyqtSlot(str, str, str)
+ def setSettingForAllExtruders(self, setting_name: str, property_name: str, property_value: str):
+ for key, extruder in self._global_container_stack.extruders.items():
+ container = extruder.userChanges
+ container.setProperty(setting_name, property_name, property_value)
+
+ @pyqtProperty("QVariantList", notify = globalContainerChanged)
+ def currentExtruderPositions(self):
+ if self._global_container_stack is None:
+ return []
+ return sorted(list(self._global_container_stack.extruders.keys()))
+
+ ## Update _current_root_material_id when the current root material was changed.
+ def _onRootMaterialChanged(self):
+ self._current_root_material_id = {}
+
+ 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")
+
+ @pyqtProperty("QVariant", notify = rootMaterialChanged)
+ def currentRootMaterialId(self):
+ return self._current_root_material_id
+
+ ## Return the variant names in the extruder stack(s).
+ ## For the variant in the global stack, use activeVariantBuildplateName
+ @pyqtProperty("QVariant", notify = activeVariantChanged)
+ def activeVariantNames(self):
+ result = {}
+
+ active_stacks = ExtruderManager.getInstance().getActiveExtruderStacks()
+ if active_stacks is not None:
+ for stack in active_stacks:
+ variant_container = stack.variant
+ position = stack.getMetaDataEntry("position")
+ if variant_container and variant_container != self._empty_variant_container:
+ result[position] = variant_container.getName()
+
+ return result
+
+ #
+ # Sets all quality and quality_changes containers to empty_quality and empty_quality_changes containers
+ # for all stacks in the currently active machine.
+ #
+ def _setEmptyQuality(self):
+ 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
+ for extruder in self._global_container_stack.extruders.values():
+ extruder.quality = self._empty_quality_container
+ extruder.qualityChanges = self._empty_quality_changes_container
+
+ self.activeQualityGroupChanged.emit()
+ self.activeQualityChangesGroupChanged.emit()
+
+ def _setQualityGroup(self, quality_group, empty_quality_changes = True):
+ self._current_quality_group = quality_group
+ if empty_quality_changes:
+ self._current_quality_changes_group = None
+
+ # Set quality and quality_changes for the GlobalStack
+ self._global_container_stack.quality = quality_group.node_for_global.getContainer()
+ if empty_quality_changes:
+ self._global_container_stack.qualityChanges = self._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.activeQualityGroupChanged.emit()
+ self.activeQualityChangesGroupChanged.emit()
+
+ def _setQualityChangesGroup(self, quality_changes_group):
+ quality_type = quality_changes_group.quality_type
+ quality_group_dict = self._quality_manager.getQualityGroups(self._global_container_stack)
+ quality_group = quality_group_dict[quality_type]
+
+ quality_changes_container = self._empty_quality_changes_container
+ quality_container = self._empty_quality_changes_container
+ if quality_changes_group.node_for_global:
+ quality_changes_container = quality_changes_group.node_for_global.getContainer()
+ if quality_group.node_for_global:
+ quality_container = quality_group.node_for_global.getContainer()
+
+ self._global_container_stack.quality = quality_container
+ self._global_container_stack.qualityChanges = quality_changes_container
+
+ for position, extruder in self._global_container_stack.extruders.items():
+ quality_changes_node = quality_changes_group.nodes_for_extruders.get(position)
+ quality_node = quality_group.nodes_for_extruders.get(position)
+
+ quality_changes_container = self._empty_quality_changes_container
+ quality_container = self._empty_quality_container
+ if quality_changes_node:
+ quality_changes_container = quality_changes_node.getContainer()
+ if quality_node:
+ quality_container = quality_node.getContainer()
+
+ extruder.quality = quality_container
+ extruder.qualityChanges = quality_changes_container
+
+ self._current_quality_group = quality_group
+ self._current_quality_changes_group = quality_changes_group
+ self.activeQualityGroupChanged.emit()
+ self.activeQualityChangesGroupChanged.emit()
+
+ def _setVariantNode(self, position, container_node):
+ self._global_container_stack.extruders[position].variant = container_node.getContainer()
+ self.activeVariantChanged.emit()
+
+ def _setGlobalVariant(self, container_node):
+ self._global_container_stack.variant = container_node.getContainer()
+
+ def _setMaterial(self, position, container_node = None):
+ if container_node:
+ self._global_container_stack.extruders[position].material = container_node.getContainer()
+ root_material_id = container_node.metadata["base_file"]
+ else:
+ self._global_container_stack.extruders[position].material = self._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]:
+ self._current_root_material_id[position] = root_material_id
+ self.rootMaterialChanged.emit()
+
+ def activeMaterialsCompatible(self):
+ # check material - variant compatibility
+ 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.material.getMetaDataEntry("compatible"):
+ return False
+ return True
+
+ ## Update current quality type and machine after setting material
+ def _updateQualityWithMaterial(self, *args):
+ Logger.log("i", "Updating quality/quality_changes due to material change")
+ current_quality_type = None
+ if self._current_quality_group:
+ current_quality_type = self._current_quality_group.quality_type
+ candidate_quality_groups = self._quality_manager.getQualityGroups(self._global_container_stack)
+ available_quality_types = {qt for qt, g in candidate_quality_groups.items() if g.is_available}
+
+ Logger.log("d", "Current quality type = [%s]", current_quality_type)
+ if not self.activeMaterialsCompatible():
+ Logger.log("i", "Active materials are not compatible, setting all qualities to empty (Not Supported).")
+ self._setEmptyQuality()
+ return
+
+ if not available_quality_types:
+ Logger.log("i", "No available quality types found, setting all qualities to empty (Not Supported).")
+ self._setEmptyQuality()
+ return
+
+ if current_quality_type in available_quality_types:
+ Logger.log("i", "Current available quality type [%s] is available, applying changes.", current_quality_type)
+ self._setQualityGroup(candidate_quality_groups[current_quality_type], empty_quality_changes = False)
+ return
+
+ # The current quality type is not available so we use the preferred quality type if it's available,
+ # otherwise use one of the available quality types.
+ quality_type = sorted(list(available_quality_types))[0]
+ preferred_quality_type = self._global_container_stack.getMetaDataEntry("preferred_quality_type")
+ if preferred_quality_type in available_quality_types:
+ quality_type = preferred_quality_type
+
+ Logger.log("i", "The current quality type [%s] is not available, switching to [%s] instead",
+ current_quality_type, quality_type)
+ self._setQualityGroup(candidate_quality_groups[quality_type], empty_quality_changes = True)
+
+ def _updateMaterialWithVariant(self, position: Optional[str]):
+ if position is None:
+ position_list = list(self._global_container_stack.extruders.keys())
+ else:
+ position_list = [position]
+
+ for position in position_list:
+ extruder = self._global_container_stack.extruders[position]
+
+ current_material_base_name = extruder.material.getMetaDataEntry("base_file")
+ current_variant_name = None
+ if extruder.variant.getId() != self._empty_variant_container.getId():
+ current_variant_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 = self._global_container_stack.getProperty("material_diameter", "value", context)
+ candidate_materials = self._material_manager.getAvailableMaterials(
+ self._global_container_stack.definition.getId(),
+ current_variant_name,
+ material_diameter)
+
+ if not candidate_materials:
+ self._setMaterial(position, container_node = None)
+ continue
+
+ if current_material_base_name in candidate_materials:
+ new_material = candidate_materials[current_material_base_name]
+ self._setMaterial(position, new_material)
+ continue
+
+ # The current material is not available, find the preferred one
+ material_node = self._material_manager.getDefaultMaterial(self._global_container_stack, current_variant_name)
+ if material_node is not None:
+ self._setMaterial(position, material_node)
+
+ ## Given a printer definition name, select the right machine instance. In case it doesn't exist, create a new
+ # instance with the same network key.
+ @pyqtSlot(str)
+ def switchPrinterType(self, machine_name):
+ # Don't switch if the user tries to change to the same type of printer
+ if self.activeMachineDefinitionName == machine_name:
+ return
+ # Get the definition id corresponding to this machine name
+ machine_definition_id = ContainerRegistry.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})
+ # 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)
+ new_machine.addMetaDataEntry("um_network_key", self.activeMachineNetworkKey)
+ new_machine.addMetaDataEntry("connect_group_name", self.activeMachineNetworkGroupName)
+ new_machine.addMetaDataEntry("hidden", False)
+ else:
+ Logger.log("i", "Found a %s with the key %s. Let's use it!", machine_name, self.activeMachineNetworkKey)
+ new_machine.setMetaDataEntry("hidden", False)
+
+ # Set the current printer instance to hidden (the metadata entry must exist)
+ self._global_container_stack.setMetaDataEntry("hidden", True)
+
+ self.setActiveMachine(new_machine.getId())
+
+ @pyqtSlot(QObject)
+ def applyRemoteConfiguration(self, configuration: ConfigurationModel):
+ self.blurSettings.emit()
+ with postponeSignals(*self._getContainerChangedSignals(), compress = CompressTechnique.CompressPerParameterValue):
+ self.switchPrinterType(configuration.printerType)
+ 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, extruder_configuration.hotendID,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 material_container_node:
+ self._setMaterial(position, material_container_node)
+ else:
+ self._global_container_stack.extruders[position].material = self._empty_material_container
+ self._updateMaterialWithVariant(position)
+
+ 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
+ else:
+ self._global_container_stack.variant = self._empty_variant_container
+ self._updateQualityWithMaterial()
+
+ ## 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):
+ machines = ContainerRegistry.getInstance().findContainerStacks(type = "machine")
+ for machine in machines:
+ if machine.getMetaDataEntry(key) == value:
+ machine.setMetaDataEntry(key, new_value)
+
+ @pyqtSlot("QVariant")
+ def setGlobalVariant(self, container_node):
+ self.blurSettings.emit()
+ with postponeSignals(*self._getContainerChangedSignals(), compress = CompressTechnique.CompressPerParameterValue):
+ self._setGlobalVariant(container_node)
+ self._updateMaterialWithVariant(None) # Update all materials
+ self._updateQualityWithMaterial()
+
+ @pyqtSlot(str, "QVariant")
+ def setMaterial(self, position, container_node):
+ position = str(position)
+ self.blurSettings.emit()
+ with postponeSignals(*self._getContainerChangedSignals(), compress = CompressTechnique.CompressPerParameterValue):
+ self._setMaterial(position, container_node)
+ self._updateQualityWithMaterial()
+
+ @pyqtSlot(str, "QVariant")
+ def setVariantGroup(self, position, container_node):
+ position = str(position)
+ self.blurSettings.emit()
+ with postponeSignals(*self._getContainerChangedSignals(), compress = CompressTechnique.CompressPerParameterValue):
+ self._setVariantNode(position, container_node)
+ self._updateMaterialWithVariant(position)
+ self._updateQualityWithMaterial()
+
+ @pyqtSlot(QObject)
+ def setQualityGroup(self, quality_group, no_dialog = False):
+ self.blurSettings.emit()
+ with postponeSignals(*self._getContainerChangedSignals(), compress = CompressTechnique.CompressPerParameterValue):
+ self._setQualityGroup(quality_group)
+
+ # See if we need to show the Discard or Keep changes screen
+ if not no_dialog and self.hasUserSettings and Preferences.getInstance().getValue("cura/active_mode") == 1:
+ self._application.discardOrKeepProfileChanges()
+
+ @pyqtProperty(QObject, fset = setQualityGroup, notify = activeQualityGroupChanged)
+ def activeQualityGroup(self):
+ return self._current_quality_group
+
+ @pyqtSlot(QObject)
+ def setQualityChangesGroup(self, quality_changes_group, no_dialog = False):
+ self.blurSettings.emit()
+ with postponeSignals(*self._getContainerChangedSignals(), compress = CompressTechnique.CompressPerParameterValue):
+ self._setQualityChangesGroup(quality_changes_group)
+
+ # See if we need to show the Discard or Keep changes screen
+ if not no_dialog and self.hasUserSettings and Preferences.getInstance().getValue("cura/active_mode") == 1:
+ self._application.discardOrKeepProfileChanges()
+
+ @pyqtProperty(QObject, fset = setQualityChangesGroup, notify = activeQualityChangesGroupChanged)
+ def activeQualityChangesGroup(self):
+ return self._current_quality_changes_group
+
+ @pyqtProperty(str, notify = activeQualityGroupChanged)
+ def activeQualityOrQualityChangesName(self):
+ name = self._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
+
+ def _updateUponMaterialMetadataChange(self):
+ with postponeSignals(*self._getContainerChangedSignals(), compress = CompressTechnique.CompressPerParameterValue):
+ self._updateMaterialWithVariant(None)
+ self._updateQualityWithMaterial()
diff --git a/cura/Settings/MaterialManager.py b/cura/Settings/MaterialManager.py
deleted file mode 100644
index 80d2723438..0000000000
--- a/cura/Settings/MaterialManager.py
+++ /dev/null
@@ -1,57 +0,0 @@
-# Copyright (c) 2017 Ultimaker B.V.
-# Cura is released under the terms of the LGPLv3 or higher.
-
-from PyQt5.QtCore import QObject, pyqtSlot #To expose data to QML.
-
-from cura.Settings.ContainerManager import ContainerManager
-from UM.Logger import Logger
-from UM.Message import Message #To create a warning message about material diameter.
-from UM.i18n import i18nCatalog #Translated strings.
-
-catalog = i18nCatalog("cura")
-
-## Handles material-related data, processing requests to change them and
-# providing data for the GUI.
-#
-# TODO: Move material-related managing over from the machine manager to here.
-class MaterialManager(QObject):
- ## Creates the global values for the material manager to use.
- def __init__(self, parent = None):
- super().__init__(parent)
-
- #Material diameter changed warning message.
- self._material_diameter_warning_message = Message(catalog.i18nc("@info:status Has a cancel button next to it.",
- "The selected material diameter causes the material to become incompatible with the current printer."), title = catalog.i18nc("@info:title", "Incompatible Material"))
- self._material_diameter_warning_message.addAction("Undo", catalog.i18nc("@action:button", "Undo"), None, catalog.i18nc("@action", "Undo changing the material diameter."))
- self._material_diameter_warning_message.actionTriggered.connect(self._materialWarningMessageAction)
-
- ## Creates an instance of the MaterialManager.
- #
- # This should only be called by PyQt to create the singleton instance of
- # this class.
- @staticmethod
- def createMaterialManager(engine = None, script_engine = None):
- return MaterialManager()
-
- @pyqtSlot(str, str)
- def showMaterialWarningMessage(self, material_id, previous_diameter):
- self._material_diameter_warning_message.previous_diameter = previous_diameter #Make sure that the undo button can properly undo the action.
- self._material_diameter_warning_message.material_id = material_id
- self._material_diameter_warning_message.show()
-
- ## Called when clicking "undo" on the warning dialogue for disappeared
- # materials.
- #
- # This executes the undo action, restoring the material diameter.
- #
- # \param button The identifier of the button that was pressed.
- def _materialWarningMessageAction(self, message, button):
- if button == "Undo":
- container_manager = ContainerManager.getInstance()
- container_manager.setContainerMetaDataEntry(self._material_diameter_warning_message.material_id, "properties/diameter", self._material_diameter_warning_message.previous_diameter)
- approximate_previous_diameter = str(round(float(self._material_diameter_warning_message.previous_diameter)))
- container_manager.setContainerMetaDataEntry(self._material_diameter_warning_message.material_id, "approximate_diameter", approximate_previous_diameter)
- container_manager.setContainerProperty(self._material_diameter_warning_message.material_id, "material_diameter", "value", self._material_diameter_warning_message.previous_diameter);
- message.hide()
- else:
- Logger.log("w", "Unknown button action for material diameter warning message: {action}".format(action = button))
\ No newline at end of file
diff --git a/cura/Settings/MaterialSettingsVisibilityHandler.py b/cura/Settings/MaterialSettingsVisibilityHandler.py
index 5b6050d2c0..ce545f4551 100644
--- a/cura/Settings/MaterialSettingsVisibilityHandler.py
+++ b/cura/Settings/MaterialSettingsVisibilityHandler.py
@@ -3,13 +3,14 @@
import UM.Settings.Models.SettingVisibilityHandler
+
class MaterialSettingsVisibilityHandler(UM.Settings.Models.SettingVisibilityHandler.SettingVisibilityHandler):
def __init__(self, parent = None, *args, **kwargs):
super().__init__(parent = parent, *args, **kwargs)
material_settings = {
"default_material_print_temperature",
- "material_bed_temperature",
+ "default_material_bed_temperature",
"material_standby_temperature",
#"material_flow_temp_graph",
"cool_fan_speed",
diff --git a/cura/Settings/MaterialsModel.py b/cura/Settings/MaterialsModel.py
deleted file mode 100644
index c4b0329336..0000000000
--- a/cura/Settings/MaterialsModel.py
+++ /dev/null
@@ -1,37 +0,0 @@
-# Copyright (c) 2017 Ultimaker B.V.
-# Cura is released under the terms of the LGPLv3 or higher.
-
-from typing import Any, List
-from UM.Settings.ContainerRegistry import ContainerRegistry #To listen for changes to the materials.
-from UM.Settings.Models.InstanceContainersModel import InstanceContainersModel #We're extending this class.
-
-## A model that shows a list of currently valid materials.
-class MaterialsModel(InstanceContainersModel):
- def __init__(self, parent = None):
- super().__init__(parent)
-
- ContainerRegistry.getInstance().containerMetaDataChanged.connect(self._onContainerMetaDataChanged)
-
- ## Called when the metadata of the container was changed.
- #
- # This makes sure that we only update when it was a material that changed.
- #
- # \param container The container whose metadata was changed.
- def _onContainerMetaDataChanged(self, container):
- if container.getMetaDataEntry("type") == "material": #Only need to update if a material was changed.
- self._container_change_timer.start()
-
- def _onContainerChanged(self, container):
- if container.getMetaDataEntry("type", "") == "material":
- super()._onContainerChanged(container)
-
- ## Group brand together
- def _sortKey(self, item) -> List[Any]:
- result = []
- result.append(item["metadata"]["brand"])
- result.append(item["metadata"]["material"])
- result.append(item["metadata"]["name"])
- result.append(item["metadata"]["color_name"])
- result.append(item["metadata"]["id"])
- result.extend(super()._sortKey(item))
- return result
diff --git a/cura/Settings/ProfilesModel.py b/cura/Settings/ProfilesModel.py
deleted file mode 100644
index 77cd407457..0000000000
--- a/cura/Settings/ProfilesModel.py
+++ /dev/null
@@ -1,222 +0,0 @@
-# Copyright (c) 2017 Ultimaker B.V.
-# Cura is released under the terms of the LGPLv3 or higher.
-
-from collections import OrderedDict
-
-from PyQt5.QtCore import Qt
-
-from UM.Application import Application
-from UM.Settings.ContainerRegistry import ContainerRegistry
-from UM.Settings.Models.InstanceContainersModel import InstanceContainersModel
-
-from cura.QualityManager import QualityManager
-from cura.Settings.ExtruderManager import ExtruderManager
-
-from typing import List, TYPE_CHECKING
-
-if TYPE_CHECKING:
- from cura.Settings.ExtruderStack import ExtruderStack
-
-
-## QML Model for listing the current list of valid quality profiles.
-#
-class ProfilesModel(InstanceContainersModel):
- LayerHeightRole = Qt.UserRole + 1001
- LayerHeightWithoutUnitRole = Qt.UserRole + 1002
- AvailableRole = Qt.UserRole + 1003
-
- def __init__(self, parent = None):
- super().__init__(parent)
- self.addRoleName(self.LayerHeightRole, "layer_height")
- self.addRoleName(self.LayerHeightWithoutUnitRole, "layer_height_without_unit")
- self.addRoleName(self.AvailableRole, "available")
-
- Application.getInstance().globalContainerStackChanged.connect(self._update)
- Application.getInstance().getMachineManager().activeVariantChanged.connect(self._update)
- Application.getInstance().getMachineManager().activeStackChanged.connect(self._update)
- Application.getInstance().getMachineManager().activeMaterialChanged.connect(self._update)
-
- self._empty_quality = ContainerRegistry.getInstance().findContainers(id = "empty_quality")[0]
-
- # Factory function, used by QML
- @staticmethod
- def createProfilesModel(engine, js_engine):
- return ProfilesModel.getInstance()
-
- ## Get the singleton instance for this class.
- @classmethod
- def getInstance(cls) -> "ProfilesModel":
- # Note: Explicit use of class name to prevent issues with inheritance.
- if not ProfilesModel.__instance:
- ProfilesModel.__instance = cls()
- return ProfilesModel.__instance
-
- @classmethod
- def hasInstance(cls) -> bool:
- return ProfilesModel.__instance is not None
-
- __instance = None # type: "ProfilesModel"
-
- ## Fetch the list of containers to display.
- #
- # See UM.Settings.Models.InstanceContainersModel._fetchInstanceContainers().
- def _fetchInstanceContainers(self):
- global_container_stack = Application.getInstance().getGlobalContainerStack()
- if global_container_stack is None:
- return {}, {}
- global_stack_definition = global_container_stack.definition
-
- # Get the list of extruders and place the selected extruder at the front of the list.
- extruder_stacks = self._getOrderedExtruderStacksList()
- materials = [extruder.material for extruder in extruder_stacks]
-
- # Fetch the list of usable qualities across all extruders.
- # The actual list of quality profiles come from the first extruder in the extruder list.
- result = QualityManager.getInstance().findAllUsableQualitiesForMachineAndExtruders(global_container_stack, extruder_stacks)
-
- # The usable quality types are set
- quality_type_set = set([x.getMetaDataEntry("quality_type") for x in result])
-
- # Fetch all qualities available for this machine and the materials selected in extruders
- all_qualities = QualityManager.getInstance().findAllQualitiesForMachineAndMaterials(global_stack_definition, materials)
-
- # If in the all qualities there is some of them that are not available due to incompatibility with materials
- # we also add it so that they will appear in the slide quality bar. However in recomputeItems will be marked as
- # not available so they will be shown in gray
- for quality in all_qualities:
- if quality.getMetaDataEntry("quality_type") not in quality_type_set:
- result.append(quality)
-
- if len(result) > 1 and self._empty_quality in result:
- result.remove(self._empty_quality)
-
- return {item.getId(): item for item in result}, {} #Only return true profiles for now, no metadata. The quality manager is not able to get only metadata yet.
-
- ## Re-computes the items in this model, and adds the layer height role.
- def _recomputeItems(self):
- # Some globals that we can re-use.
- global_container_stack = Application.getInstance().getGlobalContainerStack()
- if global_container_stack is None:
- return
-
- extruder_stacks = self._getOrderedExtruderStacksList()
- container_registry = ContainerRegistry.getInstance()
-
- # Get a list of usable/available qualities for this machine and material
- qualities = QualityManager.getInstance().findAllUsableQualitiesForMachineAndExtruders(global_container_stack, extruder_stacks)
-
- unit = global_container_stack.getBottom().getProperty("layer_height", "unit")
- if not unit:
- unit = ""
-
- # group all quality items according to quality_types, so we know which profile suits the currently
- # active machine and material, and later yield the right ones.
- tmp_all_quality_items = OrderedDict()
- for item in super()._recomputeItems():
- profiles = container_registry.findContainersMetadata(id = item["id"])
- if not profiles or "quality_type" not in profiles[0]:
- quality_type = ""
- else:
- quality_type = profiles[0]["quality_type"]
-
- if quality_type not in tmp_all_quality_items:
- tmp_all_quality_items[quality_type] = {"suitable_container": None, "all_containers": []}
-
- tmp_all_quality_items[quality_type]["all_containers"].append(item)
- if tmp_all_quality_items[quality_type]["suitable_container"] is None:
- tmp_all_quality_items[quality_type]["suitable_container"] = item
-
- # reverse the ordering (finest first, coarsest last)
- all_quality_items = OrderedDict()
- for key in reversed(tmp_all_quality_items.keys()):
- all_quality_items[key] = tmp_all_quality_items[key]
-
- # First the suitable containers are set in the model
- containers = []
- for data_item in all_quality_items.values():
- suitable_item = data_item["suitable_container"]
- if suitable_item is not None:
- containers.append(suitable_item)
-
- # Once the suitable containers are collected, the rest of the containers are appended
- for data_item in all_quality_items.values():
- for item in data_item["all_containers"]:
- if item not in containers:
- containers.append(item)
-
- # Now all the containers are set
- for item in containers:
- profile = container_registry.findContainers(id = item["id"])
-
- # When for some reason there is no profile container in the registry
- if not profile:
- self._setItemLayerHeight(item, "", "")
- item["available"] = False
- yield item
- continue
-
- profile = profile[0]
-
- # When there is a profile but it's an empty quality should. It's shown in the list (they are "Not Supported" profiles)
- if profile.getId() == "empty_quality":
- self._setItemLayerHeight(item, "", "")
- item["available"] = True
- yield item
- continue
-
- item["available"] = profile in qualities
-
- # Easy case: This profile defines its own layer height.
- if profile.hasProperty("layer_height", "value"):
- self._setItemLayerHeight(item, profile.getProperty("layer_height", "value"), unit)
- yield item
- continue
-
- machine_manager = Application.getInstance().getMachineManager()
-
- # Quality-changes profile that has no value for layer height. Get the corresponding quality profile and ask that profile.
- quality_type = profile.getMetaDataEntry("quality_type", None)
- if quality_type:
- quality_results = machine_manager.determineQualityAndQualityChangesForQualityType(quality_type)
- for quality_result in quality_results:
- if quality_result["stack"] is global_container_stack:
- quality = quality_result["quality"]
- break
- else:
- # No global container stack in the results:
- if quality_results:
- # Take any of the extruders.
- quality = quality_results[0]["quality"]
- else:
- quality = None
- if quality and quality.hasProperty("layer_height", "value"):
- self._setItemLayerHeight(item, quality.getProperty("layer_height", "value"), unit)
- yield item
- continue
-
- # Quality has no value for layer height either. Get the layer height from somewhere lower in the stack.
- skip_until_container = global_container_stack.material
- if not skip_until_container or skip_until_container == ContainerRegistry.getInstance().getEmptyInstanceContainer(): # No material in stack.
- skip_until_container = global_container_stack.variant
- if not skip_until_container or skip_until_container == ContainerRegistry.getInstance().getEmptyInstanceContainer(): # No variant in stack.
- skip_until_container = global_container_stack.getBottom()
- self._setItemLayerHeight(item, global_container_stack.getRawProperty("layer_height", "value", skip_until_container = skip_until_container.getId()), unit) # Fall through to the currently loaded material.
- yield item
-
- ## Get a list of extruder stacks with the active extruder at the front of the list.
- @staticmethod
- def _getOrderedExtruderStacksList() -> List["ExtruderStack"]:
- extruder_manager = ExtruderManager.getInstance()
- extruder_stacks = extruder_manager.getActiveExtruderStacks()
- active_extruder = extruder_manager.getActiveExtruderStack()
-
- if active_extruder in extruder_stacks:
- extruder_stacks.remove(active_extruder)
- extruder_stacks = [active_extruder] + extruder_stacks
-
- return extruder_stacks
-
- @staticmethod
- def _setItemLayerHeight(item, value, unit):
- item["layer_height"] = str(value) + unit
- item["layer_height_without_unit"] = str(value)
diff --git a/cura/Settings/QualityAndUserProfilesModel.py b/cura/Settings/QualityAndUserProfilesModel.py
deleted file mode 100644
index 645e63acdb..0000000000
--- a/cura/Settings/QualityAndUserProfilesModel.py
+++ /dev/null
@@ -1,54 +0,0 @@
-# Copyright (c) 2016 Ultimaker B.V.
-# Cura is released under the terms of the LGPLv3 or higher.
-from UM.Application import Application
-from UM.Settings.ContainerRegistry import ContainerRegistry
-
-from cura.QualityManager import QualityManager
-from cura.Settings.ProfilesModel import ProfilesModel
-from cura.Settings.ExtruderManager import ExtruderManager
-
-
-## QML Model for listing the current list of valid quality and quality changes profiles.
-#
-class QualityAndUserProfilesModel(ProfilesModel):
- def __init__(self, parent = None):
- super().__init__(parent)
-
- self._empty_quality = ContainerRegistry.getInstance().findInstanceContainers(id = "empty_quality")[0]
-
- ## Fetch the list of containers to display.
- #
- # See UM.Settings.Models.InstanceContainersModel._fetchInstanceContainers().
- def _fetchInstanceContainers(self):
- global_container_stack = Application.getInstance().getGlobalContainerStack()
- if not global_container_stack:
- return {}, {}
-
- # Fetch the list of quality changes.
- quality_manager = QualityManager.getInstance()
- machine_definition = quality_manager.getParentMachineDefinition(global_container_stack.definition)
- quality_changes_list = quality_manager.findAllQualityChangesForMachine(machine_definition)
-
- extruder_manager = ExtruderManager.getInstance()
- active_extruder = extruder_manager.getActiveExtruderStack()
- extruder_stacks = self._getOrderedExtruderStacksList()
-
- # Fetch the list of usable qualities across all extruders.
- # The actual list of quality profiles come from the first extruder in the extruder list.
- quality_list = quality_manager.findAllUsableQualitiesForMachineAndExtruders(global_container_stack, extruder_stacks)
-
- # Filter the quality_change by the list of available quality_types
- quality_type_set = set([x.getMetaDataEntry("quality_type") for x in quality_list])
- # Also show custom profiles based on "Not Supported" quality profile
- quality_type_set.add(self._empty_quality.getMetaDataEntry("quality_type"))
- filtered_quality_changes = {qc.getId(): qc for qc in quality_changes_list if
- qc.getMetaDataEntry("quality_type") in quality_type_set and
- qc.getMetaDataEntry("extruder") is not None and
- (qc.getMetaDataEntry("extruder") == active_extruder.definition.getMetaDataEntry("quality_definition") or
- qc.getMetaDataEntry("extruder") == active_extruder.definition.getId())}
-
- result = filtered_quality_changes
- for q in quality_list:
- if q.getId() != "empty_quality":
- result[q.getId()] = q
- return result, {} #Only return true profiles for now, no metadata. The quality manager is not able to get only metadata yet.
diff --git a/cura/Settings/QualitySettingsModel.py b/cura/Settings/QualitySettingsModel.py
deleted file mode 100644
index fb1aa9a6b2..0000000000
--- a/cura/Settings/QualitySettingsModel.py
+++ /dev/null
@@ -1,249 +0,0 @@
-# Copyright (c) 2017 Ultimaker B.V.
-# Cura is released under the terms of the LGPLv3 or higher.
-
-from PyQt5.QtCore import pyqtProperty, pyqtSignal, Qt
-
-from UM.Logger import Logger
-import UM.Qt
-from UM.Application import Application
-from UM.Settings.ContainerRegistry import ContainerRegistry
-import os
-
-from UM.i18n import i18nCatalog
-
-
-class QualitySettingsModel(UM.Qt.ListModel.ListModel):
- KeyRole = Qt.UserRole + 1
- LabelRole = Qt.UserRole + 2
- UnitRole = Qt.UserRole + 3
- ProfileValueRole = Qt.UserRole + 4
- ProfileValueSourceRole = Qt.UserRole + 5
- UserValueRole = Qt.UserRole + 6
- CategoryRole = Qt.UserRole + 7
-
- def __init__(self, parent = None):
- super().__init__(parent = parent)
-
- self._container_registry = ContainerRegistry.getInstance()
-
- self._extruder_id = None
- self._extruder_definition_id = None
- self._quality_id = None
- self._material_id = None
- self._i18n_catalog = None
-
- self.addRoleName(self.KeyRole, "key")
- self.addRoleName(self.LabelRole, "label")
- self.addRoleName(self.UnitRole, "unit")
- self.addRoleName(self.ProfileValueRole, "profile_value")
- self.addRoleName(self.ProfileValueSourceRole, "profile_value_source")
- self.addRoleName(self.UserValueRole, "user_value")
- self.addRoleName(self.CategoryRole, "category")
-
- self._empty_quality = self._container_registry.findInstanceContainers(id = "empty_quality")[0]
-
- def setExtruderId(self, extruder_id):
- if extruder_id != self._extruder_id:
- self._extruder_id = extruder_id
- self._update()
- self.extruderIdChanged.emit()
-
- extruderIdChanged = pyqtSignal()
- @pyqtProperty(str, fset = setExtruderId, notify = extruderIdChanged)
- def extruderId(self):
- return self._extruder_id
-
- def setExtruderDefinition(self, extruder_definition):
- if extruder_definition != self._extruder_definition_id:
- self._extruder_definition_id = extruder_definition
- self._update()
- self.extruderDefinitionChanged.emit()
-
- extruderDefinitionChanged = pyqtSignal()
- @pyqtProperty(str, fset = setExtruderDefinition, notify = extruderDefinitionChanged)
- def extruderDefinition(self):
- return self._extruder_definition_id
-
- def setQuality(self, quality):
- if quality != self._quality_id:
- self._quality_id = quality
- self._update()
- self.qualityChanged.emit()
-
- qualityChanged = pyqtSignal()
- @pyqtProperty(str, fset = setQuality, notify = qualityChanged)
- def quality(self):
- return self._quality_id
-
- def setMaterial(self, material):
- if material != self._material_id:
- self._material_id = material
- self._update()
- self.materialChanged.emit()
-
- materialChanged = pyqtSignal()
- @pyqtProperty(str, fset = setMaterial, notify = materialChanged)
- def material(self):
- return self._material_id
-
- def _update(self):
- if not self._quality_id:
- return
-
- items = []
-
- definition_container = Application.getInstance().getGlobalContainerStack().getBottom()
-
- containers = self._container_registry.findInstanceContainers(id = self._quality_id)
- if not containers:
- Logger.log("w", "Could not find a quality container with id %s", self._quality_id)
- return
-
- quality_container = None
- quality_changes_container = None
-
- if containers[0].getMetaDataEntry("type") == "quality":
- quality_container = containers[0]
- else:
- quality_changes_container = containers[0]
-
- if quality_changes_container.getMetaDataEntry("quality_type") == self._empty_quality.getMetaDataEntry("quality_type"):
- quality_container = self._empty_quality
- else:
- criteria = {
- "type": "quality",
- "quality_type": quality_changes_container.getMetaDataEntry("quality_type"),
- "definition": quality_changes_container.getDefinition().getId()
- }
-
- quality_container = self._container_registry.findInstanceContainers(**criteria)
- if not quality_container:
- Logger.log("w", "Could not find a quality container matching quality changes %s", quality_changes_container.getId())
- return
-
- quality_container = quality_container[0]
-
- quality_type = quality_container.getMetaDataEntry("quality_type")
-
- if quality_type == "not_supported":
- containers = []
- else:
- definition_id = Application.getInstance().getMachineManager().getQualityDefinitionId(quality_container.getDefinition())
- definition = quality_container.getDefinition()
-
- # Check if the definition container has a translation file.
- definition_suffix = ContainerRegistry.getMimeTypeForContainer(type(definition)).preferredSuffix
- catalog = i18nCatalog(os.path.basename(definition_id + "." + definition_suffix))
- if catalog.hasTranslationLoaded():
- self._i18n_catalog = catalog
-
- for file_name in quality_container.getDefinition().getInheritedFiles():
- catalog = i18nCatalog(os.path.basename(file_name))
- if catalog.hasTranslationLoaded():
- self._i18n_catalog = catalog
-
- criteria = {"type": "quality", "quality_type": quality_type, "definition": definition_id}
-
- if self._material_id and self._material_id != "empty_material":
- criteria["material"] = self._material_id
-
- criteria["extruder"] = self._extruder_id
-
- containers = self._container_registry.findInstanceContainers(**criteria)
- if not containers:
- # Try again, this time without extruder
- new_criteria = criteria.copy()
- new_criteria.pop("extruder")
- containers = self._container_registry.findInstanceContainers(**new_criteria)
-
- if not containers and "material" in criteria:
- # Try again, this time without material
- criteria.pop("material", None)
- containers = self._container_registry.findInstanceContainers(**criteria)
-
- if not containers:
- # Try again, this time without material or extruder
- criteria.pop("extruder") # "material" has already been popped
- containers = self._container_registry.findInstanceContainers(**criteria)
-
- if not containers:
- Logger.log("w", "Could not find any quality containers matching the search criteria %s" % str(criteria))
- return
-
- if quality_changes_container:
- if quality_type == "not_supported":
- criteria = {"type": "quality_changes", "quality_type": quality_type, "name": quality_changes_container.getName()}
- else:
- criteria = {"type": "quality_changes", "quality_type": quality_type, "definition": definition_id, "name": quality_changes_container.getName()}
- if self._extruder_definition_id != "":
- extruder_definitions = self._container_registry.findDefinitionContainers(id = self._extruder_definition_id)
- if extruder_definitions:
- criteria["extruder"] = Application.getInstance().getMachineManager().getQualityDefinitionId(extruder_definitions[0])
- criteria["name"] = quality_changes_container.getName()
- else:
- criteria["extruder"] = None
-
- changes = self._container_registry.findInstanceContainers(**criteria)
- if changes:
- containers.extend(changes)
-
- global_container_stack = Application.getInstance().getGlobalContainerStack()
-
- current_category = ""
- for definition in definition_container.findDefinitions():
- if definition.type == "category":
- current_category = definition.label
- if self._i18n_catalog:
- current_category = self._i18n_catalog.i18nc(definition.key + " label", definition.label)
- continue
-
- profile_value = None
- profile_value_source = ""
- for container in containers:
- new_value = container.getProperty(definition.key, "value")
-
- if new_value is not None:
- profile_value_source = container.getMetaDataEntry("type")
- profile_value = new_value
-
- # Global tab should use resolve (if there is one)
- if not self._extruder_id:
- resolve_value = global_container_stack.getProperty(definition.key, "resolve")
- if resolve_value is not None and profile_value is not None and profile_value_source != "quality_changes":
- profile_value = resolve_value
-
- user_value = None
- if not self._extruder_id:
- user_value = global_container_stack.getTop().getProperty(definition.key, "value")
- else:
- extruder_stack = self._container_registry.findContainerStacks(id = self._extruder_id)
- if extruder_stack:
- user_value = extruder_stack[0].getTop().getProperty(definition.key, "value")
-
- if profile_value is None and user_value is None:
- continue
-
- settable_per_extruder = global_container_stack.getProperty(definition.key, "settable_per_extruder")
- # If a setting is not settable per extruder (global) and we're looking at an extruder tab, don't show this value.
- if self._extruder_id != "" and not settable_per_extruder:
- continue
-
- # If a setting is settable per extruder (not global) and we're looking at global tab, don't show this value.
- if self._extruder_id == "" and settable_per_extruder:
- continue
-
- label = definition.label
- if self._i18n_catalog:
- label = self._i18n_catalog.i18nc(definition.key + " label", label)
-
- items.append({
- "key": definition.key,
- "label": label,
- "unit": definition.unit,
- "profile_value": "" if profile_value is None else str(profile_value), # it is for display only
- "profile_value_source": profile_value_source,
- "user_value": "" if user_value is None else str(user_value),
- "category": current_category
- })
-
- self.setItems(items)
diff --git a/cura/Settings/SettingInheritanceManager.py b/cura/Settings/SettingInheritanceManager.py
index 0d4cd02cdb..e317b20f68 100644
--- a/cura/Settings/SettingInheritanceManager.py
+++ b/cura/Settings/SettingInheritanceManager.py
@@ -1,7 +1,7 @@
# Copyright (c) 2017 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
-from PyQt5.QtCore import QObject, pyqtProperty, pyqtSignal
+from PyQt5.QtCore import QObject, QTimer, pyqtProperty, pyqtSignal
from UM.FlameProfiler import pyqtSlot
from UM.Application import Application
from UM.Logger import Logger
@@ -30,6 +30,11 @@ class SettingInheritanceManager(QObject):
ExtruderManager.getInstance().activeExtruderChanged.connect(self._onActiveExtruderChanged)
self._onActiveExtruderChanged()
+ self._update_timer = QTimer()
+ self._update_timer.setInterval(500)
+ self._update_timer.setSingleShot(True)
+ self._update_timer.timeout.connect(self._update)
+
settingsWithIntheritanceChanged = pyqtSignal()
## Get the keys of all children settings with an override.
@@ -226,9 +231,7 @@ class SettingInheritanceManager(QObject):
self._onActiveExtruderChanged()
def _onContainersChanged(self, container):
- # TODO: Multiple container changes in sequence now cause quite a few recalculations.
- # This isn't that big of an issue, but it could be in the future.
- self._update()
+ self._update_timer.start()
@staticmethod
def createSettingInheritanceManager(engine=None, script_engine=None):
diff --git a/cura/Settings/SettingOverrideDecorator.py b/cura/Settings/SettingOverrideDecorator.py
index b853c06c8e..9054d9d04f 100644
--- a/cura/Settings/SettingOverrideDecorator.py
+++ b/cura/Settings/SettingOverrideDecorator.py
@@ -3,6 +3,7 @@
import copy
+from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator
from UM.Scene.SceneNodeDecorator import SceneNodeDecorator
from UM.Signal import Signal, signalemitter
from UM.Settings.InstanceContainer import InstanceContainer
@@ -61,7 +62,7 @@ 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 = any(bool(self._stack.getProperty(setting, "value")) for setting in self._non_printing_mesh_settings)
+ deep_copy._is_non_printing_mesh = self.evaluateIsNonPrintingMesh()
return deep_copy
@@ -89,10 +90,18 @@ class SettingOverrideDecorator(SceneNodeDecorator):
def isNonPrintingMesh(self):
return self._is_non_printing_mesh
+ def evaluateIsNonPrintingMesh(self):
+ return any(bool(self._stack.getProperty(setting, "value")) for setting in self._non_printing_mesh_settings)
+
def _onSettingChanged(self, instance, property_name): # Reminder: 'property' is a built-in function
- # Trigger slice/need slicing if the value has changed.
- if property_name == "value":
- self._is_non_printing_mesh = any(bool(self._stack.getProperty(setting, "value")) for setting in self._non_printing_mesh_settings)
+ object_has_instance_setting = False
+ for container in self._stack.getContainers():
+ if container.hasProperty(instance, "value"):
+ object_has_instance_setting = True
+ break
+ if property_name == "value" and object_has_instance_setting:
+ # Trigger slice/need slicing if the value has changed.
+ self._is_non_printing_mesh = self.evaluateIsNonPrintingMesh()
Application.getInstance().getBackend().needsSlicing()
Application.getInstance().getBackend().tickle()
diff --git a/cura/Settings/SettingVisibilityPresetsModel.py b/cura/Settings/SettingVisibilityPresetsModel.py
new file mode 100644
index 0000000000..e5a2e24412
--- /dev/null
+++ b/cura/Settings/SettingVisibilityPresetsModel.py
@@ -0,0 +1,136 @@
+# Copyright (c) 2018 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+
+import os
+import urllib
+from configparser import ConfigParser
+
+from PyQt5.QtCore import pyqtProperty, Qt, pyqtSignal, pyqtSlot, QUrl
+
+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
+
+import cura.CuraApplication
+
+
+class SettingVisibilityPresetsModel(ListModel):
+ IdRole = Qt.UserRole + 1
+ NameRole = Qt.UserRole + 2
+ SettingsRole = Qt.UserRole + 4
+
+ def __init__(self, parent = None):
+ super().__init__(parent)
+ self.addRoleName(self.IdRole, "id")
+ self.addRoleName(self.NameRole, "name")
+ self.addRoleName(self.SettingsRole, "settings")
+
+ self._populate()
+
+ self._preferences = Preferences.getInstance()
+ self._preferences.addPreference("cura/active_setting_visibility_preset", "custom") # Preference to store which preset is currently selected
+ self._preferences.addPreference("cura/custom_visible_settings", "") # Preference that stores the "custom" set so it can always be restored (even after a restart)
+ self._preferences.preferenceChanged.connect(self._onPreferencesChanged)
+
+ self._active_preset = self._preferences.getValue("cura/active_setting_visibility_preset")
+ if self.find("id", self._active_preset) < 0:
+ self._active_preset = "custom"
+
+ self.activePresetChanged.emit()
+
+
+ def _populate(self):
+ items = []
+ for item in Resources.getAllResourcesOfType(cura.CuraApplication.CuraApplication.ResourceTypes.SettingVisibilityPreset):
+ try:
+ mime_type = MimeTypeDatabase.getMimeTypeForFile(item)
+ except MimeTypeNotFoundError:
+ Logger.log("e", "Could not determine mime type of file %s", item)
+ continue
+
+ id = urllib.parse.unquote_plus(mime_type.stripExtension(os.path.basename(item)))
+
+ if not os.path.isfile(item):
+ continue
+
+ parser = ConfigParser(allow_no_value=True) # accept options without any value,
+
+ try:
+ parser.read([item])
+
+ if not parser.has_option("general", "name") and not parser.has_option("general", "weight"):
+ continue
+
+ settings = []
+ for section in parser.sections():
+ if section == 'general':
+ continue
+
+ settings.append(section)
+ for option in parser[section].keys():
+ settings.append(option)
+
+ items.append({
+ "id": id,
+ "name": parser["general"]["name"],
+ "weight": parser["general"]["weight"],
+ "settings": settings
+ })
+
+ except Exception as e:
+ Logger.log("e", "Failed to load setting preset %s: %s", file_path, str(e))
+
+
+ items.sort(key = lambda k: (k["weight"], k["id"]))
+ self.setItems(items)
+
+ @pyqtSlot(str)
+ def setActivePreset(self, preset_id):
+ if preset_id != "custom" and self.find("id", preset_id) == -1:
+ Logger.log("w", "Tried to set active preset to unknown id %s", preset_id)
+ return
+
+ if preset_id == "custom" and self._active_preset == "custom":
+ # Copy current visibility set to custom visibility set preference so it can be restored later
+ visibility_string = self._preferences.getValue("general/visible_settings")
+ self._preferences.setValue("cura/custom_visible_settings", visibility_string)
+
+ self._preferences.setValue("cura/active_setting_visibility_preset", preset_id)
+
+ self._active_preset = preset_id
+ self.activePresetChanged.emit()
+
+ activePresetChanged = pyqtSignal()
+
+ @pyqtProperty(str, notify = activePresetChanged)
+ def activePreset(self):
+ return self._active_preset
+
+ def _onPreferencesChanged(self, name):
+ if name != "general/visible_settings":
+ return
+
+ if self._active_preset != "custom":
+ return
+
+ # Copy current visibility set to custom visibility set preference so it can be restored later
+ visibility_string = self._preferences.getValue("general/visible_settings")
+ self._preferences.setValue("cura/custom_visible_settings", visibility_string)
+
+
+ # Factory function, used by QML
+ @staticmethod
+ def createSettingVisibilityPresetsModel(engine, js_engine):
+ return SettingVisibilityPresetsModel.getInstance()
+
+ ## Get the singleton instance for this class.
+ @classmethod
+ def getInstance(cls) -> "SettingVisibilityPresetsModel":
+ # Note: Explicit use of class name to prevent issues with inheritance.
+ if not SettingVisibilityPresetsModel.__instance:
+ SettingVisibilityPresetsModel.__instance = cls()
+ return SettingVisibilityPresetsModel.__instance
+
+ __instance = None # type: "SettingVisibilityPresetsModel"
\ No newline at end of file
diff --git a/cura/Settings/UserProfilesModel.py b/cura/Settings/UserProfilesModel.py
deleted file mode 100644
index 6605f52f8a..0000000000
--- a/cura/Settings/UserProfilesModel.py
+++ /dev/null
@@ -1,85 +0,0 @@
-# Copyright (c) 2017 Ultimaker B.V.
-# Cura is released under the terms of the LGPLv3 or higher.
-
-from UM.Application import Application
-from UM.Settings.ContainerRegistry import ContainerRegistry
-
-from cura.QualityManager import QualityManager
-from cura.Settings.ProfilesModel import ProfilesModel
-from cura.Settings.ExtruderManager import ExtruderManager
-
-## QML Model for listing the current list of valid quality changes profiles.
-#
-class UserProfilesModel(ProfilesModel):
- def __init__(self, parent = None):
- super().__init__(parent)
-
- #Need to connect to the metaDataChanged signal of the active materials.
- self.__current_extruders = []
- self.__current_materials = []
-
- Application.getInstance().getExtruderManager().extrudersChanged.connect(self.__onExtrudersChanged)
- self.__onExtrudersChanged()
- self.__current_materials = [extruder.material for extruder in self.__current_extruders]
- for material in self.__current_materials:
- material.metaDataChanged.connect(self._onContainerChanged)
-
- self._empty_quality = ContainerRegistry.getInstance().findContainers(id = "empty_quality")[0]
-
- ## Fetch the list of containers to display.
- #
- # See UM.Settings.Models.InstanceContainersModel._fetchInstanceContainers().
- def _fetchInstanceContainers(self):
- global_container_stack = Application.getInstance().getGlobalContainerStack()
- if not global_container_stack:
- return {}, {}
-
- # Fetch the list of quality changes.
- quality_manager = QualityManager.getInstance()
- machine_definition = quality_manager.getParentMachineDefinition(global_container_stack.definition)
- quality_changes_list = quality_manager.findAllQualityChangesForMachine(machine_definition)
-
- extruder_manager = ExtruderManager.getInstance()
- active_extruder = extruder_manager.getActiveExtruderStack()
- extruder_stacks = self._getOrderedExtruderStacksList()
-
- # Fetch the list of usable qualities across all extruders.
- # The actual list of quality profiles come from the first extruder in the extruder list.
- quality_list = quality_manager.findAllUsableQualitiesForMachineAndExtruders(global_container_stack, extruder_stacks)
-
- # Filter the quality_change by the list of available quality_types
- quality_type_set = set([x.getMetaDataEntry("quality_type") for x in quality_list])
- quality_type_set.add(self._empty_quality.getMetaDataEntry("quality_type"))
-
- filtered_quality_changes = {qc.getId():qc for qc in quality_changes_list if
- qc.getMetaDataEntry("quality_type") in quality_type_set and
- qc.getMetaDataEntry("extruder") is not None and
- (qc.getMetaDataEntry("extruder") == active_extruder.definition.getMetaDataEntry("quality_definition") or
- qc.getMetaDataEntry("extruder") == active_extruder.definition.getId())}
-
- return filtered_quality_changes, {} #Only return true profiles for now, no metadata. The quality manager is not able to get only metadata yet.
-
- ## Called when a container changed on an extruder stack.
- #
- # If it's the material we need to connect to the metaDataChanged signal of
- # that.
- def __onContainerChanged(self, new_container):
- #Careful not to update when a quality or quality changes profile changed!
- #If you then update you're going to have an infinite recursion because the update may change the container.
- if new_container.getMetaDataEntry("type") == "material":
- for material in self.__current_materials:
- material.metaDataChanged.disconnect(self._onContainerChanged)
- self.__current_materials = [extruder.material for extruder in self.__current_extruders]
- for material in self.__current_materials:
- material.metaDataChanged.connect(self._onContainerChanged)
-
- ## Called when the current set of extruders change.
- #
- # This makes sure that we are listening to the signal for when the
- # materials change.
- def __onExtrudersChanged(self):
- for extruder in self.__current_extruders:
- extruder.containersChanged.disconnect(self.__onContainerChanged)
- self.__current_extruders = Application.getInstance().getExtruderManager().getExtruderStacks()
- for extruder in self.__current_extruders:
- extruder.containersChanged.connect(self.__onContainerChanged)
\ No newline at end of file
diff --git a/cura/Snapshot.py b/cura/Snapshot.py
new file mode 100644
index 0000000000..1f2a24aecd
--- /dev/null
+++ b/cura/Snapshot.py
@@ -0,0 +1,116 @@
+# Copyright (c) 2018 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+import numpy
+
+from PyQt5 import QtCore
+from PyQt5.QtGui import QImage
+
+from cura.PreviewPass import PreviewPass
+from cura.Scene import ConvexHullNode
+
+from UM.Application import Application
+from UM.Math.AxisAlignedBox import AxisAlignedBox
+from UM.Math.Matrix import Matrix
+from UM.Math.Vector import Vector
+from UM.Mesh.MeshData import transformVertices
+from UM.Scene.Camera import Camera
+from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator
+
+
+class Snapshot:
+ @staticmethod
+ def getImageBoundaries(image: QImage):
+ # Look at the resulting image to get a good crop.
+ # Get the pixels as byte array
+ pixel_array = image.bits().asarray(image.byteCount())
+ width, height = image.width(), image.height()
+ # Convert to numpy array, assume it's 32 bit (it should always be)
+ pixels = numpy.frombuffer(pixel_array, dtype=numpy.uint8).reshape([height, width, 4])
+ # Find indices of non zero pixels
+ nonzero_pixels = numpy.nonzero(pixels)
+ min_y, min_x, min_a_ = numpy.amin(nonzero_pixels, axis=1)
+ max_y, max_x, max_a_ = numpy.amax(nonzero_pixels, axis=1)
+
+ return min_x, max_x, min_y, max_y
+
+ ## Return a QImage of the scene
+ # Uses PreviewPass that leaves out some elements
+ # Aspect ratio assumes a square
+ @staticmethod
+ def snapshot(width = 300, height = 300):
+ scene = Application.getInstance().getController().getScene()
+ active_camera = scene.getActiveCamera()
+ render_width, render_height = active_camera.getWindowSize()
+ render_width = int(render_width)
+ render_height = int(render_height)
+ preview_pass = PreviewPass(render_width, render_height)
+
+ root = scene.getRoot()
+ camera = Camera("snapshot", root)
+
+ # determine zoom and look at
+ bbox = None
+ for node in DepthFirstIterator(root):
+ if node.callDecoration("isSliceable") and node.getMeshData() and node.isVisible():
+ 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
+
+ look_at = bbox.center
+ # guessed size so the objects are hopefully big
+ size = max(bbox.width, bbox.height, bbox.depth * 0.5)
+
+ # Looking from this direction (x, y, z) in OGL coordinates
+ 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
+ camera.setPosition(look_at + looking_from_offset)
+ camera.lookAt(look_at)
+
+ satisfied = False
+ size = None
+ fovy = 30
+
+ while not satisfied:
+ if size is not None:
+ satisfied = True # always be satisfied after second try
+ projection_matrix = Matrix()
+ # Somehow the aspect ratio is also influenced in reverse by the screen width/height
+ # So you have to set it to render_width/render_height to get 1
+ projection_matrix.setPerspective(fovy, render_width / render_height, 1, 500)
+ camera.setProjectionMatrix(projection_matrix)
+ preview_pass.setCamera(camera)
+ preview_pass.render()
+ pixel_output = preview_pass.getOutput()
+
+ min_x, max_x, min_y, max_y = Snapshot.getImageBoundaries(pixel_output)
+
+ size = max((max_x - min_x) / render_width, (max_y - min_y) / render_height)
+ if size > 0.5 or satisfied:
+ satisfied = True
+ else:
+ # make it big and allow for some empty space around
+ fovy *= 0.5 # strangely enough this messes up the aspect ratio: fovy *= size * 1.1
+
+ # make it a square
+ if max_x - min_x >= max_y - min_y:
+ # make y bigger
+ min_y, max_y = int((max_y + min_y) / 2 - (max_x - min_x) / 2), int((max_y + min_y) / 2 + (max_x - min_x) / 2)
+ else:
+ # make x bigger
+ min_x, max_x = int((max_x + min_x) / 2 - (max_y - min_y) / 2), int((max_x + min_x) / 2 + (max_y - min_y) / 2)
+ cropped_image = pixel_output.copy(min_x, min_y, max_x - min_x, max_y - min_y)
+
+ # Scale it to the correct size
+ scaled_image = cropped_image.scaled(
+ width, height,
+ aspectRatioMode = QtCore.Qt.IgnoreAspectRatio,
+ transformMode = QtCore.Qt.SmoothTransformation)
+
+ return scaled_image
diff --git a/cura_app.py b/cura_app.py
index 6d1ff6ab6b..6c2d1c2937 100755
--- a/cura_app.py
+++ b/cura_app.py
@@ -16,6 +16,12 @@ 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"]:
@@ -26,12 +32,12 @@ if not known_args["debug"]:
return os.path.expanduser("~/.local/share/cura")
elif Platform.isOSX():
return os.path.expanduser("~/Library/Logs/cura")
-
+
if hasattr(sys, "frozen"):
dirpath = get_cura_dir_path()
os.makedirs(dirpath, exist_ok = True)
- sys.stdout = open(os.path.join(dirpath, "stdout.log"), "w")
- sys.stderr = open(os.path.join(dirpath, "stderr.log"), "w")
+ sys.stdout = open(os.path.join(dirpath, "stdout.log"), "w", encoding = "utf-8")
+ sys.stderr = open(os.path.join(dirpath, "stderr.log"), "w", encoding = "utf-8")
import platform
import faulthandler
@@ -71,8 +77,45 @@ if "PYTHONPATH" in os.environ.keys(): # If PYTHONPATH is u
def exceptHook(hook_type, value, traceback):
from cura.CrashHandler import CrashHandler
- _crash_handler = CrashHandler(hook_type, value, traceback)
- _crash_handler.show()
+ from cura.CuraApplication import CuraApplication
+ has_started = False
+ if CuraApplication.Created:
+ has_started = CuraApplication.getInstance().started
+
+ #
+ # When the exception hook is triggered, the QApplication may not have been initialized yet. In this case, we don't
+ # have an QApplication to handle the event loop, which is required by the Crash Dialog.
+ # The flag "CuraApplication.Created" is set to True when CuraApplication finishes its constructor call.
+ #
+ # Before the "started" flag is set to True, the Qt event loop has not started yet. The event loop is a blocking
+ # call to the QApplication.exec_(). In this case, we need to:
+ # 1. Remove all scheduled events so no more unnecessary events will be processed, such as loading the main dialog,
+ # loading the machine, etc.
+ # 2. Start the Qt event loop with exec_() and show the Crash Dialog.
+ #
+ # If the application has finished its initialization and was running fine, and then something causes a crash,
+ # we run the old routine to show the Crash Dialog.
+ #
+ from PyQt5.Qt import QApplication
+ if CuraApplication.Created:
+ _crash_handler = CrashHandler(hook_type, value, traceback, has_started)
+ if CuraApplication.splash is not None:
+ CuraApplication.splash.close()
+ if not has_started:
+ CuraApplication.getInstance().removePostedEvents(None)
+ _crash_handler.early_crash_dialog.show()
+ sys.exit(CuraApplication.getInstance().exec_())
+ else:
+ _crash_handler.show()
+ else:
+ application = QApplication(sys.argv)
+ application.removePostedEvents(None)
+ _crash_handler = CrashHandler(hook_type, value, traceback, has_started)
+ # This means the QtApplication could be created and so the splash screen. Then Cura closes it
+ if CuraApplication.splash is not None:
+ CuraApplication.splash.close()
+ _crash_handler.early_crash_dialog.show()
+ sys.exit(application.exec_())
if not known_args["debug"]:
sys.excepthook = exceptHook
diff --git a/plugins/3MFReader/ThreeMFReader.py b/plugins/3MFReader/ThreeMFReader.py
index 09ed1e126d..3a1298bdba 100755
--- a/plugins/3MFReader/ThreeMFReader.py
+++ b/plugins/3MFReader/ThreeMFReader.py
@@ -1,29 +1,31 @@
-# Copyright (c) 2015 Ultimaker B.V.
+# Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
import os.path
import zipfile
+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 cura.Settings.SettingOverrideDecorator import SettingOverrideDecorator
-from UM.Application import Application
from cura.Settings.ExtruderManager import ExtruderManager
-from cura.QualityManager import QualityManager
from cura.Scene.CuraSceneNode import CuraSceneNode
from cura.Scene.BuildPlateDecorator import BuildPlateDecorator
from cura.Scene.SliceableObjectDecorator import SliceableObjectDecorator
from cura.Scene.ZOffsetDecorator import ZOffsetDecorator
+from cura.Machines.QualityManager import getMachineDefinitionIDForQualitySearch
MYPY = False
-import Savitar
-import numpy
-
try:
if not MYPY:
import xml.etree.cElementTree as ET
@@ -37,10 +39,6 @@ class ThreeMFReader(MeshReader):
super().__init__()
self._supported_extensions = [".3mf"]
self._root = None
- self._namespaces = {
- "3mf": "http://schemas.microsoft.com/3dmanufacturing/core/2015/02",
- "cura": "http://software.ultimaker.com/xml/cura/3mf/2015/10"
- }
self._base_name = ""
self._unit = None
self._object_count = 0 # Used to name objects as there is no node name yet.
@@ -81,7 +79,7 @@ class ThreeMFReader(MeshReader):
self._object_count += 1
node_name = "Object %s" % self._object_count
- active_build_plate = Application.getInstance().getBuildPlateModel().activeBuildPlate
+ active_build_plate = Application.getInstance().getMultiBuildPlateModel().activeBuildPlate
um_node = CuraSceneNode()
um_node.addDecorator(BuildPlateDecorator(active_build_plate))
@@ -124,8 +122,8 @@ class ThreeMFReader(MeshReader):
um_node.callDecoration("setActiveExtruder", default_stack.getId())
# Get the definition & set it
- definition = QualityManager.getInstance().getParentMachineDefinition(global_container_stack.getBottom())
- um_node.callDecoration("getStack").getTop().setDefinition(definition.getId())
+ definition_id = getMachineDefinitionIDForQualitySearch(global_container_stack.definition)
+ um_node.callDecoration("getStack").getTop().setDefinition(definition_id)
setting_container = um_node.callDecoration("getStack").getTop()
diff --git a/plugins/3MFReader/ThreeMFWorkspaceReader.py b/plugins/3MFReader/ThreeMFWorkspaceReader.py
index 913cea4f26..f5daa77bb0 100755
--- a/plugins/3MFReader/ThreeMFWorkspaceReader.py
+++ b/plugins/3MFReader/ThreeMFWorkspaceReader.py
@@ -1,11 +1,19 @@
# Copyright (c) 2017 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
+from configparser import ConfigParser
+import zipfile
+import os
+import threading
+
+import xml.etree.ElementTree as ET
+
from UM.Workspace.WorkspaceReader import WorkspaceReader
from UM.Application import Application
from UM.Logger import Logger
from UM.i18n import i18nCatalog
+from UM.Signal import postponeSignals, CompressTechnique
from UM.Settings.ContainerStack import ContainerStack
from UM.Settings.DefinitionContainer import DefinitionContainer
from UM.Settings.InstanceContainer import InstanceContainer
@@ -13,28 +21,91 @@ from UM.Settings.ContainerRegistry import ContainerRegistry
from UM.MimeTypeDatabase import MimeTypeDatabase
from UM.Job import Job
from UM.Preferences import Preferences
-from UM.Util import parseBool
-from .WorkspaceDialog import WorkspaceDialog
-
-import xml.etree.ElementTree as ET
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
-from cura.QualityManager import QualityManager
from cura.CuraApplication import CuraApplication
-from configparser import ConfigParser
-import zipfile
-import io
-import configparser
-import os
+from .WorkspaceDialog import WorkspaceDialog
i18n_catalog = i18nCatalog("cura")
+#
+# HACK:
+#
+# In project loading, when override the existing machine is selected, the stacks and containers that are correctly
+# 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.
+#
+# This "@call_on_qt_thread" decorator makes sure that a function will always be called on the Qt thread (blocking).
+# It is applied to the read() function of project loading so it can be guaranteed that only after the project loading
+# process is completely done, everything else that needs to occupy the QT thread will be executed.
+#
+class InterCallObject:
+ def __init__(self):
+ self.finish_event = threading.Event()
+ self.result = None
+
+
+def call_on_qt_thread(func):
+ def _call_on_qt_thread_wrapper(*args, **kwargs):
+ def _handle_call(ico, *args, **kwargs):
+ ico.result = func(*args, **kwargs)
+ ico.finish_event.set()
+ inter_call_object = InterCallObject()
+ new_args = tuple([inter_call_object] + list(args)[:])
+ CuraApplication.getInstance().callLater(_handle_call, *new_args, **kwargs)
+ inter_call_object.finish_event.wait()
+ return inter_call_object.result
+ return _call_on_qt_thread_wrapper
+
+
+class ContainerInfo:
+ def __init__(self, file_name: str, serialized: str, parser: ConfigParser):
+ self.file_name = file_name
+ self.serialized = serialized
+ self.parser = parser
+ self.container = None
+ self.definition_id = None
+
+
+class QualityChangesInfo:
+ def __init__(self):
+ self.name = None
+ self.global_info = None
+ self.extruder_info_dict = {}
+
+
+class MachineInfo:
+ def __init__(self):
+ self.container_id = None
+ self.name = None
+ self.definition_id = None
+ self.quality_type = None
+ self.custom_quality_name = None
+ self.quality_changes_info = None
+ self.variant_info = None
+
+ self.definition_changes_info = None
+ self.user_changes_info = None
+
+ self.extruder_info_dict = {}
+
+
+class ExtruderInfo:
+ def __init__(self):
+ self.position = None
+ self.variant_info = None
+ self.root_material_id = None
+
+ self.definition_changes_info = None
+ self.user_changes_info = None
+
+
## Base implementation for reading 3MF workspace files.
class ThreeMFWorkspaceReader(WorkspaceReader):
def __init__(self):
@@ -65,6 +136,18 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
# In Cura 2.5 and 2.6, the empty profiles used to have those long names
self._old_empty_profile_id_dict = {"empty_%s" % k: "empty" for k in ["material", "variant"]}
+ self._is_same_machine_type = False
+ self._old_new_materials = {}
+ self._materials_to_select = {}
+ self._machine_info = None
+
+ def _clearState(self):
+ self._is_same_machine_type = False
+ self._id_mapping = {}
+ self._old_new_materials = {}
+ self._materials_to_select = {}
+ self._machine_info = None
+
## Get a unique name based on the old_id. This is different from directly calling the registry in that it caches results.
# This has nothing to do with speed, but with getting consistent new naming for instances & objects.
def getNewId(self, old_id):
@@ -90,7 +173,7 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
# The default ContainerStack.deserialize() will connect signals, which is not desired in this case.
# Since we know that the stack files are INI files, so we directly use the ConfigParser to parse them.
serialized = archive.open(file_name).read().decode("utf-8")
- stack_config = ConfigParser()
+ stack_config = ConfigParser(interpolation = None)
stack_config.read_string(serialized)
# sanity check
@@ -116,6 +199,8 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
# \param file_name
# \param show_dialog In case we use preRead() to check if a file is a valid project file, we don't want to show a dialog.
def preRead(self, file_name, show_dialog=True, *args, **kwargs):
+ self._clearState()
+
self._3mf_mesh_reader = Application.getInstance().getMeshFileHandler().getReaderForFile(file_name)
if self._3mf_mesh_reader and self._3mf_mesh_reader.preRead(file_name) == WorkspaceReader.PreReadResult.accepted:
pass
@@ -123,6 +208,7 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
Logger.log("w", "Could not find reader that was able to read the scene data for 3MF workspace")
return WorkspaceReader.PreReadResult.failed
+ self._machine_info = MachineInfo()
machine_type = ""
variant_type_name = i18n_catalog.i18nc("@label", "Nozzle")
@@ -130,11 +216,6 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
archive = zipfile.ZipFile(file_name, "r")
cura_file_names = [name for name in archive.namelist() if name.startswith("Cura/")]
- # A few lists of containers in this project files.
- # When loading the global stack file, it may be associated with those containers, which may or may not be
- # in Cura already, so we need to provide them as alternative search lists.
- instance_container_list = []
-
resolve_strategy_keys = ["machine", "material", "quality_changes"]
self._resolve_strategies = {k: None for k in resolve_strategy_keys}
containers_found_dict = {k: False for k in resolve_strategy_keys}
@@ -142,23 +223,23 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
#
# Read definition containers
#
+ machine_definition_id = None
machine_definition_container_count = 0
extruder_definition_container_count = 0
definition_container_files = [name for name in cura_file_names if name.endswith(self._definition_container_suffix)]
- for each_definition_container_file in definition_container_files:
- container_id = self._stripFileToId(each_definition_container_file)
+ for definition_container_file in definition_container_files:
+ container_id = self._stripFileToId(definition_container_file)
definitions = self._container_registry.findDefinitionContainersMetadata(id = container_id)
+ serialized = archive.open(definition_container_file).read().decode("utf-8")
if not definitions:
- definition_container = DefinitionContainer(container_id)
- definition_container.deserialize(archive.open(each_definition_container_file).read().decode("utf-8"), file_name = each_definition_container_file)
- definition_container = definition_container.getMetaData()
-
+ definition_container = DefinitionContainer.deserializeMetadata(serialized, container_id)[0]
else:
definition_container = definitions[0]
definition_container_type = definition_container.get("type")
if definition_container_type == "machine":
+ machine_definition_id = container_id
machine_type = definition_container["name"]
variant_type_name = definition_container.get("variants_name", variant_type_name)
@@ -167,22 +248,29 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
extruder_definition_container_count += 1
else:
Logger.log("w", "Unknown definition container type %s for %s",
- definition_container_type, each_definition_container_file)
+ definition_container_type, definition_container_file)
Job.yieldThread()
if machine_definition_container_count != 1:
- return WorkspaceReader.PreReadResult.failed #Not a workspace file but ordinary 3MF.
+ return WorkspaceReader.PreReadResult.failed # Not a workspace file but ordinary 3MF.
material_labels = []
material_conflict = False
xml_material_profile = self._getXmlProfileClass()
+ reverse_material_id_dict = {}
if self._material_container_suffix is None:
self._material_container_suffix = ContainerRegistry.getMimeTypeForContainer(xml_material_profile).preferredSuffix
if xml_material_profile:
material_container_files = [name for name in cura_file_names if name.endswith(self._material_container_suffix)]
for material_container_file in material_container_files:
container_id = self._stripFileToId(material_container_file)
- material_labels.append(self._getMaterialLabelFromSerialized(archive.open(material_container_file).read().decode("utf-8")))
+
+ serialized = archive.open(material_container_file).read().decode("utf-8")
+ metadata_list = xml_material_profile.deserializeMetadata(serialized, container_id)
+ reverse_map = {metadata["id"]: container_id for metadata in metadata_list}
+ reverse_material_id_dict.update(reverse_map)
+
+ material_labels.append(self._getMaterialLabelFromSerialized(serialized))
if self._container_registry.findContainersMetadata(id = container_id): #This material already exists.
containers_found_dict["material"] = True
if not self._container_registry.isReadOnly(container_id): # Only non readonly materials can be in conflict
@@ -192,49 +280,52 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
# Check if any quality_changes instance container is in conflict.
instance_container_files = [name for name in cura_file_names if name.endswith(self._instance_container_suffix)]
quality_name = ""
- quality_type = ""
num_settings_overriden_by_quality_changes = 0 # How many settings are changed by the quality changes
- num_settings_overriden_by_definition_changes = 0 # How many settings are changed by the definition changes
num_user_settings = 0
quality_changes_conflict = False
- definition_changes_conflict = False
- for each_instance_container_file in instance_container_files:
- container_id = self._stripFileToId(each_instance_container_file)
- instance_container = InstanceContainer(container_id)
+ self._machine_info.quality_changes_info = QualityChangesInfo()
- # Deserialize InstanceContainer by converting read data from bytes to string
- instance_container.deserialize(archive.open(each_instance_container_file).read().decode("utf-8"),
- file_name = each_instance_container_file)
- instance_container_list.append(instance_container)
+ quality_changes_info_list = []
+ instance_container_info_dict = {} # id -> parser
+ for instance_container_file_name in instance_container_files:
+ container_id = self._stripFileToId(instance_container_file_name)
- container_type = instance_container.getMetaDataEntry("type")
+ serialized = archive.open(instance_container_file_name).read().decode("utf-8")
+ serialized = InstanceContainer._updateSerialized(serialized, instance_container_file_name)
+ parser = ConfigParser(interpolation = None)
+ parser.read_string(serialized)
+ container_info = ContainerInfo(instance_container_file_name, serialized, parser)
+ instance_container_info_dict[container_id] = container_info
+
+ container_type = parser["metadata"]["type"]
if container_type == "quality_changes":
- quality_name = instance_container.getName()
- num_settings_overriden_by_quality_changes += len(instance_container._instances)
+ quality_changes_info_list.append(container_info)
+
+ if not parser.has_option("metadata", "position"):
+ self._machine_info.quality_changes_info.name = parser["general"]["name"]
+ self._machine_info.quality_changes_info.global_info = container_info
+ else:
+ position = parser["metadata"]["position"]
+ self._machine_info.quality_changes_info.extruder_info_dict[position] = container_info
+
+ quality_name = parser["general"]["name"]
+ values = parser["values"] if parser.has_section("values") else dict()
+ num_settings_overriden_by_quality_changes += len(values)
# Check if quality changes already exists.
quality_changes = self._container_registry.findInstanceContainers(id = container_id)
if quality_changes:
containers_found_dict["quality_changes"] = True
# Check if there really is a conflict by comparing the values
+ instance_container = InstanceContainer(container_id)
+ instance_container.deserialize(serialized, file_name = instance_container_file_name)
if quality_changes[0] != instance_container:
quality_changes_conflict = True
- elif container_type == "definition_changes":
- definition_name = instance_container.getName()
- num_settings_overriden_by_definition_changes += len(instance_container._instances)
- # Check if definition changes already exists.
- definition_changes = self._container_registry.findInstanceContainers(id = container_id)
- # Check if there is any difference the loaded settings from the project file and the settings in Cura.
- if definition_changes:
- containers_found_dict["definition_changes"] = True
- # Check if there really is a conflict by comparing the values
- if definition_changes[0] != instance_container:
- definition_changes_conflict = True
elif container_type == "quality":
if not quality_name:
- quality_name = instance_container.getName()
+ quality_name = parser["general"]["name"]
elif container_type == "user":
- num_user_settings += len(instance_container._instances)
+ num_user_settings += len(parser["values"])
elif container_type in self._ignored_instance_container_types:
# Ignore certain instance container types
Logger.log("w", "Ignoring instance container [%s] with type [%s]", container_id, container_type)
@@ -242,6 +333,9 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
Job.yieldThread()
+ if self._machine_info.quality_changes_info.global_info is None:
+ self._machine_info.quality_changes_info = None
+
# Load ContainerStack files and ExtruderStack files
global_stack_file, extruder_stack_files = self._determineGlobalAndExtruderStackFiles(
file_name, cura_file_names)
@@ -250,10 +344,11 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
# - the global stack exists but some/all of the extruder stacks DON'T exist
# - the global stack DOESN'T exist but some/all of the extruder stacks exist
# To simplify this, only check if the global stack exists or not
- container_id = self._stripFileToId(global_stack_file)
+ global_stack_id = self._stripFileToId(global_stack_file)
serialized = archive.open(global_stack_file).read().decode("utf-8")
machine_name = self._getMachineNameFromSerializedStack(serialized)
- stacks = self._container_registry.findContainerStacks(id = container_id)
+ stacks = self._container_registry.findContainerStacks(name = machine_name, type = "machine")
+ self._is_same_machine_type = True
if stacks:
global_stack = stacks[0]
containers_found_dict["machine"] = True
@@ -265,30 +360,79 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
if global_stack.getContainer(index).getId() != container_id:
machine_conflict = True
break
+ self._is_same_machine_type = global_stack.definition.getId() == machine_definition_id
+
+ # Get quality type
+ parser = ConfigParser(interpolation = None)
+ parser.read_string(serialized)
+ quality_container_id = parser["containers"][str(_ContainerIndexes.Quality)]
+ quality_type = instance_container_info_dict[quality_container_id].parser["metadata"]["quality_type"]
+
+ # Get machine info
+ serialized = archive.open(global_stack_file).read().decode("utf-8")
+ serialized = GlobalStack._updateSerialized(serialized, global_stack_file)
+ parser = ConfigParser(interpolation = None)
+ parser.read_string(serialized)
+ definition_changes_id = parser["containers"][str(_ContainerIndexes.DefinitionChanges)]
+ if definition_changes_id not in ("empty", "empty_definition_changes"):
+ self._machine_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"):
+ self._machine_info.user_changes_info = instance_container_info_dict[user_changes_id]
+
+ # Also check variant and material in case it doesn't have extruder stacks
+ if not extruder_stack_files:
+ position = "0"
+
+ extruder_info = ExtruderInfo()
+ extruder_info.position = position
+ variant_id = parser["containers"][str(_ContainerIndexes.Variant)]
+ material_id = parser["containers"][str(_ContainerIndexes.Material)]
+ if variant_id not in ("empty", "empty_variant"):
+ 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
+ self._machine_info.extruder_info_dict[position] = extruder_info
+ else:
+ variant_id = parser["containers"][str(_ContainerIndexes.Variant)]
+ if variant_id not in ("empty", "empty_variant"):
+ self._machine_info.variant_info = instance_container_info_dict[variant_id]
+
Job.yieldThread()
# if the global stack is found, we check if there are conflicts in the extruder stacks
- if containers_found_dict["machine"] and not machine_conflict:
- for extruder_stack_file in extruder_stack_files:
- serialized = archive.open(extruder_stack_file).read().decode("utf-8")
- parser = configparser.ConfigParser()
- parser.read_string(serialized)
+ for extruder_stack_file in extruder_stack_files:
+ serialized = archive.open(extruder_stack_file).read().decode("utf-8")
+ serialized = ExtruderStack._updateSerialized(serialized, extruder_stack_file)
+ parser = ConfigParser(interpolation = None)
+ parser.read_string(serialized)
- # The check should be done for the extruder stack that's associated with the existing global stack,
- # and those extruder stacks may have different IDs.
- # So we check according to the positions
+ # The check should be done for the extruder stack that's associated with the existing global stack,
+ # and those extruder stacks may have different IDs.
+ # So we check according to the positions
+ position = parser["metadata"]["position"]
+ variant_id = parser["containers"][str(_ContainerIndexes.Variant)]
+ material_id = parser["containers"][str(_ContainerIndexes.Material)]
- position = str(parser["metadata"]["position"])
+ extruder_info = ExtruderInfo()
+ extruder_info.position = position
+ if variant_id not in ("empty", "empty_variant"):
+ extruder_info.variant_info = instance_container_info_dict[variant_id]
+ if material_id not in ("empty", "empty_material"):
+ root_material_id = reverse_material_id_dict[material_id]
+ extruder_info.root_material_id = root_material_id
+ definition_changes_id = parser["containers"][str(_ContainerIndexes.DefinitionChanges)]
+ if definition_changes_id not in ("empty", "empty_definition_changes"):
+ extruder_info.definition_changes_info = instance_container_info_dict[definition_changes_id]
+ user_changes_id = parser["containers"][str(_ContainerIndexes.UserChanges)]
+ if user_changes_id not in ("empty", "empty_user_changes"):
+ extruder_info.user_changes_info = instance_container_info_dict[user_changes_id]
+ self._machine_info.extruder_info_dict[position] = extruder_info
+
+ if not machine_conflict and containers_found_dict["machine"]:
if position not in global_stack.extruders:
- # The extruder position defined in the project doesn't exist in this global stack.
- # We can say that it is a machine conflict, but it is very hard to override the machine in this
- # case because we need to override the existing extruders and add the non-existing extruders.
- #
- # HACK:
- # To make this simple, we simply say that there is no machine conflict and create a new machine
- # by default.
- machine_conflict = False
- break
+ continue
existing_extruder_stack = global_stack.extruders[position]
# check if there are any changes at all in any of the container stacks.
@@ -329,10 +473,18 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
extruders = num_extruders * [""]
+ self._machine_info.container_id = global_stack_id
+ self._machine_info.name = machine_name
+ self._machine_info.definition_id = machine_definition_id
+ self._machine_info.quality_type = quality_type
+ self._machine_info.custom_quality_name = quality_name
+
+ if machine_conflict and not self._is_same_machine_type:
+ machine_conflict = False
+
# Show the dialog, informing the user what is about to happen.
self._dialog.setMachineConflict(machine_conflict)
self._dialog.setQualityChangesConflict(quality_changes_conflict)
- self._dialog.setDefinitionChangesConflict(definition_changes_conflict)
self._dialog.setMaterialConflict(material_conflict)
self._dialog.setHasVisibleSettingsField(has_visible_settings_string)
self._dialog.setNumVisibleSettings(num_visible_settings)
@@ -375,7 +527,7 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
## Overrides an ExtruderStack in the given GlobalStack and returns the new ExtruderStack.
def _overrideExtruderStack(self, global_stack, extruder_file_content, extruder_stack_file):
# Get extruder position first
- extruder_config = configparser.ConfigParser()
+ extruder_config = ConfigParser(interpolation = None)
extruder_config.read_string(extruder_file_content)
if not extruder_config.has_option("metadata", "position"):
msg = "Could not find 'metadata/position' in extruder stack file"
@@ -401,7 +553,29 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
# containing global.cfg / extruder.cfg
#
# \param file_name
+ @call_on_qt_thread
def read(self, file_name):
+ container_registry = ContainerRegistry.getInstance()
+ signals = [container_registry.containerAdded,
+ container_registry.containerRemoved,
+ container_registry.containerMetaDataChanged]
+ #
+ # We now have different managers updating their lookup tables upon container changes. It is critical to make
+ # sure that the managers have a complete set of data when they update.
+ #
+ # In project loading, lots of the container-related signals are loosely emitted, which can create timing gaps
+ # for incomplete data update or other kinds of issues to happen.
+ #
+ # To avoid this, we postpone all signals so they don't get emitted immediately. But, please also be aware that,
+ # because of this, do not expect to have the latest data in the lookup tables in project loading.
+ #
+ with postponeSignals(*signals, compress = CompressTechnique.NoCompression):
+ return self._read(file_name)
+
+ def _read(self, file_name):
+ application = CuraApplication.getInstance()
+ material_manager = application.getMaterialManager()
+
archive = zipfile.ZipFile(file_name, "r")
cura_file_names = [name for name in archive.namelist() if name.startswith("Cura/")]
@@ -420,6 +594,7 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
Logger.log("w", "Workspace did not contain visible settings. Leaving visibility unchanged")
else:
global_preferences.setValue("general/visible_settings", visible_settings)
+ global_preferences.setValue("cura/active_setting_visibility_preset", "custom")
categories_expanded = temp_preferences.getValue("cura/categories_expanded")
if categories_expanded is None:
@@ -427,52 +602,24 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
else:
global_preferences.setValue("cura/categories_expanded", categories_expanded)
- Application.getInstance().expandedCategoriesChanged.emit() # Notify the GUI of the change
+ application.expandedCategoriesChanged.emit() # Notify the GUI of the change
- self._id_mapping = {}
+ # If a machine with the same name is of a different type, always create a new one.
+ if not self._is_same_machine_type or self._resolve_strategies["machine"] != "override":
+ # We need to create a new machine
+ machine_name = self._container_registry.uniqueName(self._machine_info.name)
- # We don't add containers right away, but wait right until right before the stack serialization.
- # We do this so that if something goes wrong, it's easier to clean up.
- containers_to_add = []
+ global_stack = CuraStackBuilder.createMachine(machine_name, self._machine_info.definition_id)
+ extruder_stack_dict = global_stack.extruders
- global_stack_file, extruder_stack_files = self._determineGlobalAndExtruderStackFiles(file_name, cura_file_names)
+ self._container_registry.addContainer(global_stack)
+ else:
+ # Find the machine
+ global_stack = self._container_registry.findContainerStacks(name = self._machine_info.name, type = "machine")[0]
+ extruder_stacks = self._container_registry.findContainerStacks(machine = global_stack.getId(),
+ type = "extruder_train")
+ extruder_stack_dict = {stack.getMetaDataEntry("position"): stack for stack in extruder_stacks}
- global_stack = None
- extruder_stacks = []
- extruder_stacks_added = []
- container_stacks_added = []
- machine_extruder_count = None
-
- containers_added = []
-
- global_stack_id_original = self._stripFileToId(global_stack_file)
- global_stack_id_new = global_stack_id_original
- global_stack_name_original = self._getMachineNameFromSerializedStack(archive.open(global_stack_file).read().decode("utf-8"))
- global_stack_name_new = global_stack_name_original
- global_stack_need_rename = False
-
- extruder_stack_id_map = {} # new and old ExtruderStack IDs map
- if self._resolve_strategies["machine"] == "new":
- # We need a new id if the id already exists
- if self._container_registry.findContainerStacksMetadata(id = global_stack_id_original):
- global_stack_id_new = self.getNewId(global_stack_id_original)
- global_stack_need_rename = True
-
- if self._container_registry.findContainerStacksMetadata(name = global_stack_id_original):
- global_stack_name_new = self._container_registry.uniqueName(global_stack_name_original)
-
- for each_extruder_stack_file in extruder_stack_files:
- old_container_id = self._stripFileToId(each_extruder_stack_file)
- new_container_id = old_container_id
- if self._container_registry.findContainerStacksMetadata(id = old_container_id):
- # get a new name for this extruder
- new_container_id = self.getNewId(old_container_id)
-
- extruder_stack_id_map[old_container_id] = new_container_id
-
- # TODO: For the moment we use pretty naive existence checking. If the ID is the same, we assume in quite a few
- # TODO: cases that the container loaded is the same (most notable in materials & definitions).
- # TODO: It might be possible that we need to add smarter checking in the future.
Logger.log("d", "Workspace loading is checking definitions...")
# Get all the definition files & check if they exist. If not, add them.
definition_container_files = [name for name in cura_file_names if name.endswith(self._definition_container_suffix)]
@@ -487,7 +634,6 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
Job.yieldThread()
Logger.log("d", "Workspace loading is checking materials...")
- material_containers = []
# Get all the material files and check if they exist. If not, add them.
xml_material_profile = self._getXmlProfileClass()
if self._material_container_suffix is None:
@@ -495,520 +641,57 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
if xml_material_profile:
material_container_files = [name for name in cura_file_names if name.endswith(self._material_container_suffix)]
for material_container_file in material_container_files:
+ to_deserialize_material = False
container_id = self._stripFileToId(material_container_file)
+ need_new_name = False
materials = self._container_registry.findInstanceContainers(id = container_id)
if not materials:
- material_container = xml_material_profile(container_id)
- material_container.deserialize(archive.open(material_container_file).read().decode("utf-8"),
- file_name = material_container_file)
- containers_to_add.append(material_container)
+ # No material found, deserialize this material later and add it
+ to_deserialize_material = True
else:
material_container = materials[0]
- if not self._container_registry.isReadOnly(container_id): # Only create new materials if they are not read only.
+ old_material_root_id = material_container.getMetaDataEntry("base_file")
+ if not self._container_registry.isReadOnly(old_material_root_id): # Only create new materials if they are not read only.
+ to_deserialize_material = True
+
if self._resolve_strategies["material"] == "override":
- material_container.deserialize(archive.open(material_container_file).read().decode("utf-8"),
- file_name = material_container_file)
+ # Remove the old materials and then deserialize the one from the project
+ root_material_id = material_container.getMetaDataEntry("base_file")
+ material_manager.removeMaterialByRootId(root_material_id)
elif self._resolve_strategies["material"] == "new":
# Note that we *must* deserialize it with a new ID, as multiple containers will be
# auto created & added.
- material_container = xml_material_profile(self.getNewId(container_id))
- material_container.deserialize(archive.open(material_container_file).read().decode("utf-8"),
- file_name = material_container_file)
- containers_to_add.append(material_container)
+ container_id = self.getNewId(container_id)
+ self._old_new_materials[old_material_root_id] = container_id
+ need_new_name = True
- material_containers.append(material_container)
+ if to_deserialize_material:
+ material_container = xml_material_profile(container_id)
+ material_container.deserialize(archive.open(material_container_file).read().decode("utf-8"),
+ file_name = container_id + "." + self._material_container_suffix)
+ if need_new_name:
+ new_name = ContainerRegistry.getInstance().uniqueName(material_container.getName())
+ material_container.setName(new_name)
+ material_container.setDirty(True)
+ self._container_registry.addContainer(material_container)
Job.yieldThread()
- Logger.log("d", "Workspace loading is checking instance containers...")
- # Get quality_changes and user profiles saved in the workspace
- instance_container_files = [name for name in cura_file_names if name.endswith(self._instance_container_suffix)]
- user_instance_containers = []
- quality_and_definition_changes_instance_containers = []
- for instance_container_file in instance_container_files:
- container_id = self._stripFileToId(instance_container_file)
- serialized = archive.open(instance_container_file).read().decode("utf-8")
+ # Handle quality changes if any
+ self._processQualityChanges(global_stack)
- # HACK! we ignore "quality" and "variant" instance containers!
- parser = configparser.ConfigParser()
- parser.read_string(serialized)
- if not parser.has_option("metadata", "type"):
- Logger.log("w", "Cannot find metadata/type in %s, ignoring it", instance_container_file)
- continue
- if parser.get("metadata", "type") in self._ignored_instance_container_types:
- continue
-
- instance_container = InstanceContainer(container_id)
-
- # Deserialize InstanceContainer by converting read data from bytes to string
- instance_container.deserialize(serialized, file_name = instance_container_file)
- container_type = instance_container.getMetaDataEntry("type")
- Job.yieldThread()
-
- #
- # IMPORTANT:
- # If an instance container (or maybe other type of container) exists, and user chooses "Create New",
- # we need to rename this container and all references to it, and changing those references are VERY
- # HARD.
- #
- if container_type in self._ignored_instance_container_types:
- # Ignore certain instance container types
- Logger.log("w", "Ignoring instance container [%s] with type [%s]", container_id, container_type)
- continue
- elif container_type == "user":
- # Check if quality changes already exists.
- user_containers = self._container_registry.findInstanceContainers(id = container_id)
- if not user_containers:
- containers_to_add.append(instance_container)
- else:
- if self._resolve_strategies["machine"] == "override" or self._resolve_strategies["machine"] is None:
- instance_container = user_containers[0]
- instance_container.deserialize(archive.open(instance_container_file).read().decode("utf-8"),
- file_name = instance_container_file)
- instance_container.setDirty(True)
- elif self._resolve_strategies["machine"] == "new":
- # The machine is going to get a spiffy new name, so ensure that the id's of user settings match.
- old_extruder_id = instance_container.getMetaDataEntry("extruder", None)
- if old_extruder_id:
- new_extruder_id = extruder_stack_id_map[old_extruder_id]
- new_id = new_extruder_id + "_current_settings"
- instance_container.setMetaDataEntry("id", new_id)
- instance_container.setName(new_id)
- instance_container.setMetaDataEntry("extruder", new_extruder_id)
- containers_to_add.append(instance_container)
-
- machine_id = instance_container.getMetaDataEntry("machine", None)
- if machine_id:
- new_machine_id = self.getNewId(machine_id)
- new_id = new_machine_id + "_current_settings"
- instance_container.setMetaDataEntry("id", new_id)
- instance_container.setName(new_id)
- instance_container.setMetaDataEntry("machine", new_machine_id)
- containers_to_add.append(instance_container)
- user_instance_containers.append(instance_container)
- elif container_type in ("quality_changes", "definition_changes"):
- # Check if quality changes already exists.
- changes_containers = self._container_registry.findInstanceContainers(id = container_id)
- if not changes_containers:
- # no existing containers with the same ID, so we can safely add the new one
- containers_to_add.append(instance_container)
- else:
- # we have found existing container with the same ID, so we need to resolve according to the
- # selected strategy.
- if self._resolve_strategies[container_type] == "override":
- instance_container = changes_containers[0]
- instance_container.deserialize(archive.open(instance_container_file).read().decode("utf-8"),
- file_name = instance_container_file)
- instance_container.setDirty(True)
-
- elif self._resolve_strategies[container_type] == "new":
- # TODO: how should we handle the case "new" for quality_changes and definition_changes?
-
- instance_container.setName(self._container_registry.uniqueName(instance_container.getName()))
- new_changes_container_id = self.getNewId(instance_container.getId())
- instance_container.setMetaDataEntry("id", new_changes_container_id)
-
- # TODO: we don't know the following is correct or not, need to verify
- # AND REFACTOR!!!
- if self._resolve_strategies["machine"] == "new":
- # The machine is going to get a spiffy new name, so ensure that the id's of user settings match.
- old_extruder_id = instance_container.getMetaDataEntry("extruder", None)
- # Note that in case of a quality_changes extruder means the definition id of the extruder stack
- # For the user settings, it means the actual extruder stack id it's assigned to.
- if old_extruder_id and old_extruder_id in extruder_stack_id_map:
- new_extruder_id = extruder_stack_id_map[old_extruder_id]
- instance_container.setMetaDataEntry("extruder", new_extruder_id)
-
- machine_id = instance_container.getMetaDataEntry("machine", None)
- if machine_id:
- new_machine_id = self.getNewId(machine_id)
- instance_container.setMetaDataEntry("machine", new_machine_id)
-
- containers_to_add.append(instance_container)
-
- elif self._resolve_strategies[container_type] is None:
- # The ID already exists, but nothing in the values changed, so do nothing.
- pass
- quality_and_definition_changes_instance_containers.append(instance_container)
-
- if container_type == "definition_changes":
- definition_changes_extruder_count = instance_container.getProperty("machine_extruder_count", "value")
- if definition_changes_extruder_count is not None:
- machine_extruder_count = definition_changes_extruder_count
-
- else:
- existing_container = self._container_registry.findInstanceContainersMetadata(id = container_id)
- if not existing_container:
- containers_to_add.append(instance_container)
- if global_stack_need_rename:
- if instance_container.getMetaDataEntry("machine"):
- instance_container.setMetaDataEntry("machine", global_stack_id_new)
-
- # Add all the containers right before we try to add / serialize the stack
- for container in containers_to_add:
- self._container_registry.addContainer(container)
- container.setDirty(True)
- containers_added.append(container)
-
- # Get the stack(s) saved in the workspace.
- Logger.log("d", "Workspace loading is checking stacks containers...")
-
- # load global stack file
- try:
- stack = None
-
- if self._resolve_strategies["machine"] == "override":
- container_stacks = self._container_registry.findContainerStacks(id = global_stack_id_original)
- stack = container_stacks[0]
-
- # HACK
- # There is a machine, check if it has authentication data. If so, keep that data.
- network_authentication_id = stack.getMetaDataEntry("network_authentication_id")
- network_authentication_key = stack.getMetaDataEntry("network_authentication_key")
- stack.deserialize(archive.open(global_stack_file).read().decode("utf-8"), file_name = global_stack_file)
- if network_authentication_id:
- stack.addMetaDataEntry("network_authentication_id", network_authentication_id)
- if network_authentication_key:
- stack.addMetaDataEntry("network_authentication_key", network_authentication_key)
-
- elif self._resolve_strategies["machine"] == "new":
- # create a new global stack
- stack = GlobalStack(global_stack_id_new)
- # Deserialize stack by converting read data from bytes to string
- stack.deserialize(archive.open(global_stack_file).read().decode("utf-8"),
- file_name = global_stack_file)
-
- # Ensure a unique ID and name
- stack.setMetaDataEntry("id", global_stack_id_new)
-
- # Only machines need a new name, stacks may be non-unique
- stack.setName(global_stack_name_new)
-
- container_stacks_added.append(stack)
- self._container_registry.addContainer(stack)
- containers_added.append(stack)
- else:
- Logger.log("e", "Resolve strategy of %s for machine is not supported", self._resolve_strategies["machine"])
-
- # Create a new definition_changes container if it was empty
- if stack.definitionChanges == self._container_registry.getEmptyInstanceContainer():
- stack.setDefinitionChanges(CuraStackBuilder.createDefinitionChangesContainer(stack, stack.getId() + "_settings"))
- global_stack = stack
- Job.yieldThread()
- except:
- Logger.logException("w", "We failed to serialize the stack. Trying to clean up.")
- # Something went really wrong. Try to remove any data that we added.
- for container in containers_added:
- self._container_registry.removeContainer(container.getId())
- return
-
- # load extruder stack files
- try:
- for extruder_stack_file in extruder_stack_files:
- container_id = self._stripFileToId(extruder_stack_file)
- extruder_file_content = archive.open(extruder_stack_file, "r").read().decode("utf-8")
-
- if self._resolve_strategies["machine"] == "override":
- # deserialize new extruder stack over the current ones (if any)
- stack = self._overrideExtruderStack(global_stack, extruder_file_content, extruder_stack_file)
- if stack is None:
- continue
-
- elif self._resolve_strategies["machine"] == "new":
- new_id = extruder_stack_id_map[container_id]
- stack = ExtruderStack(new_id)
-
- # HACK: the global stack can have a new name, so we need to make sure that this extruder stack
- # references to the new name instead of the old one. Normally, this can be done after
- # deserialize() by setting the metadata, but in the case of ExtruderStack, deserialize()
- # also does addExtruder() to its machine stack, so we have to make sure that it's pointing
- # to the right machine BEFORE deserialization.
- extruder_config = configparser.ConfigParser()
- extruder_config.read_string(extruder_file_content)
- extruder_config.set("metadata", "machine", global_stack_id_new)
- tmp_string_io = io.StringIO()
- extruder_config.write(tmp_string_io)
- extruder_file_content = tmp_string_io.getvalue()
-
- stack.deserialize(extruder_file_content, file_name = extruder_stack_file)
-
- # Ensure a unique ID and name
- stack.setMetaDataEntry("id", new_id)
-
- self._container_registry.addContainer(stack)
- extruder_stacks_added.append(stack)
- containers_added.append(stack)
- else:
- Logger.log("w", "Unknown resolve strategy: %s", self._resolve_strategies["machine"])
-
- # Create a new definition_changes container if it was empty
- if stack.definitionChanges == self._container_registry.getEmptyInstanceContainer():
- stack.setDefinitionChanges(CuraStackBuilder.createDefinitionChangesContainer(stack, stack.getId() + "_settings"))
-
- if stack.getMetaDataEntry("type") == "extruder_train":
- extruder_stacks.append(stack)
-
- # If not extruder stacks were saved in the project file (pre 3.1) create one manually
- # We re-use the container registry's addExtruderStackForSingleExtrusionMachine method for this
- if not extruder_stacks:
- if self._resolve_strategies["machine"] == "new":
- stack = self._container_registry.addExtruderStackForSingleExtrusionMachine(global_stack, "fdmextruder")
- else:
- stack = global_stack.extruders.get("0")
- if not stack:
- # this should not happen
- Logger.log("e", "Cannot find any extruder in an existing global stack [%s].", global_stack.getId())
- if stack:
- if global_stack.quality.getId() in ("empty", "empty_quality"):
- stack.quality = empty_quality_container
- if self._resolve_strategies["machine"] == "override":
- # in case the extruder is newly created (for a single-extrusion machine), we need to override
- # the existing extruder stack.
- existing_extruder_stack = global_stack.extruders[stack.getMetaDataEntry("position")]
- for idx in range(len(_ContainerIndexes.IndexTypeMap)):
- existing_extruder_stack.replaceContainer(idx, stack._containers[idx], postpone_emit = True)
- extruder_stacks.append(existing_extruder_stack)
- else:
- extruder_stacks.append(stack)
-
- except:
- Logger.logException("w", "We failed to serialize the stack. Trying to clean up.")
- # Something went really wrong. Try to remove any data that we added.
- for container in containers_added:
- self._container_registry.removeContainer(container.getId())
- return
-
-
- # Check quality profiles to make sure that if one stack has the "not supported" quality profile,
- # all others should have the same.
- #
- # This block code tries to fix the following problems in Cura 3.0 and earlier:
- # 1. The upgrade script can rename all "Not Supported" quality profiles to "empty_quality", but it cannot fix
- # the problem that the global stack the extruder stacks may have different quality profiles. The code
- # below loops over all stacks and make sure that if there is one stack with "Not Supported" profile, the
- # rest should also use the "Not Supported" profile.
- # 2. In earlier versions (at least 2.7 and 3.0), a wrong quality profile could be assigned to a stack. For
- # example, a UM3 can have a BB 0.8 variant with "aa04_pla_fast" quality profile enabled. To fix this,
- # in the code below we also check the actual available quality profiles for the machine.
- #
- has_not_supported = False
- for stack in [global_stack] + extruder_stacks:
- if stack.quality.getId() in ("empty", "empty_quality"):
- has_not_supported = True
- break
-
- # We filter out extruder stacks that are not actually used, for example the UM3 and custom FDM printer extruder count setting.
- extruder_stacks_in_use = extruder_stacks
- if machine_extruder_count is not None:
- extruder_stacks_in_use = extruder_stacks[:machine_extruder_count]
-
- available_quality = QualityManager.getInstance().findAllUsableQualitiesForMachineAndExtruders(global_stack,
- extruder_stacks_in_use)
- if not has_not_supported:
- has_not_supported = not available_quality
-
- quality_has_been_changed = False
-
- if has_not_supported:
- empty_quality_container = self._container_registry.findInstanceContainers(id = "empty_quality")[0]
- for stack in [global_stack] + extruder_stacks_in_use:
- stack.replaceContainer(_ContainerIndexes.Quality, empty_quality_container)
- empty_quality_changes_container = self._container_registry.findInstanceContainers(id = "empty_quality_changes")[0]
- for stack in [global_stack] + extruder_stacks_in_use:
- stack.replaceContainer(_ContainerIndexes.QualityChanges, empty_quality_changes_container)
- quality_has_been_changed = True
-
- else:
- empty_quality_changes_container = self._container_registry.findInstanceContainers(id="empty_quality_changes")[0]
-
- # The machine in the project has non-empty quality and there are usable qualities for this machine.
- # We need to check if the current quality_type is still usable for this machine, if not, then the quality
- # will be reset to the "preferred quality" if present, otherwise "normal".
- available_quality_types = [q.getMetaDataEntry("quality_type") for q in available_quality]
-
- if global_stack.quality.getMetaDataEntry("quality_type") not in available_quality_types:
- # We are here because the quality_type specified in the project is not supported any more,
- # so we need to switch it to the "preferred quality" if present, otherwise "normal".
- quality_has_been_changed = True
-
- # find the preferred quality
- preferred_quality_id = global_stack.getMetaDataEntry("preferred_quality", None)
- if preferred_quality_id is not None:
- definition_id = global_stack.definition.getId()
- definition_id = global_stack.definition.getMetaDataEntry("quality_definition", definition_id)
- if not parseBool(global_stack.getMetaDataEntry("has_machine_quality", "False")):
- definition_id = "fdmprinter"
-
- containers = self._container_registry.findInstanceContainers(id = preferred_quality_id,
- type = "quality",
- definition = definition_id)
- containers = [c for c in containers if not c.getMetaDataEntry("material", "")]
- if containers:
- global_stack.quality = containers[0]
- global_stack.qualityChanges = empty_quality_changes_container
- # also find the quality containers for the extruders
- for extruder_stack in extruder_stacks_in_use:
- search_criteria = {"id": preferred_quality_id,
- "type": "quality",
- "definition": definition_id}
- if global_stack.getMetaDataEntry("has_machine_materials") and extruder_stack.material.getId() not in ("empty", "empty_material"):
- search_criteria["material"] = extruder_stack.material.getId()
- containers = self._container_registry.findInstanceContainers(**search_criteria)
- if containers:
- extruder_stack.quality = containers[0]
- extruder_stack.qualityChanges = empty_quality_changes_container
- else:
- Logger.log("e", "Cannot find preferred quality for extruder [%s].", extruder_stack.getId())
-
- else:
- # we cannot find the preferred quality. THIS SHOULD NOT HAPPEN
- Logger.log("e", "Cannot find the preferred quality for machine [%s]", global_stack.getId())
- else:
- # The quality_type specified in the project file is usable, but the quality container itself may not
- # be correct. For example, for UM2, the quality container can be "draft" while it should be "um2_draft"
- # instead.
- # In this code branch, we try to fix those incorrect quality containers.
- #
- # ***IMPORTANT***: We only do this fix for single-extrusion machines.
- # We will first find the correct quality profile for the extruder, then apply the same
- # quality profile for the global stack.
- #
- if len(extruder_stacks) == 1:
- extruder_stack = extruder_stacks[0]
-
- search_criteria = {"type": "quality", "quality_type": global_stack.quality.getMetaDataEntry("quality_type")}
- search_criteria["definition"] = global_stack.definition.getId()
- if not parseBool(global_stack.getMetaDataEntry("has_machine_quality", "False")):
- search_criteria["definition"] = "fdmprinter"
-
- if global_stack.getMetaDataEntry("has_machine_materials") and extruder_stack.material.getId() not in ("empty", "empty_material"):
- search_criteria["material"] = extruder_stack.material.getId()
- containers = self._container_registry.findInstanceContainers(**search_criteria)
- if containers:
- new_quality_container = containers[0]
- extruder_stack.quality = new_quality_container
- global_stack.quality = new_quality_container
-
- # Replacing the old containers if resolve is "new".
- # When resolve is "new", some containers will get renamed, so all the other containers that reference to those
- # MUST get updated too.
- #
- if self._resolve_strategies["machine"] == "new":
- # A new machine was made, but it was serialized with the wrong user container. Fix that now.
- for container in user_instance_containers:
- # replacing the container ID for user instance containers for the extruders
- extruder_id = container.getMetaDataEntry("extruder", None)
- if extruder_id:
- for extruder in extruder_stacks:
- if extruder.getId() == extruder_id:
- extruder.userChanges = container
- continue
-
- # replacing the container ID for user instance containers for the machine
- machine_id = container.getMetaDataEntry("machine", None)
- if machine_id:
- if global_stack.getId() == machine_id:
- global_stack.userChanges = container
- continue
-
- changes_container_types = ("quality_changes", "definition_changes")
- if quality_has_been_changed:
- # DO NOT replace quality_changes if the current quality_type is not supported
- changes_container_types = ("definition_changes",)
- for changes_container_type in changes_container_types:
- if self._resolve_strategies[changes_container_type] == "new":
- # Quality changes needs to get a new ID, added to registry and to the right stacks
- for each_changes_container in quality_and_definition_changes_instance_containers:
- # NOTE: The renaming and giving new IDs are possibly redundant because they are done in the
- # instance container loading part.
- new_id = each_changes_container.getId()
-
- # Find the old (current) changes container in the global stack
- if changes_container_type == "quality_changes":
- old_container = global_stack.qualityChanges
- elif changes_container_type == "definition_changes":
- old_container = global_stack.definitionChanges
-
- # sanity checks
- # NOTE: The following cases SHOULD NOT happen!!!!
- if not old_container:
- Logger.log("e", "We try to get [%s] from the global stack [%s] but we got None instead!",
- changes_container_type, global_stack.getId())
-
- # Replace the quality/definition changes container if it's in the GlobalStack
- # NOTE: we can get an empty container here, but the IDs will not match,
- # so this comparison is fine.
- if self._id_mapping.get(old_container.getId()) == new_id:
- if changes_container_type == "quality_changes":
- global_stack.qualityChanges = each_changes_container
- elif changes_container_type == "definition_changes":
- global_stack.definitionChanges = each_changes_container
- continue
-
- # Replace the quality/definition changes container if it's in one of the ExtruderStacks
- for each_extruder_stack in extruder_stacks:
- changes_container = None
- if changes_container_type == "quality_changes":
- changes_container = each_extruder_stack.qualityChanges
- elif changes_container_type == "definition_changes":
- changes_container = each_extruder_stack.definitionChanges
-
- # sanity checks
- # NOTE: The following cases SHOULD NOT happen!!!!
- if not changes_container:
- Logger.log("e", "We try to get [%s] from the extruder stack [%s] but we got None instead!",
- changes_container_type, each_extruder_stack.getId())
-
- # NOTE: we can get an empty container here, but the IDs will not match,
- # so this comparison is fine.
- if self._id_mapping.get(changes_container.getId()) == new_id:
- if changes_container_type == "quality_changes":
- each_extruder_stack.qualityChanges = each_changes_container
- elif changes_container_type == "definition_changes":
- each_extruder_stack.definitionChanges = each_changes_container
-
- if self._resolve_strategies["material"] == "new":
- # the actual material instance container can have an ID such as
- # __
- # which cannot be determined immediately, so here we use a HACK to find the right new material
- # instance ID:
- # - get the old material IDs for all material
- # - find the old material with the longest common prefix in ID, that's the old material
- # - update the name by replacing the old prefix with the new
- # - find the new material container and set it to the stack
- old_to_new_material_dict = {}
- for each_material in material_containers:
- # find the material's old name
- for old_id, new_id in self._id_mapping.items():
- if each_material.getId() == new_id:
- old_to_new_material_dict[old_id] = each_material
- break
-
- # replace old material in global and extruder stacks with new
- self._replaceStackMaterialWithNew(global_stack, old_to_new_material_dict)
- if extruder_stacks:
- for each_extruder_stack in extruder_stacks:
- self._replaceStackMaterialWithNew(each_extruder_stack, old_to_new_material_dict)
-
- if extruder_stacks:
- for stack in extruder_stacks:
- ExtruderManager.getInstance().registerExtruder(stack, global_stack.getId())
+ # Prepare the machine
+ self._applyChangesToMachine(global_stack, extruder_stack_dict)
Logger.log("d", "Workspace loading is notifying rest of the code of changes...")
-
- if self._resolve_strategies["machine"] == "new":
- for stack in extruder_stacks:
- stack.setNextStack(global_stack)
- stack.containersChanged.emit(stack.getTop())
- else:
- if quality_has_been_changed:
- CuraApplication.getInstance().getMachineManager().activeQualityChanged.emit()
-
# Actually change the active machine.
- Application.getInstance().setGlobalContainerStack(global_stack)
-
- # Notify everything/one that is to notify about changes.
- global_stack.containersChanged.emit(global_stack.getTop())
+ #
+ # This is scheduled for later is because it depends on the Variant/Material/Qualitiy Managers to have the latest
+ # data, but those managers will only update upon a container/container metadata changed signal. Because this
+ # function is running on the main thread (Qt thread), although those "changed" signals have been emitted, but
+ # they won't take effect until this function is done.
+ # To solve this, we schedule _updateActiveMachine() for later so it will have the latest data.
+ self._updateActiveMachine(global_stack)
# Load all the nodes / meshdata of the workspace
nodes = self._3mf_mesh_reader.read(file_name)
@@ -1021,60 +704,275 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
self.setWorkspaceName(base_file_name)
return nodes
- ## HACK: Replaces the material container in the given stack with a newly created material container.
- # This function is used when the user chooses to resolve material conflicts by creating new ones.
- def _replaceStackMaterialWithNew(self, stack, old_new_material_dict):
- # The material containers in the project file are 'parent' material such as "generic_pla",
- # but a material container used in a global/extruder stack is a 'child' material,
- # such as "generic_pla_ultimaker3_AA_0.4", which can be formalised as the following:
- #
- # __
- #
- # In the project loading, when a user chooses to resolve material conflicts by creating new ones,
- # the old 'parent' material ID and the new 'parent' material ID are known, but not the child material IDs.
- # In this case, the global stack and the extruder stacks need to use the newly created material, but the
- # material containers they use are 'child' material. So, here, we need to find the right 'child' material for
- # the stacks.
- #
- # This hack approach works as follows:
- # - No matter there is a child material or not, the actual material we are looking for has the prefix
- # "", which is the old material name. For the material in a stack, we know that the new
- # material's ID will be "_blabla..", so we just need to replace the old material ID
- # with the new one to get the new 'child' material.
- # - Because the material containers have IDs such as "m #nn", if we use simple prefix matching, there can
- # be a problem in the following scenario:
- # - there are two materials in the project file, namely "m #1" and "m #11"
- # - the child materials in use are for example: "m #1_um3_aa04", "m #11_um3_aa04"
- # - if we only check for a simple prefix match, then "m #11_um3_aa04" will match with "m #1", but they
- # are not the same material
- # To avoid this, when doing the prefix matching, we use the result with the longest mactching prefix.
+ def _processQualityChanges(self, global_stack):
+ if self._machine_info.quality_changes_info is None:
+ return
- # find the old material ID
- old_material_id_in_stack = stack.material.getId()
- best_matching_old_material_id = None
- best_matching_old_material_prefix_length = -1
- for old_parent_material_id in old_new_material_dict:
- if len(old_parent_material_id) < best_matching_old_material_prefix_length:
+ application = CuraApplication.getInstance()
+ quality_manager = application.getQualityManager()
+
+ # If we have custom profiles, load them
+ quality_changes_name = self._machine_info.quality_changes_info.name
+ if self._machine_info.quality_changes_info is not None:
+ Logger.log("i", "Loading custom profile [%s] from project file",
+ self._machine_info.quality_changes_info.name)
+
+ # Get the correct extruder definition IDs for quality changes
+ from cura.Machines.QualityManager import getMachineDefinitionIDForQualitySearch
+ machine_definition_id_for_quality = getMachineDefinitionIDForQualitySearch(global_stack.definition)
+ machine_definition_for_quality = self._container_registry.findDefinitionContainers(id = machine_definition_id_for_quality)[0]
+
+ quality_changes_info = self._machine_info.quality_changes_info
+ quality_changes_quality_type = quality_changes_info.global_info.parser["metadata"]["quality_type"]
+
+ quality_changes_name = quality_changes_info.name
+ create_new = self._resolve_strategies.get("quality_changes") != "override"
+ if create_new:
+ container_info_dict = {None: self._machine_info.quality_changes_info.global_info}
+ container_info_dict.update(quality_changes_info.extruder_info_dict)
+
+ quality_changes_name = self._container_registry.uniqueName(quality_changes_name)
+ for position, container_info in container_info_dict.items():
+ extruder_stack = None
+ if position is not None:
+ extruder_stack = global_stack.extruders[position]
+ container = quality_manager._createQualityChanges(quality_changes_quality_type,
+ quality_changes_name,
+ global_stack, extruder_stack)
+ container_info.container = container
+ container.setDirty(True)
+ self._container_registry.addContainer(container)
+
+ Logger.log("d", "Created new quality changes container [%s]", container.getId())
+
+ else:
+ # Find the existing containers
+ quality_changes_containers = self._container_registry.findInstanceContainers(name = quality_changes_name,
+ type = "quality_changes")
+ for container in quality_changes_containers:
+ extruder_position = container.getMetaDataEntry("position")
+ if extruder_position is None:
+ quality_changes_info.global_info.container = container
+ else:
+ if extruder_position not in quality_changes_info.extruder_info_dict:
+ quality_changes_info.extruder_info_dict[extruder_position] = ContainerInfo(None, None, None)
+ container_info = quality_changes_info.extruder_info_dict[extruder_position]
+ container_info.container = container
+
+ # If there is no quality changes for any extruder, create one.
+ if not quality_changes_info.extruder_info_dict:
+ container_info = ContainerInfo(None, None, None)
+ quality_changes_info.extruder_info_dict["0"] = container_info
+ extruder_stack = global_stack.extruders["0"]
+
+ 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)
+
+ Logger.log("d", "Created new quality changes container [%s]", container.getId())
+
+ # 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()
+
+ # Loop over everything and override the existing containers
+ global_info = quality_changes_info.global_info
+ global_info.container.clear() # Clear all
+ for key, value in global_info.parser["values"].items():
+ if not machine_definition_for_quality.getProperty(key, "settable_per_extruder"):
+ global_info.container.setProperty(key, "value", value)
+ else:
+ quality_changes_info.extruder_info_dict["0"].container.setProperty(key, "value", value)
+
+ for position, container_info in quality_changes_info.extruder_info_dict.items():
+ if container_info.parser is None:
+ continue
+
+ if container_info.container is None:
+ extruder_stack = global_stack.extruders[position]
+ container = quality_manager._createQualityChanges(quality_changes_quality_type, quality_changes_name,
+ global_stack, extruder_stack)
+ container_info.container = container
+
+ for key, value in container_info.parser["values"].items():
+ container_info.container.setProperty(key, "value", value)
+
+ self._machine_info.quality_changes_info.name = quality_changes_name
+
+ def _clearStack(self, stack):
+ application = CuraApplication.getInstance()
+
+ stack.definitionChanges.clear()
+ stack.variant = application.empty_variant_container
+ stack.material = application.empty_material_container
+ stack.quality = application.empty_quality_container
+ stack.qualityChanges = application.empty_quality_changes_container
+ stack.userChanges.clear()
+
+ def _applyDefinitionChanges(self, global_stack, extruder_stack_dict):
+ values_to_set_for_extruders = {}
+ if self._machine_info.definition_changes_info is not None:
+ parser = self._machine_info.definition_changes_info.parser
+ for key, value in parser["values"].items():
+ if global_stack.getProperty(key, "settable_per_extruder"):
+ values_to_set_for_extruders[key] = value
+ else:
+ global_stack.definitionChanges.setProperty(key, "value", value)
+
+ for position, extruder_stack in extruder_stack_dict.items():
+ if position not in self._machine_info.extruder_info_dict:
continue
- if len(old_parent_material_id) <= len(old_material_id_in_stack):
- if old_parent_material_id == old_material_id_in_stack[0:len(old_parent_material_id)]:
- best_matching_old_material_prefix_length = len(old_parent_material_id)
- best_matching_old_material_id = old_parent_material_id
- if best_matching_old_material_id is None:
- Logger.log("w", "Cannot find any matching old material ID for stack [%s] material [%s]. Something can go wrong",
- stack.getId(), old_material_id_in_stack)
- return
+ extruder_info = self._machine_info.extruder_info_dict[position]
+ if extruder_info.definition_changes_info is None:
+ continue
+ parser = extruder_info.definition_changes_info.parser
+ for key, value in values_to_set_for_extruders.items():
+ extruder_stack.definitionChanges.setProperty(key, "value", value)
+ if parser is not None:
+ for key, value in parser["values"].items():
+ extruder_stack.definitionChanges.setProperty(key, "value", value)
- # find the new material container
- new_material_id = old_new_material_dict[best_matching_old_material_id].getId() + old_material_id_in_stack[len(best_matching_old_material_id):]
- new_material_containers = self._container_registry.findInstanceContainers(id = new_material_id, type = "material")
- if not new_material_containers:
- Logger.log("e", "Cannot find new material container [%s]", new_material_id)
- return
+ def _applyUserChanges(self, global_stack, extruder_stack_dict):
+ values_to_set_for_extruder_0 = {}
+ if self._machine_info.user_changes_info is not None:
+ parser = self._machine_info.user_changes_info.parser
+ for key, value in parser["values"].items():
+ if global_stack.getProperty(key, "settable_per_extruder"):
+ values_to_set_for_extruder_0[key] = value
+ else:
+ global_stack.userChanges.setProperty(key, "value", value)
- # replace the material in the given stack
- stack.material = new_material_containers[0]
+ for position, extruder_stack in extruder_stack_dict.items():
+ if position not in self._machine_info.extruder_info_dict:
+ continue
+
+ extruder_info = self._machine_info.extruder_info_dict[position]
+ if extruder_info.user_changes_info is not None:
+ parser = self._machine_info.extruder_info_dict[position].user_changes_info.parser
+ if position == "0":
+ for key, value in values_to_set_for_extruder_0.items():
+ extruder_stack.userChanges.setProperty(key, "value", value)
+ if parser is not None:
+ for key, value in parser["values"].items():
+ extruder_stack.userChanges.setProperty(key, "value", value)
+
+ def _applyVariants(self, global_stack, extruder_stack_dict):
+ application = CuraApplication.getInstance()
+ variant_manager = application.getVariantManager()
+
+ if self._machine_info.variant_info is not None:
+ parser = self._machine_info.variant_info.parser
+ variant_name = parser["general"]["name"]
+
+ from cura.Machines.VariantManager import VariantType
+ variant_type = VariantType.BUILD_PLATE
+
+ node = variant_manager.getVariantNode(global_stack.definition.getId(), variant_name, variant_type)
+ if node is not None:
+ global_stack.variant = node.getContainer()
+
+ for position, extruder_stack in extruder_stack_dict.items():
+ if position not in self._machine_info.extruder_info_dict:
+ continue
+ extruder_info = self._machine_info.extruder_info_dict[position]
+ if extruder_info.variant_info is None:
+ continue
+ parser = extruder_info.variant_info.parser
+
+ variant_name = parser["general"]["name"]
+ from cura.Machines.VariantManager import VariantType
+ variant_type = VariantType.NOZZLE
+
+ node = variant_manager.getVariantNode(global_stack.definition.getId(), variant_name, variant_type)
+ if node is not None:
+ extruder_stack.variant = node.getContainer()
+
+ def _applyMaterials(self, global_stack, extruder_stack_dict):
+ application = CuraApplication.getInstance()
+ material_manager = application.getMaterialManager()
+
+ # Force update lookup tables first
+ material_manager.initialize()
+
+ for position, extruder_stack in extruder_stack_dict.items():
+ if position not in self._machine_info.extruder_info_dict:
+ continue
+ extruder_info = self._machine_info.extruder_info_dict[position]
+ if extruder_info.root_material_id is None:
+ continue
+
+ root_material_id = extruder_info.root_material_id
+ root_material_id = self._old_new_materials.get(root_material_id, root_material_id)
+
+ # get material diameter of this extruder
+ machine_material_diameter = extruder_stack.materialDiameter
+ material_node = material_manager.getMaterialNode(global_stack.definition.getId(),
+ extruder_stack.variant.getName(),
+ machine_material_diameter,
+ root_material_id)
+ if material_node is not None:
+ extruder_stack.material = material_node.getContainer()
+
+ def _applyChangesToMachine(self, global_stack, extruder_stack_dict):
+ # Clear all first
+ self._clearStack(global_stack)
+ for extruder_stack in extruder_stack_dict.values():
+ self._clearStack(extruder_stack)
+
+ self._applyDefinitionChanges(global_stack, extruder_stack_dict)
+ self._applyUserChanges(global_stack, extruder_stack_dict)
+ self._applyVariants(global_stack, extruder_stack_dict)
+ self._applyMaterials(global_stack, extruder_stack_dict)
+
+ # prepare the quality to select
+ self._quality_changes_to_apply = None
+ self._quality_type_to_apply = None
+ if self._machine_info.quality_changes_info is not None:
+ self._quality_changes_to_apply = self._machine_info.quality_changes_info.name
+ else:
+ self._quality_type_to_apply = self._machine_info.quality_type
+
+ def _updateActiveMachine(self, global_stack):
+ # Actually change the active machine.
+ machine_manager = Application.getInstance().getMachineManager()
+ material_manager = Application.getInstance().getMaterialManager()
+ quality_manager = Application.getInstance().getQualityManager()
+
+ # Force update the lookup maps first
+ material_manager.initialize()
+ quality_manager.initialize()
+
+ machine_manager.setActiveMachine(global_stack.getId())
+
+ if self._quality_changes_to_apply:
+ quality_changes_group_dict = quality_manager.getQualityChangesGroups(global_stack)
+ if self._quality_changes_to_apply not in quality_changes_group_dict:
+ Logger.log("e", "Could not find quality_changes [%s]", self._quality_changes_to_apply)
+ return
+ quality_changes_group = quality_changes_group_dict[self._quality_changes_to_apply]
+ machine_manager.setQualityChangesGroup(quality_changes_group, no_dialog = True)
+ else:
+ self._quality_type_to_apply = self._quality_type_to_apply.lower()
+ quality_group_dict = quality_manager.getQualityGroups(global_stack)
+ if self._quality_type_to_apply in quality_group_dict:
+ quality_group = quality_group_dict[self._quality_type_to_apply]
+ else:
+ Logger.log("i", "Could not find quality type [%s], switch to default", self._quality_type_to_apply)
+ preferred_quality_type = global_stack.getMetaDataEntry("preferred_quality_type")
+ quality_group_dict = quality_manager.getQualityGroups(global_stack)
+ quality_group = quality_group_dict.get(preferred_quality_type)
+ if quality_group is None:
+ Logger.log("e", "Could not get preferred quality type [%s]", preferred_quality_type)
+
+ if quality_group is not None:
+ machine_manager.setQualityGroup(quality_group, no_dialog = True)
+
+ # Notify everything/one that is to notify about changes.
+ global_stack.containersChanged.emit(global_stack.getTop())
def _stripFileToId(self, file):
mime_type = MimeTypeDatabase.getMimeTypeForFile(file)
@@ -1086,7 +984,7 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
## Get the list of ID's of all containers in a container stack by partially parsing it's serialized data.
def _getContainerIdListFromSerialized(self, serialized):
- parser = configparser.ConfigParser(interpolation=None, empty_lines_in_values=False)
+ parser = ConfigParser(interpolation=None, empty_lines_in_values=False)
parser.read_string(serialized)
container_ids = []
@@ -1107,7 +1005,7 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
return container_ids
def _getMachineNameFromSerializedStack(self, serialized):
- parser = configparser.ConfigParser(interpolation=None, empty_lines_in_values=False)
+ parser = ConfigParser(interpolation=None, empty_lines_in_values=False)
parser.read_string(serialized)
return parser["general"].get("name", "")
diff --git a/plugins/3MFReader/WorkspaceDialog.py b/plugins/3MFReader/WorkspaceDialog.py
index 5b474843d5..bb31afd40b 100644
--- a/plugins/3MFReader/WorkspaceDialog.py
+++ b/plugins/3MFReader/WorkspaceDialog.py
@@ -52,7 +52,6 @@ class WorkspaceDialog(QObject):
machineConflictChanged = pyqtSignal()
qualityChangesConflictChanged = pyqtSignal()
- definitionChangesConflictChanged = pyqtSignal()
materialConflictChanged = pyqtSignal()
numVisibleSettingsChanged = pyqtSignal()
activeModeChanged = pyqtSignal()
@@ -196,10 +195,6 @@ class WorkspaceDialog(QObject):
def qualityChangesConflict(self):
return self._has_quality_changes_conflict
- @pyqtProperty(bool, notify=definitionChangesConflictChanged)
- def definitionChangesConflict(self):
- return self._has_definition_changes_conflict
-
@pyqtProperty(bool, notify=materialConflictChanged)
def materialConflict(self):
return self._has_material_conflict
@@ -229,18 +224,11 @@ class WorkspaceDialog(QObject):
self._has_quality_changes_conflict = quality_changes_conflict
self.qualityChangesConflictChanged.emit()
- def setDefinitionChangesConflict(self, definition_changes_conflict):
- if self._has_definition_changes_conflict != definition_changes_conflict:
- self._has_definition_changes_conflict = definition_changes_conflict
- self.definitionChangesConflictChanged.emit()
-
def getResult(self):
if "machine" in self._result and not self._has_machine_conflict:
self._result["machine"] = None
if "quality_changes" in self._result and not self._has_quality_changes_conflict:
self._result["quality_changes"] = None
- if "definition_changes" in self._result and not self._has_definition_changes_conflict:
- self._result["definition_changes"] = None
if "material" in self._result and not self._has_material_conflict:
self._result["material"] = None
diff --git a/plugins/3MFReader/WorkspaceDialog.qml b/plugins/3MFReader/WorkspaceDialog.qml
index 826b488e02..5418dcef6d 100644
--- a/plugins/3MFReader/WorkspaceDialog.qml
+++ b/plugins/3MFReader/WorkspaceDialog.qml
@@ -390,6 +390,13 @@ UM.Dialog
}
}
+ function accept() {
+ manager.closeBackend();
+ manager.onOkButtonClicked();
+ base.visible = false;
+ base.accept();
+ }
+
function reject() {
manager.onCancelButtonClicked();
base.visible = false;
diff --git a/plugins/3MFWriter/ThreeMFWorkspaceWriter.py b/plugins/3MFWriter/ThreeMFWorkspaceWriter.py
index f07a37a25f..3f5e69317e 100644
--- a/plugins/3MFWriter/ThreeMFWorkspaceWriter.py
+++ b/plugins/3MFWriter/ThreeMFWorkspaceWriter.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.
-from UM.Workspace.WorkspaceWriter import WorkspaceWriter
+import configparser
+from io import StringIO
+import zipfile
+
from UM.Application import Application
+from UM.Logger import Logger
from UM.Preferences import Preferences
from UM.Settings.ContainerRegistry import ContainerRegistry
-from cura.Settings.ExtruderManager import ExtruderManager
-import zipfile
-from io import StringIO
-import configparser
+from UM.Workspace.WorkspaceWriter import WorkspaceWriter
class ThreeMFWorkspaceWriter(WorkspaceWriter):
@@ -16,7 +17,10 @@ class ThreeMFWorkspaceWriter(WorkspaceWriter):
super().__init__()
def write(self, stream, nodes, mode=WorkspaceWriter.OutputMode.BinaryMode):
- mesh_writer = Application.getInstance().getMeshFileHandler().getWriter("3MFWriter")
+ application = Application.getInstance()
+ machine_manager = application.getMachineManager()
+
+ mesh_writer = application.getMeshFileHandler().getWriter("3MFWriter")
if not mesh_writer: # We need to have the 3mf mesh writer, otherwise we can't save the entire workspace
return False
@@ -29,17 +33,17 @@ class ThreeMFWorkspaceWriter(WorkspaceWriter):
if archive is None: # This happens if there was no mesh data to write.
archive = zipfile.ZipFile(stream, "w", compression = zipfile.ZIP_DEFLATED)
- global_container_stack = Application.getInstance().getGlobalContainerStack()
+ global_stack = machine_manager.activeMachine
# Add global container stack data to the archive.
- self._writeContainerToArchive(global_container_stack, archive)
+ self._writeContainerToArchive(global_stack, archive)
# Also write all containers in the stack to the file
- for container in global_container_stack.getContainers():
+ for container in global_stack.getContainers():
self._writeContainerToArchive(container, archive)
# Check if the machine has extruders and save all that data as well.
- for extruder_stack in ExtruderManager.getInstance().getMachineExtruders(global_container_stack.getId()):
+ for extruder_stack in global_stack.extruders.values():
self._writeContainerToArchive(extruder_stack, archive)
for container in extruder_stack.getContainers():
self._writeContainerToArchive(container, archive)
@@ -57,11 +61,11 @@ class ThreeMFWorkspaceWriter(WorkspaceWriter):
# Save Cura version
version_file = zipfile.ZipInfo("Cura/version.ini")
- version_config_parser = configparser.ConfigParser()
+ version_config_parser = configparser.ConfigParser(interpolation = None)
version_config_parser.add_section("versions")
- version_config_parser.set("versions", "cura_version", Application.getInstance().getVersion())
- version_config_parser.set("versions", "build_type", Application.getInstance().getBuildType())
- version_config_parser.set("versions", "is_debug_mode", str(Application.getInstance().getIsDebugMode()))
+ version_config_parser.set("versions", "cura_version", application.getVersion())
+ version_config_parser.set("versions", "build_type", application.getBuildType())
+ version_config_parser.set("versions", "is_debug_mode", str(application.getIsDebugMode()))
version_file_string = StringIO()
version_config_parser.write(version_file_string)
@@ -85,7 +89,8 @@ class ThreeMFWorkspaceWriter(WorkspaceWriter):
# Some containers have a base file, which should then be the file to use.
if "base_file" in container.getMetaData():
base_file = container.getMetaDataEntry("base_file")
- container = ContainerRegistry.getInstance().findContainers(id = base_file)[0]
+ if base_file != container.getId():
+ container = ContainerRegistry.getInstance().findContainers(id = base_file)[0]
file_name = "Cura/%s.%s" % (container.getId(), file_suffix)
@@ -97,7 +102,7 @@ class ThreeMFWorkspaceWriter(WorkspaceWriter):
file_in_archive.compress_type = zipfile.ZIP_DEFLATED
# Do not include the network authentication keys
- ignore_keys = {"network_authentication_id", "network_authentication_key"}
+ ignore_keys = {"network_authentication_id", "network_authentication_key", "octoprint_api_key"}
serialized_data = container.serialize(ignored_metadata_keys = ignore_keys)
archive.writestr(file_in_archive, serialized_data)
diff --git a/plugins/3MFWriter/ThreeMFWriter.py b/plugins/3MFWriter/ThreeMFWriter.py
index c4b7035cf1..ff6333763a 100644
--- a/plugins/3MFWriter/ThreeMFWriter.py
+++ b/plugins/3MFWriter/ThreeMFWriter.py
@@ -68,7 +68,7 @@ class ThreeMFWriter(MeshWriter):
if not isinstance(um_node, SceneNode):
return None
- active_build_plate_nr = CuraApplication.getInstance().getBuildPlateModel().activeBuildPlate
+ active_build_plate_nr = CuraApplication.getInstance().getMultiBuildPlateModel().activeBuildPlate
if um_node.callDecoration("getBuildPlateNumber") != active_build_plate_nr:
return
diff --git a/plugins/AutoSave/AutoSave.py b/plugins/AutoSave/AutoSave.py
index 331f328f2d..5fdac502b5 100644
--- a/plugins/AutoSave/AutoSave.py
+++ b/plugins/AutoSave/AutoSave.py
@@ -9,6 +9,7 @@ from UM.Application import Application
from UM.Resources import Resources
from UM.Logger import Logger
+
class AutoSave(Extension):
def __init__(self):
super().__init__()
@@ -16,18 +17,40 @@ class AutoSave(Extension):
Preferences.getInstance().preferenceChanged.connect(self._triggerTimer)
self._global_stack = None
- Application.getInstance().globalContainerStackChanged.connect(self._onGlobalStackChanged)
- self._onGlobalStackChanged()
Preferences.getInstance().addPreference("cura/autosave_delay", 1000 * 10)
self._change_timer = QTimer()
self._change_timer.setInterval(Preferences.getInstance().getValue("cura/autosave_delay"))
self._change_timer.setSingleShot(True)
- self._change_timer.timeout.connect(self._onTimeout)
self._saving = False
+ # At this point, the Application instance has not finished its constructor call yet, so directly using something
+ # like Application.getInstance() is not correct. The initialisation now will only gets triggered after the
+ # application finishes its start up successfully.
+ self._init_timer = QTimer()
+ self._init_timer.setInterval(1000)
+ self._init_timer.setSingleShot(True)
+ self._init_timer.timeout.connect(self.initialize)
+ self._init_timer.start()
+
+ def initialize(self):
+ # only initialise if the application is created and has started
+ from cura.CuraApplication import CuraApplication
+ if not CuraApplication.Created:
+ self._init_timer.start()
+ return
+ if not CuraApplication.getInstance().started:
+ self._init_timer.start()
+ return
+
+ self._change_timer.timeout.connect(self._onTimeout)
+ Application.getInstance().globalContainerStackChanged.connect(self._onGlobalStackChanged)
+ self._onGlobalStackChanged()
+
+ self._triggerTimer()
+
def _triggerTimer(self, *args):
if not self._saving:
self._change_timer.start()
diff --git a/plugins/ChangeLogPlugin/ChangeLog.txt b/plugins/ChangeLogPlugin/ChangeLog.txt
index de895b3e41..8a031c9eae 100755
--- a/plugins/ChangeLogPlugin/ChangeLog.txt
+++ b/plugins/ChangeLogPlugin/ChangeLog.txt
@@ -1,3 +1,55 @@
+[3.2.1]
+*Bug fixes
+- Fixed issues where Cura crashes on startup and loading profiles
+- Updated translations
+- Fixed an issue where the text would not render properly
+
+[3.2.0]
+*Tree support
+Experimental tree-like support structure that uses ‘branches’ to support prints. Branches ‘grow’ and multiply towards the model, with fewer contact points than alternative support methods. This results in better surface finishes for organic-shaped prints.
+
+*Adaptive layers
+Prints with a variable layer thickness which adapts to the angle of the model’s surfaces. The result is high-quality surface finishes with a marginally increased print time. This setting can be found under the experimental category.
+
+*Faster startup
+Printer definitions are now loaded when adding a printer, instead of loading all available printers on startup.
+
+*Backface culling in layer view
+Doubled frame rate by only rendering visible surfaces of the model in the layer view, instead of rendering the entire model. Good for lower spec GPUs as it is less resource-intensive.
+
+*Multi build plate
+Experimental feature that creates separate build plates with shared settings in a single session, eliminating the need to clear the build plate multiple times. Multiple build plates can be sliced and sent to a printer or printer group in Cura Connect. This feature must be enabled manually in the preferences ‘general’ tab.
+
+*Improved mesh type selection
+New button in the left toolbar to edit per model settings, giving the user more control over where to place support. Objects can be used as meshes, with a drop down list where ‘Print as support’, ‘Don't overlap support with other models’, ‘Modify settings for overlap with other models’, or ‘Modify settings for infill of other models’ can be specified. Contributed by fieldOfView.
+
+*View optimization
+Quick camera controls introduced in version 3.1 have been revised to create more accurate isometric, front, left, and right views.
+
+*Updated sidebar to QtQuick 2.0
+Application framework updated to increase speed, achieve a better width and style fit, and gives users dropdown menus that are styled to fit the enabled Ultimaker Cura theme, instead of the operating system’s theme.
+
+*Hide sidebar
+The sidebar can now be hidden/shown by selecting View > Expand/Collapse Sidebar, or with the hotkey CMD + E (Mac) or CTRL + E (PC and Linux).
+
+*Disable ‘Send slice information’
+A shortcut to disable ‘Send slice information’ has been added to the first launch to make it easier for privacy-conscious users to keep slice information private.
+
+*Signed binaries (Windows)
+For security-conscious users, the Windows installer and Windows binaries have been digitally signed to prevent “Unknown application” warnings and virus scanner false-positives.
+
+*Start/end gcode script per extruder
+Variables from both extruders in the start and end gcode snippets can now be accessed and edited, creating uniformity between profiles in different slicing environments. Contributed by fieldOfView.
+
+*OctoPrint plugin added to plugin browser
+This plugin enables printers managed with OctoPrint to print via Ultimaker Cura interface (version 3.2 or later).
+
+*Bugfixes
+- Fixed a bug where the mirror tool and center model options when used together would reset the model transformations
+- Updated config file path to fix crashes caused by user config files that are located on remote drives
+- Updated Arduino drivers to fix triggering errors during OTA updates in shared environments. This also fixes an issue when upgrading the firmware of the Ultimaker Original.
+- Fixed an issue where arranging small models would fail, due to conflict with small model files combined with the “Ensure models are kept apart” option
+
[3.1.0]
*Profile added for 0.25 mm print core
This new print core gives extra fine line widths which gives prints extra definition and surface quality.
diff --git a/plugins/CuraEngineBackend/CuraEngineBackend.py b/plugins/CuraEngineBackend/CuraEngineBackend.py
index 06d38eccd0..af6162c8d5 100755
--- a/plugins/CuraEngineBackend/CuraEngineBackend.py
+++ b/plugins/CuraEngineBackend/CuraEngineBackend.py
@@ -10,7 +10,6 @@ from UM.Logger import Logger
from UM.Message import Message
from UM.PluginRegistry import PluginRegistry
from UM.Resources import Resources
-from UM.Settings.Validator import ValidatorState #To find if a setting is in an error state. We can't slice then.
from UM.Platform import Platform
from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator
from UM.Qt.Duration import DurationFormat
@@ -32,7 +31,11 @@ import Arcus
from UM.i18n import i18nCatalog
catalog = i18nCatalog("cura")
+
class CuraEngineBackend(QObject, Backend):
+
+ backendError = Signal()
+
## Starts the back-end plug-in.
#
# This registers all the signal listeners and prepares for communication
@@ -59,23 +62,26 @@ class CuraEngineBackend(QObject, Backend):
default_engine_location = execpath
break
+ self._application = Application.getInstance()
+ self._multi_build_plate_model = None
+ self._machine_error_checker = None
+
if not default_engine_location:
raise EnvironmentError("Could not find CuraEngine")
- Logger.log("i", "Found CuraEngine at: %s" %(default_engine_location))
+ Logger.log("i", "Found CuraEngine at: %s", default_engine_location)
default_engine_location = os.path.abspath(default_engine_location)
Preferences.getInstance().addPreference("backend/location", default_engine_location)
# Workaround to disable layer view processing if layer view is not active.
self._layer_view_active = False
- Application.getInstance().getController().activeViewChanged.connect(self._onActiveViewChanged)
- Application.getInstance().getBuildPlateModel().activeBuildPlateChanged.connect(self._onActiveViewChanged)
self._onActiveViewChanged()
+
self._stored_layer_data = []
self._stored_optimized_layer_data = {} # key is build plate number, then arrays are stored until they go to the ProcessSlicesLayersJob
- self._scene = Application.getInstance().getController().getScene()
+ self._scene = self._application.getController().getScene()
self._scene.sceneChanged.connect(self._onSceneChanged)
# Triggers for auto-slicing. Auto-slicing is triggered as follows:
@@ -83,19 +89,10 @@ class CuraEngineBackend(QObject, Backend):
# - whenever there is a value change, we start the timer
# - sometimes an error check can get scheduled for a value change, in that case, we ONLY want to start the
# auto-slicing timer when that error check is finished
- # If there is an error check, it will set the "_is_error_check_scheduled" flag, stop the auto-slicing timer,
- # and only wait for the error check to be finished to start the auto-slicing timer again.
+ # If there is an error check, stop the auto-slicing timer, and only wait for the error check to be finished
+ # to start the auto-slicing timer again.
#
self._global_container_stack = None
- Application.getInstance().globalContainerStackChanged.connect(self._onGlobalStackChanged)
- Application.getInstance().getExtruderManager().extrudersAdded.connect(self._onGlobalStackChanged)
- self._onGlobalStackChanged()
-
- Application.getInstance().stacksValidationFinished.connect(self._onStackErrorCheckFinished)
-
- # A flag indicating if an error check was scheduled
- # If so, we will stop the auto-slice timer and start upon the error check
- self._is_error_check_scheduled = False
# Listeners for receiving messages from the back-end.
self._message_handlers["cura.proto.Layer"] = self._onLayerMessage
@@ -121,13 +118,6 @@ class CuraEngineBackend(QObject, Backend):
self._last_num_objects = defaultdict(int) # Count number of objects to see if there is something changed
self._postponed_scene_change_sources = [] # scene change is postponed (by a tool)
- self.backendQuit.connect(self._onBackendQuit)
- self.backendConnected.connect(self._onBackendConnected)
-
- # When a tool operation is in progress, don't slice. So we need to listen for tool operations.
- Application.getInstance().getController().toolOperationStarted.connect(self._onToolOperationStarted)
- Application.getInstance().getController().toolOperationStopped.connect(self._onToolOperationStopped)
-
self._slice_start_time = None
Preferences.getInstance().addPreference("general/auto_slice", True)
@@ -142,6 +132,30 @@ class CuraEngineBackend(QObject, Backend):
self.determineAutoSlicing()
Preferences.getInstance().preferenceChanged.connect(self._onPreferencesChanged)
+ self._application.initializationFinished.connect(self.initialize)
+
+ def initialize(self):
+ self._multi_build_plate_model = self._application.getMultiBuildPlateModel()
+
+ self._application.getController().activeViewChanged.connect(self._onActiveViewChanged)
+ self._multi_build_plate_model.activeBuildPlateChanged.connect(self._onActiveViewChanged)
+
+ self._application.globalContainerStackChanged.connect(self._onGlobalStackChanged)
+ self._onGlobalStackChanged()
+
+ # extruder enable / disable. Actually wanted to use machine manager here, but the initialization order causes it to crash
+ ExtruderManager.getInstance().extrudersChanged.connect(self._extruderChanged)
+
+ self.backendQuit.connect(self._onBackendQuit)
+ self.backendConnected.connect(self._onBackendConnected)
+
+ # When a tool operation is in progress, don't slice. So we need to listen for tool operations.
+ self._application.getController().toolOperationStarted.connect(self._onToolOperationStarted)
+ self._application.getController().toolOperationStopped.connect(self._onToolOperationStopped)
+
+ self._machine_error_checker = self._application.getMachineErrorChecker()
+ self._machine_error_checker.errorCheckFinished.connect(self._onStackErrorCheckFinished)
+
## Terminate the engine process.
#
# This function should terminate the engine process.
@@ -187,14 +201,12 @@ class CuraEngineBackend(QObject, Backend):
## Manually triggers a reslice
@pyqtSlot()
def forceSlice(self):
- if self._use_timer:
- self._change_timer.start()
- else:
- self.slice()
+ self.markSliceAll()
+ self.slice()
## Perform a slice of the scene.
def slice(self):
- Logger.log("d", "starting to slice!")
+ Logger.log("d", "Starting to slice...")
self._slice_start_time = time()
if not self._build_plates_to_be_sliced:
self.processingProgress.emit(1.0)
@@ -202,14 +214,14 @@ class CuraEngineBackend(QObject, Backend):
return
if self._process_layers_job:
- Logger.log("d", " ## Process layers job still busy, trying later")
+ Logger.log("d", "Process layers job still busy, trying later.")
return
if not hasattr(self._scene, "gcode_dict"):
self._scene.gcode_dict = {}
# see if we really have to slice
- active_build_plate = Application.getInstance().getBuildPlateModel().activeBuildPlate
+ active_build_plate = Application.getInstance().getMultiBuildPlateModel().activeBuildPlate
build_plate_to_be_sliced = self._build_plates_to_be_sliced.pop(0)
Logger.log("d", "Going to slice build plate [%s]!" % build_plate_to_be_sliced)
num_objects = self._numObjects()
@@ -292,6 +304,7 @@ class CuraEngineBackend(QObject, Backend):
if job.isCancelled() or job.getError() or job.getResult() == StartSliceJob.StartJobResult.Error:
self.backendStateChange.emit(BackendState.Error)
+ self.backendError.emit(job)
return
if job.getResult() == StartSliceJob.StartJobResult.MaterialIncompatible:
@@ -300,6 +313,7 @@ class CuraEngineBackend(QObject, Backend):
"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.backendError.emit(job)
else:
self.backendStateChange.emit(BackendState.NotStarted)
return
@@ -328,6 +342,7 @@ class CuraEngineBackend(QObject, Backend):
title = catalog.i18nc("@info:title", "Unable to slice"))
self._error_message.show()
self.backendStateChange.emit(BackendState.Error)
+ self.backendError.emit(job)
else:
self.backendStateChange.emit(BackendState.NotStarted)
return
@@ -350,6 +365,7 @@ class CuraEngineBackend(QObject, Backend):
title = catalog.i18nc("@info:title", "Unable to slice"))
self._error_message.show()
self.backendStateChange.emit(BackendState.Error)
+ self.backendError.emit(job)
return
if job.getResult() == StartSliceJob.StartJobResult.BuildPlateError:
@@ -358,6 +374,7 @@ class CuraEngineBackend(QObject, Backend):
title = catalog.i18nc("@info:title", "Unable to slice"))
self._error_message.show()
self.backendStateChange.emit(BackendState.Error)
+ self.backendError.emit(job)
else:
self.backendStateChange.emit(BackendState.NotStarted)
@@ -367,9 +384,9 @@ class CuraEngineBackend(QObject, Backend):
title = catalog.i18nc("@info:title", "Unable to slice"))
self._error_message.show()
self.backendStateChange.emit(BackendState.Error)
+ self.backendError.emit(job)
else:
self.backendStateChange.emit(BackendState.NotStarted)
- pass
self._invokeSlice()
return
@@ -427,12 +444,10 @@ class CuraEngineBackend(QObject, Backend):
if not isinstance(source, SceneNode):
return
- # This case checks if the source node is a node that contains a GCode. In this case the
- # cached layer data is removed so the previous data is not rendered - CURA-4821
+ # This case checks if the source node is a node that contains GCode. In this case the
+ # current layer data is removed so the previous data is not rendered - CURA-4821
if source.callDecoration("isBlockSlicing") and source.callDecoration("getLayerData"):
- if self._stored_optimized_layer_data:
- print(self._stored_optimized_layer_data)
- del self._stored_optimized_layer_data[source.callDecoration("getBuildPlateNumber")]
+ self._stored_optimized_layer_data = {}
build_plate_changed = set()
source_build_plate_number = source.callDecoration("getBuildPlateNumber")
@@ -502,7 +517,7 @@ class CuraEngineBackend(QObject, Backend):
node.getParent().removeChild(node)
def markSliceAll(self):
- for build_plate_number in range(Application.getInstance().getBuildPlateModel().maxBuildPlate + 1):
+ for build_plate_number in range(Application.getInstance().getMultiBuildPlateModel().maxBuildPlate + 1):
if build_plate_number not in self._build_plates_to_be_sliced:
self._build_plates_to_be_sliced.append(build_plate_number)
@@ -526,11 +541,9 @@ class CuraEngineBackend(QObject, Backend):
elif property == "validationState":
if self._use_timer:
- self._is_error_check_scheduled = True
self._change_timer.stop()
def _onStackErrorCheckFinished(self):
- self._is_error_check_scheduled = False
if not self._slicing and self._build_plates_to_be_sliced:
self.needsSlicing()
self._onChanged()
@@ -545,6 +558,8 @@ class CuraEngineBackend(QObject, Backend):
#
# \param message The protobuf message containing sliced layer data.
def _onOptimizedLayerMessage(self, message):
+ if self._start_slice_job_build_plate not in self._stored_optimized_layer_data:
+ self._stored_optimized_layer_data[self._start_slice_job_build_plate] = []
self._stored_optimized_layer_data[self._start_slice_job_build_plate].append(message)
## Called when a progress message is received from the engine.
@@ -554,12 +569,15 @@ class CuraEngineBackend(QObject, Backend):
self.processingProgress.emit(message.amount)
self.backendStateChange.emit(BackendState.Processing)
- # testing
def _invokeSlice(self):
if self._use_timer:
# if the error check is scheduled, wait for the error check finish signal to trigger auto-slice,
# otherwise business as usual
- if self._is_error_check_scheduled:
+ if self._machine_error_checker is None:
+ self._change_timer.stop()
+ return
+
+ if self._machine_error_checker.needToWaitForResult:
self._change_timer.stop()
else:
self._change_timer.start()
@@ -585,7 +603,7 @@ class CuraEngineBackend(QObject, Backend):
Logger.log("d", "Slicing took %s seconds", time() - self._slice_start_time )
# See if we need to process the sliced layers job.
- active_build_plate = Application.getInstance().getBuildPlateModel().activeBuildPlate
+ active_build_plate = Application.getInstance().getMultiBuildPlateModel().activeBuildPlate
if self._layer_view_active and (self._process_layers_job is None or not self._process_layers_job.isRunning()) and active_build_plate == self._start_slice_job_build_plate:
self._startProcessSlicedLayersJob(active_build_plate)
# self._onActiveViewChanged()
@@ -625,7 +643,11 @@ class CuraEngineBackend(QObject, Backend):
if self._use_timer:
# if the error check is scheduled, wait for the error check finish signal to trigger auto-slice,
# otherwise business as usual
- if self._is_error_check_scheduled:
+ if self._machine_error_checker is None:
+ self._change_timer.stop()
+ return
+
+ if self._machine_error_checker.needToWaitForResult:
self._change_timer.stop()
else:
self._change_timer.start()
@@ -705,7 +727,7 @@ class CuraEngineBackend(QObject, Backend):
application = Application.getInstance()
view = application.getController().getActiveView()
if view:
- active_build_plate = application.getBuildPlateModel().activeBuildPlate
+ active_build_plate = application.getMultiBuildPlateModel().activeBuildPlate
if view.getPluginId() == "SimulationView": # If switching to layer view, we should process the layers if that hasn't been done yet.
self._layer_view_active = True
# There is data and we're not slicing at the moment
@@ -777,3 +799,9 @@ class CuraEngineBackend(QObject, Backend):
def tickle(self):
if self._use_timer:
self._change_timer.start()
+
+ def _extruderChanged(self):
+ for build_plate_number in range(self._multi_build_plate_model.maxBuildPlate + 1):
+ if build_plate_number not in self._build_plates_to_be_sliced:
+ self._build_plates_to_be_sliced.append(build_plate_number)
+ self._invokeSlice()
diff --git a/plugins/CuraEngineBackend/ProcessGCodeJob.py b/plugins/CuraEngineBackend/ProcessGCodeJob.py
index ed430f8fa9..817daa9f85 100644
--- a/plugins/CuraEngineBackend/ProcessGCodeJob.py
+++ b/plugins/CuraEngineBackend/ProcessGCodeJob.py
@@ -12,6 +12,6 @@ class ProcessGCodeLayerJob(Job):
self._message = message
def run(self):
- active_build_plate_id = Application.getInstance().getBuildPlateModel().activeBuildPlate
+ active_build_plate_id = Application.getInstance().getMultiBuildPlateModel().activeBuildPlate
gcode_list = self._scene.gcode_dict[active_build_plate_id]
gcode_list.append(self._message.data.decode("utf-8", "replace"))
diff --git a/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py b/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py
index c1fc597d80..cbc097bb33 100644
--- a/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py
+++ b/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py
@@ -81,7 +81,8 @@ class ProcessSlicedLayersJob(Job):
Application.getInstance().getController().activeViewChanged.connect(self._onActiveViewChanged)
- new_node = CuraSceneNode()
+ # The no_setting_override is here because adding the SettingOverrideDecorator will trigger a reslice
+ new_node = CuraSceneNode(no_setting_override = True)
new_node.addDecorator(BuildPlateDecorator(self._build_plate_number))
# Force garbage collection.
diff --git a/plugins/CuraEngineBackend/StartSliceJob.py b/plugins/CuraEngineBackend/StartSliceJob.py
index fa5473ba38..96124a3514 100644
--- a/plugins/CuraEngineBackend/StartSliceJob.py
+++ b/plugins/CuraEngineBackend/StartSliceJob.py
@@ -5,6 +5,7 @@ import numpy
from string import Formatter
from enum import IntEnum
import time
+import re
from UM.Job import Job
from UM.Application import Application
@@ -15,7 +16,7 @@ from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator
from UM.Settings.Validator import ValidatorState
from UM.Settings.SettingRelation import RelationType
-from cura.Scene.CuraSceneNode import CuraSceneNode as SceneNode
+from cura.Scene.CuraSceneNode import CuraSceneNode
from cura.OneAtATimeIterator import OneAtATimeIterator
from cura.Settings.ExtruderManager import ExtruderManager
@@ -54,19 +55,19 @@ class GcodeStartEndFormatter(Formatter):
extruder_nr = int(kwargs["-1"][key_fragments[1]]) # get extruder_nr values from the global stack
except (KeyError, ValueError):
# either the key does not exist, or the value is not an int
- Logger.log("w", "Unable to determine stack nr '%s' for key '%s' in start/end gcode, using global stack", key_fragments[1], key_fragments[0])
+ Logger.log("w", "Unable to determine stack nr '%s' for key '%s' in start/end g-code, using global stack", key_fragments[1], key_fragments[0])
elif len(key_fragments) != 1:
- Logger.log("w", "Incorrectly formatted placeholder '%s' in start/end gcode", key)
+ Logger.log("w", "Incorrectly formatted placeholder '%s' in start/end g-code", key)
return "{" + str(key) + "}"
key = key_fragments[0]
try:
return kwargs[str(extruder_nr)][key]
except KeyError:
- Logger.log("w", "Unable to replace '%s' placeholder in start/end gcode", key)
+ Logger.log("w", "Unable to replace '%s' placeholder in start/end g-code", key)
return "{" + key + "}"
else:
- Logger.log("w", "Incorrectly formatted placeholder '%s' in start/end gcode", key)
+ Logger.log("w", "Incorrectly formatted placeholder '%s' in start/end g-code", key)
return "{" + str(key) + "}"
@@ -128,16 +129,19 @@ class StartSliceJob(Job):
self.setResult(StartJobResult.MaterialIncompatible)
return
- for extruder_stack in ExtruderManager.getInstance().getMachineExtruders(stack.getId()):
+ for position, extruder_stack in stack.extruders.items():
material = extruder_stack.findContainer({"type": "material"})
+ if not extruder_stack.isEnabled:
+ continue
if material:
if material.getMetaDataEntry("compatible") == False:
self.setResult(StartJobResult.MaterialIncompatible)
return
+
# Don't slice if there is a per object setting with an error value.
for node in DepthFirstIterator(self._scene.getRoot()):
- if type(node) is not SceneNode or not node.isSelectable():
+ if not isinstance(node, CuraSceneNode) or not node.isSelectable():
continue
if self._checkStackForErrors(node.callDecoration("getStack")):
@@ -161,10 +165,15 @@ class StartSliceJob(Job):
if getattr(node, "_outside_buildarea", False):
continue
+ # Filter on current build plate
+ build_plate_number = node.callDecoration("getBuildPlateNumber")
+ if build_plate_number is not None and build_plate_number != self._build_plate_number:
+ continue
+
children = node.getAllChildren()
children.append(node)
for child_node in children:
- if type(child_node) is SceneNode and child_node.getMeshData() and child_node.getMeshData().getVertices() is not None:
+ if child_node.getMeshData() and child_node.getMeshData().getVertices() is not None:
temp_list.append(child_node)
if temp_list:
@@ -176,17 +185,24 @@ class StartSliceJob(Job):
temp_list = []
has_printing_mesh = False
for node in DepthFirstIterator(self._scene.getRoot()):
- if node.callDecoration("isSliceable") and type(node) is SceneNode and node.getMeshData() and node.getMeshData().getVertices() is not None:
+ 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)
- if (node.callDecoration("getBuildPlateNumber") == self._build_plate_number):
- if not getattr(node, "_outside_buildarea", False) or is_non_printing_mesh:
- temp_list.append(node)
- if not is_non_printing_mesh:
- has_printing_mesh = True
+ # Find a reason not to add the node
+ if node.callDecoration("getBuildPlateNumber") != self._build_plate_number:
+ continue
+ if getattr(node, "_outside_buildarea", False) and not is_non_printing_mesh:
+ continue
+ node_position = node.callDecoration("getActiveExtruderPosition")
+ if not stack.extruders[str(node_position)].isEnabled:
+ continue
+
+ temp_list.append(node)
+ if not is_non_printing_mesh:
+ has_printing_mesh = True
Job.yieldThread()
@@ -262,9 +278,15 @@ class StartSliceJob(Job):
# \return A dictionary of replacement tokens to the values they should be
# replaced with.
def _buildReplacementTokens(self, stack) -> dict:
+ default_extruder_position = int(Application.getInstance().getMachineManager().defaultExtruderPosition)
result = {}
for key in stack.getAllKeys():
- result[key] = stack.getProperty(key, "value")
+ setting_type = stack.definition.getProperty(key, "type")
+ value = stack.getProperty(key, "value")
+ if setting_type == "extruder" and value == -1:
+ # replace with the default value
+ value = default_extruder_position
+ result[key] = value
Job.yieldThread()
result["print_bed_temperature"] = result["material_bed_temperature"] # Renamed settings.
@@ -302,7 +324,7 @@ class StartSliceJob(Job):
settings["default_extruder_nr"] = default_extruder_nr
return str(fmt.format(value, **settings))
except:
- Logger.logException("w", "Unable to do token replacement on start/end gcode")
+ Logger.logException("w", "Unable to do token replacement on start/end g-code")
return str(value)
## Create extruder message from stack
@@ -338,10 +360,12 @@ class StartSliceJob(Job):
# Pre-compute material material_bed_temp_prepend and material_print_temp_prepend
start_gcode = settings["machine_start_gcode"]
- bed_temperature_settings = {"material_bed_temperature", "material_bed_temperature_layer_0"}
- settings["material_bed_temp_prepend"] = all(("{" + setting + "}" not in start_gcode for setting in bed_temperature_settings))
- print_temperature_settings = {"material_print_temperature", "material_print_temperature_layer_0", "default_material_print_temperature", "material_initial_print_temperature", "material_final_print_temperature", "material_standby_temperature"}
- settings["material_print_temp_prepend"] = all(("{" + setting + "}" not in start_gcode for setting in print_temperature_settings))
+ bed_temperature_settings = ["material_bed_temperature", "material_bed_temperature_layer_0"]
+ pattern = r"\{(%s)(,\s?\w+)?\}" % "|".join(bed_temperature_settings) # match {setting} as well as {setting, extruder_nr}
+ settings["material_bed_temp_prepend"] = re.search(pattern, start_gcode) == None
+ print_temperature_settings = ["material_print_temperature", "material_print_temperature_layer_0", "default_material_print_temperature", "material_initial_print_temperature", "material_final_print_temperature", "material_standby_temperature"]
+ pattern = r"\{(%s)(,\s?\w+)?\}" % "|".join(print_temperature_settings) # match {setting} as well as {setting, extruder_nr}
+ settings["material_print_temp_prepend"] = re.search(pattern, start_gcode) == None
# Replace the setting tokens in start and end g-code.
# Use values from the first used extruder by default so we get the expected temperatures
@@ -368,11 +392,11 @@ class StartSliceJob(Job):
# limit_to_extruder property.
def _buildGlobalInheritsStackMessage(self, stack):
for key in stack.getAllKeys():
- extruder = int(round(float(stack.getProperty(key, "limit_to_extruder"))))
- if extruder >= 0: #Set to a specific extruder.
+ extruder_position = int(round(float(stack.getProperty(key, "limit_to_extruder"))))
+ if extruder_position >= 0: # Set to a specific extruder.
setting_extruder = self._slice_message.addRepeatedMessage("limit_to_extruder")
setting_extruder.name = key
- setting_extruder.extruder = extruder
+ setting_extruder.extruder = extruder_position
Job.yieldThread()
## Check if a node has per object settings and ensure that they are set correctly in the message
diff --git a/plugins/CuraProfileReader/CuraProfileReader.py b/plugins/CuraProfileReader/CuraProfileReader.py
index 5631d138aa..69b2187541 100644
--- a/plugins/CuraProfileReader/CuraProfileReader.py
+++ b/plugins/CuraProfileReader/CuraProfileReader.py
@@ -39,7 +39,7 @@ class CuraProfileReader(ProfileReader):
except zipfile.BadZipFile:
# It must be an older profile from Cura 2.1.
- with open(file_name, encoding="utf-8") as fhandle:
+ 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)]
@@ -52,10 +52,10 @@ class CuraProfileReader(ProfileReader):
parser = configparser.ConfigParser(interpolation=None)
parser.read_string(serialized)
- if not "general" in parser:
+ if "general" not in parser:
Logger.log("w", "Missing required section 'general'.")
return []
- if not "version" in parser["general"]:
+ if "version" not in parser["general"]:
Logger.log("w", "Missing required 'version' property")
return []
diff --git a/plugins/FirmwareUpdateChecker/FirmwareUpdateChecker.py b/plugins/FirmwareUpdateChecker/FirmwareUpdateChecker.py
index 458aca5787..23a040f2e2 100644
--- a/plugins/FirmwareUpdateChecker/FirmwareUpdateChecker.py
+++ b/plugins/FirmwareUpdateChecker/FirmwareUpdateChecker.py
@@ -20,7 +20,7 @@ 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"
+ JEDI_VERSION_URL = "http://software.ultimaker.com/jedi/releases/latest.version?utm_source=cura&utm_medium=software&utm_campaign=resources"
def __init__(self):
super().__init__()
@@ -49,7 +49,6 @@ class FirmwareUpdateChecker(Extension):
def _onContainerAdded(self, container):
# Only take care when a new GlobalStack was added
if isinstance(container, GlobalStack):
- Logger.log("i", "You have a '%s' in printer list. Let's check the firmware!", container.getId())
self.checkFirmwareVersion(container, True)
## Connect with software.ultimaker.com, load latest.version and check version info.
diff --git a/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py b/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py
index 6dd7338cfd..fd6c4680e8 100644
--- a/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py
+++ b/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py
@@ -44,6 +44,8 @@ class FirmwareUpdateCheckerJob(Job):
# 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!")
+
# 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()
diff --git a/plugins/GCodeProfileReader/GCodeProfileReader.py b/plugins/GCodeProfileReader/GCodeProfileReader.py
index 9d7f0059f9..d6bda85a48 100644
--- a/plugins/GCodeProfileReader/GCodeProfileReader.py
+++ b/plugins/GCodeProfileReader/GCodeProfileReader.py
@@ -9,7 +9,7 @@ from UM.Logger import Logger
from UM.i18n import i18nCatalog
catalog = i18nCatalog("cura")
-from cura.ProfileReader import ProfileReader
+from cura.ProfileReader import ProfileReader, NoProfileException
## A class that reads profile data from g-code files.
#
@@ -66,12 +66,17 @@ class GCodeProfileReader(ProfileReader):
return None
serialized = unescapeGcodeComment(serialized)
+ serialized = serialized.strip()
+
+ if not serialized:
+ Logger.log("i", "No custom profile to import from this g-code: %s", file_name)
+ raise NoProfileException()
# serialized data can be invalid JSON
try:
json_data = json.loads(serialized)
except Exception as e:
- Logger.log("e", "Could not parse serialized JSON data from GCode %s, error: %s", file_name, e)
+ Logger.log("e", "Could not parse serialized JSON data from g-code %s, error: %s", file_name, e)
return None
profiles = []
diff --git a/plugins/GCodeProfileReader/plugin.json b/plugins/GCodeProfileReader/plugin.json
index 8111bc687c..f8f7d4c291 100644
--- a/plugins/GCodeProfileReader/plugin.json
+++ b/plugins/GCodeProfileReader/plugin.json
@@ -1,5 +1,5 @@
{
- "name": "GCode Profile Reader",
+ "name": "G-code Profile Reader",
"author": "Ultimaker B.V.",
"version": "1.0.0",
"description": "Provides support for importing profiles from g-code files.",
diff --git a/plugins/GCodeReader/FlavorParser.py b/plugins/GCodeReader/FlavorParser.py
index f63ba3ca69..c064ffbf10 100644
--- a/plugins/GCodeReader/FlavorParser.py
+++ b/plugins/GCodeReader/FlavorParser.py
@@ -437,7 +437,7 @@ class FlavorParser:
scene_node.addDecorator(gcode_list_decorator)
# gcode_dict stores gcode_lists for a number of build plates.
- active_build_plate_id = Application.getInstance().getBuildPlateModel().activeBuildPlate
+ active_build_plate_id = Application.getInstance().getMultiBuildPlateModel().activeBuildPlate
gcode_dict = {active_build_plate_id: gcode_list}
Application.getInstance().getController().getScene().gcode_dict = gcode_dict
diff --git a/plugins/GCodeReader/GCodeReader.py b/plugins/GCodeReader/GCodeReader.py
index cb2f5d99e0..050f243f9b 100755
--- a/plugins/GCodeReader/GCodeReader.py
+++ b/plugins/GCodeReader/GCodeReader.py
@@ -26,7 +26,7 @@ class GCodeReader(MeshReader):
# PreRead is used to get the correct flavor. If not, Marlin is set by default
def preRead(self, file_name, *args, **kwargs):
- with open(file_name, "r") as file:
+ with open(file_name, "r", encoding = "utf-8") as file:
for line in file:
if line[:len(self._flavor_keyword)] == self._flavor_keyword:
try:
diff --git a/plugins/GCodeWriter/GCodeWriter.py b/plugins/GCodeWriter/GCodeWriter.py
index 95c48c4d9e..1b3b7264a1 100644
--- a/plugins/GCodeWriter/GCodeWriter.py
+++ b/plugins/GCodeWriter/GCodeWriter.py
@@ -5,6 +5,7 @@ from UM.Mesh.MeshWriter import MeshWriter
from UM.Logger import Logger
from UM.Application import Application
from UM.Settings.InstanceContainer import InstanceContainer
+from UM.Util import parseBool
from cura.Settings.ExtruderManager import ExtruderManager
@@ -56,10 +57,10 @@ class GCodeWriter(MeshWriter):
# file. This must always be text mode.
def write(self, stream, nodes, mode = MeshWriter.OutputMode.TextMode):
if mode != MeshWriter.OutputMode.TextMode:
- Logger.log("e", "GCode Writer does not support non-text mode.")
+ Logger.log("e", "GCodeWriter does not support non-text mode.")
return False
- active_build_plate = Application.getInstance().getBuildPlateModel().activeBuildPlate
+ active_build_plate = Application.getInstance().getMultiBuildPlateModel().activeBuildPlate
scene = Application.getInstance().getController().getScene()
gcode_dict = getattr(scene, "gcode_dict")
if not gcode_dict:
@@ -107,8 +108,8 @@ class GCodeWriter(MeshWriter):
prefix_length = len(prefix)
container_with_profile = stack.qualityChanges
- if not container_with_profile:
- Logger.log("e", "No valid quality profile found, not writing settings to GCode!")
+ if container_with_profile.getId() == "empty_quality_changes":
+ Logger.log("e", "No valid quality profile found, not writing settings to g-code!")
return ""
flat_global_container = self._createFlattenedContainerInstance(stack.getTop(), container_with_profile)
@@ -120,12 +121,20 @@ class GCodeWriter(MeshWriter):
if flat_global_container.getMetaDataEntry("quality_type", None) is None:
flat_global_container.addMetaDataEntry("quality_type", stack.quality.getMetaDataEntry("quality_type", "normal"))
+ # Change the default defintion
+ default_machine_definition = "fdmprinter"
+ if parseBool(stack.getMetaDataEntry("has_machine_quality", "False")):
+ default_machine_definition = stack.getMetaDataEntry("quality_definition")
+ if not default_machine_definition:
+ default_machine_definition = stack.definition.getId()
+ flat_global_container.setMetaDataEntry("definition", default_machine_definition)
+
serialized = flat_global_container.serialize()
data = {"global_quality": serialized}
- for extruder in sorted(ExtruderManager.getInstance().getMachineExtruders(stack.getId()), key = lambda k: k.getMetaDataEntry("position")):
+ for extruder in sorted(stack.extruders.values(), key = lambda k: k.getMetaDataEntry("position")):
extruder_quality = extruder.qualityChanges
- if not extruder_quality:
+ if extruder_quality.getId() == "empty_quality_changes":
Logger.log("w", "No extruder quality profile found, not writing quality for extruder %s to file!", extruder.getId())
continue
flat_extruder_quality = self._createFlattenedContainerInstance(extruder.getTop(), extruder_quality)
@@ -140,6 +149,10 @@ class GCodeWriter(MeshWriter):
# Ensure that quality_type is set. (Can happen if we have empty quality changes).
if flat_extruder_quality.getMetaDataEntry("quality_type", None) is None:
flat_extruder_quality.addMetaDataEntry("quality_type", extruder.quality.getMetaDataEntry("quality_type", "normal"))
+
+ # Change the default defintion
+ flat_extruder_quality.setMetaDataEntry("definition", default_machine_definition)
+
extruder_serialized = flat_extruder_quality.serialize()
data.setdefault("extruder_quality", []).append(extruder_serialized)
diff --git a/plugins/GCodeWriter/__init__.py b/plugins/GCodeWriter/__init__.py
index a89332a371..1a5728f510 100644
--- a/plugins/GCodeWriter/__init__.py
+++ b/plugins/GCodeWriter/__init__.py
@@ -13,7 +13,7 @@ def getMetaData():
"mesh_writer": {
"output": [{
"extension": "gcode",
- "description": catalog.i18nc("@item:inlistbox", "GCode File"),
+ "description": catalog.i18nc("@item:inlistbox", "G-code File"),
"mime_type": "text/x-gcode",
"mode": GCodeWriter.GCodeWriter.OutputMode.TextMode
}]
diff --git a/plugins/GCodeWriter/plugin.json b/plugins/GCodeWriter/plugin.json
index 5788b01375..5fcb1a3bd7 100644
--- a/plugins/GCodeWriter/plugin.json
+++ b/plugins/GCodeWriter/plugin.json
@@ -1,8 +1,8 @@
{
- "name": "GCode Writer",
+ "name": "G-code Writer",
"author": "Ultimaker B.V.",
"version": "1.0.0",
- "description": "Writes GCode to a file.",
+ "description": "Writes g-code to a file.",
"api": 4,
"i18n-catalog": "cura"
}
diff --git a/plugins/LegacyProfileReader/LegacyProfileReader.py b/plugins/LegacyProfileReader/LegacyProfileReader.py
index 07cd8b0aad..824fc959a1 100644
--- a/plugins/LegacyProfileReader/LegacyProfileReader.py
+++ b/plugins/LegacyProfileReader/LegacyProfileReader.py
@@ -125,7 +125,10 @@ class LegacyProfileReader(ProfileReader):
Logger.log("e", "Dictionary of Doom has no translation. Is it the correct JSON file?")
return None
current_printer_definition = global_container_stack.definition
- profile.setDefinition(current_printer_definition.getId())
+ quality_definition = current_printer_definition.getMetaDataEntry("quality_definition")
+ if not quality_definition:
+ quality_definition = current_printer_definition.getId()
+ profile.setDefinition(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")
@@ -162,20 +165,21 @@ class LegacyProfileReader(ProfileReader):
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)
+
#We need to return one extruder stack and one global stack.
global_container_id = container_registry.uniqueName("Global Imported Legacy Profile")
global_profile = profile.duplicate(new_id = global_container_id, new_name = profile_id) #Needs to have the same name as the extruder profile.
global_profile.setDirty(True)
- #Only the extruder stack has an extruder metadata entry.
- profile.addMetaDataEntry("extruder", ExtruderManager.getInstance().getActiveExtruderStack().definition.getId())
+ profile_definition = "fdmprinter"
+ from UM.Util import parseBool
+ if parseBool(global_container_stack.getMetaDataEntry("has_machine_quality", "False")):
+ profile_definition = global_container_stack.getMetaDataEntry("quality_definition")
+ if not profile_definition:
+ profile_definition = global_container_stack.definition.getId()
+ global_profile.setDefinition(profile_definition)
- #Split all settings into per-extruder and global settings.
- for setting_key in profile.getAllKeys():
- settable_per_extruder = global_container_stack.getProperty(setting_key, "settable_per_extruder")
- if settable_per_extruder:
- global_profile.removeInstance(setting_key)
- else:
- profile.removeInstance(setting_key)
-
- return [global_profile, profile]
+ return [global_profile]
diff --git a/plugins/MachineSettingsAction/MachineSettingsAction.py b/plugins/MachineSettingsAction/MachineSettingsAction.py
index 101ba54ed0..ded59bf934 100755
--- a/plugins/MachineSettingsAction/MachineSettingsAction.py
+++ b/plugins/MachineSettingsAction/MachineSettingsAction.py
@@ -2,20 +2,16 @@
# Cura is released under the terms of the LGPLv3 or higher.
from PyQt5.QtCore import pyqtProperty, pyqtSignal
+
+import UM.i18n
from UM.FlameProfiler import pyqtSlot
-
-from cura.MachineAction import MachineAction
-
from UM.Application import Application
from UM.Settings.ContainerRegistry import ContainerRegistry
from UM.Settings.DefinitionContainer import DefinitionContainer
-from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator
-from UM.Logger import Logger
-from cura.Settings.ExtruderManager import ExtruderManager
+from cura.MachineAction import MachineAction
from cura.Settings.CuraStackBuilder import CuraStackBuilder
-import UM.i18n
catalog = UM.i18n.i18nCatalog("cura")
@@ -26,6 +22,8 @@ class MachineSettingsAction(MachineAction):
super().__init__("MachineSettingsAction", catalog.i18nc("@action", "Machine Settings"))
self._qml_url = "MachineSettingsAction.qml"
+ self._application = Application.getInstance()
+
self._global_container_stack = None
from cura.Settings.CuraContainerStack import _ContainerIndexes
@@ -34,38 +32,44 @@ class MachineSettingsAction(MachineAction):
self._container_registry = ContainerRegistry.getInstance()
self._container_registry.containerAdded.connect(self._onContainerAdded)
self._container_registry.containerRemoved.connect(self._onContainerRemoved)
- Application.getInstance().globalContainerStackChanged.connect(self._onGlobalContainerChanged)
+ self._application.globalContainerStackChanged.connect(self._onGlobalContainerChanged)
- self._empty_container = self._container_registry.getEmptyInstanceContainer()
+ self._backend = self._application.getBackend()
- self._backend = Application.getInstance().getBackend()
+ 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
def _onContainerAdded(self, container):
# Add this action as a supported action to all machine definitions
if isinstance(container, DefinitionContainer) and container.getMetaDataEntry("type") == "machine":
- Application.getInstance().getMachineActionManager().addSupportedAction(container.getId(), self.getKey())
+ 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_container = container.definitionChanges
- if definition_changes_container == self._empty_container:
+ definition_changes_id = container.definitionChanges.getId()
+ if self._isEmptyDefinitionChanges(definition_changes_id):
return
- self._container_registry.removeContainer(definition_changes_container.getId())
+ self._container_registry.removeContainer(definition_changes_id)
def _reset(self):
if not self._global_container_stack:
return
# Make sure there is a definition_changes container to store the machine settings
- definition_changes_container = self._global_container_stack.definitionChanges
- if definition_changes_container == self._empty_container:
- definition_changes_container = CuraStackBuilder.createDefinitionChangesContainer(
- self._global_container_stack, self._global_container_stack.getName() + "_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 CuraContainerStack, _ContainerIndexes
+ from cura.Settings.CuraContainerStack import _ContainerIndexes
container_index = _ContainerIndexes.DefinitionChanges
if container_index != self._container_index:
@@ -105,66 +109,15 @@ class MachineSettingsAction(MachineAction):
@pyqtSlot(int)
def setMachineExtruderCount(self, extruder_count):
- extruder_manager = Application.getInstance().getExtruderManager()
-
- definition_changes_container = self._global_container_stack.definitionChanges
- if not self._global_container_stack or definition_changes_container == self._empty_container:
- return
-
- previous_extruder_count = self._global_container_stack.getProperty("machine_extruder_count", "value")
- if extruder_count == previous_extruder_count:
- return
-
- # reset all extruder number settings whose value is no longer valid
- for setting_instance in self._global_container_stack.userChanges.findInstances():
- setting_key = setting_instance.definition.key
- if not self._global_container_stack.getProperty(setting_key, "type") in ("extruder", "optional_extruder"):
- continue
-
- old_value = int(self._global_container_stack.userChanges.getProperty(setting_key, "value"))
- if old_value >= extruder_count:
- self._global_container_stack.userChanges.removeInstance(setting_key)
- Logger.log("d", "Reset [%s] because its old value [%s] is no longer valid ", setting_key, old_value)
-
- # Check to see if any objects are set to print with an extruder that will no longer exist
- root_node = Application.getInstance().getController().getScene().getRoot()
- for node in DepthFirstIterator(root_node):
- if node.getMeshData():
- extruder_nr = node.callDecoration("getActiveExtruderPosition")
-
- if extruder_nr is not None and int(extruder_nr) > extruder_count - 1:
- node.callDecoration("setActiveExtruder", extruder_manager.getExtruderStack(extruder_count - 1).getId())
-
- definition_changes_container.setProperty("machine_extruder_count", "value", extruder_count)
-
- # Make sure one of the extruder stacks is active
- extruder_manager.setActiveExtruderIndex(0)
-
- # Move settable_per_extruder values out of the global container
- # 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.getTop()
-
- if previous_extruder_count == 1:
- extruder_stacks = ExtruderManager.getInstance().getActiveExtruderStacks()
- global_user_container = self._global_container_stack.getTop()
-
- 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.getTop().setProperty(setting_key, "value", global_user_container.getProperty(setting_key, "value"))
- global_user_container.removeInstance(setting_key)
-
- self.forceUpdate()
+ # 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):
# Force rebuilding the build volume by reloading the global container stack.
# This is a bit of a hack, but it seems quick enough.
- Application.getInstance().globalContainerStackChanged.emit()
+ self._application.globalContainerStackChanged.emit()
@pyqtSlot()
def updateHasMaterialsMetadata(self):
@@ -177,9 +130,11 @@ class MachineSettingsAction(MachineAction):
# In other words: only continue for the UM2 (extended), but not for the UM2+
return
- stacks = ExtruderManager.getInstance().getExtruderStacks()
+ machine_manager = self._application.getMachineManager()
+ extruder_positions = list(self._global_container_stack.extruders.keys())
has_materials = self._global_container_stack.getProperty("machine_gcode_flavor", "value") != "UltiGCode"
+ material_node = None
if has_materials:
if "has_materials" in self._global_container_stack.getMetaData():
self._global_container_stack.setMetaDataEntry("has_materials", True)
@@ -187,101 +142,22 @@ class MachineSettingsAction(MachineAction):
self._global_container_stack.addMetaDataEntry("has_materials", True)
# Set the material container for each extruder to a sane default
- for stack in stacks:
- material_container = stack.material
- if material_container == self._empty_container:
- machine_approximate_diameter = str(round(self._global_container_stack.getProperty("material_diameter", "value")))
- search_criteria = { "type": "material", "definition": "fdmprinter", "id": self._global_container_stack.getMetaDataEntry("preferred_material"), "approximate_diameter": machine_approximate_diameter}
- materials = self._container_registry.findInstanceContainers(**search_criteria)
- if materials:
- stack.material = materials[0]
+ material_manager = self._application.getMaterialManager()
+ material_node = material_manager.getDefaultMaterial(self._global_container_stack, None)
+
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")
- for stack in stacks:
- stack.material = ContainerRegistry.getInstance().getEmptyInstanceContainer()
+ # set materials
+ for position in extruder_positions:
+ machine_manager.setMaterial(position, material_node)
- Application.getInstance().globalContainerStackChanged.emit()
+ self._application.globalContainerStackChanged.emit()
@pyqtSlot(int)
def updateMaterialForDiameter(self, extruder_position: int):
# Updates the material container to a material that matches the material diameter set for the printer
- if not self._global_container_stack:
- return
-
- if not self._global_container_stack.getMetaDataEntry("has_materials", False):
- return
-
- extruder_stack = self._global_container_stack.extruders[str(extruder_position)]
-
- material_diameter = extruder_stack.material.getProperty("material_diameter", "value")
- if not material_diameter:
- # in case of "empty" material
- material_diameter = 0
-
- material_approximate_diameter = str(round(material_diameter))
- machine_diameter = extruder_stack.definitionChanges.getProperty("material_diameter", "value")
- if not machine_diameter:
- if extruder_stack.definition.hasProperty("material_diameter", "value"):
- machine_diameter = extruder_stack.definition.getProperty("material_diameter", "value")
- else:
- machine_diameter = self._global_container_stack.definition.getProperty("material_diameter", "value")
- machine_approximate_diameter = str(round(machine_diameter))
-
- if material_approximate_diameter != machine_approximate_diameter:
- Logger.log("i", "The the currently active material(s) do not match the diameter set for the printer. Finding alternatives.")
-
- if self._global_container_stack.getMetaDataEntry("has_machine_materials", False):
- materials_definition = self._global_container_stack.definition.getId()
- has_material_variants = self._global_container_stack.getMetaDataEntry("has_variants", False)
- else:
- materials_definition = "fdmprinter"
- has_material_variants = False
-
- old_material = extruder_stack.material
- search_criteria = {
- "type": "material",
- "approximate_diameter": machine_approximate_diameter,
- "material": old_material.getMetaDataEntry("material", "value"),
- "brand": old_material.getMetaDataEntry("brand", "value"),
- "supplier": old_material.getMetaDataEntry("supplier", "value"),
- "color_name": old_material.getMetaDataEntry("color_name", "value"),
- "definition": materials_definition
- }
- if has_material_variants:
- search_criteria["variant"] = extruder_stack.variant.getId()
-
- if old_material == self._empty_container:
- search_criteria.pop("material", None)
- search_criteria.pop("supplier", None)
- search_criteria.pop("brand", None)
- search_criteria.pop("definition", None)
- search_criteria["id"] = extruder_stack.getMetaDataEntry("preferred_material")
-
- materials = self._container_registry.findInstanceContainers(**search_criteria)
- if not materials:
- # Same material with new diameter is not found, search for generic version of the same material type
- search_criteria.pop("supplier", None)
- search_criteria.pop("brand", None)
- search_criteria["color_name"] = "Generic"
- materials = self._container_registry.findInstanceContainers(**search_criteria)
- if not materials:
- # Generic material with new diameter is not found, search for preferred material
- search_criteria.pop("color_name", None)
- search_criteria.pop("material", None)
- search_criteria["id"] = extruder_stack.getMetaDataEntry("preferred_material")
- materials = self._container_registry.findInstanceContainers(**search_criteria)
- if not materials:
- # Preferred material with new diameter is not found, search for any material
- search_criteria.pop("id", None)
- materials = self._container_registry.findInstanceContainers(**search_criteria)
- if not materials:
- # Just use empty material as a final fallback
- materials = [self._empty_container]
-
- Logger.log("i", "Selecting new material: %s", materials[0].getId())
-
- extruder_stack.material = materials[0]
+ self._application.getExtruderManager().updateMaterialForDiameter(extruder_position)
diff --git a/plugins/MachineSettingsAction/MachineSettingsAction.qml b/plugins/MachineSettingsAction/MachineSettingsAction.qml
index b815d71acc..b12f8f8696 100644
--- a/plugins/MachineSettingsAction/MachineSettingsAction.qml
+++ b/plugins/MachineSettingsAction/MachineSettingsAction.qml
@@ -70,8 +70,8 @@ Cura.MachineAction
anchors.top: pageTitle.bottom
anchors.topMargin: UM.Theme.getSize("default_margin").height
- property real columnWidth: ((width - 3 * UM.Theme.getSize("default_margin").width) / 2) | 0
- property real labelColumnWidth: columnWidth * 0.5
+ property real columnWidth: Math.round((width - 3 * UM.Theme.getSize("default_margin").width) / 2)
+ property real labelColumnWidth: Math.round(columnWidth / 2)
Tab
{
@@ -165,7 +165,7 @@ Cura.MachineAction
id: gcodeFlavorComboBox
sourceComponent: comboBoxWithOptions
property string settingKey: "machine_gcode_flavor"
- property string label: catalog.i18nc("@label", "Gcode flavor")
+ property string label: catalog.i18nc("@label", "G-code flavor")
property bool forceUpdateOnChange: true
property var afterOnActivate: manager.updateHasMaterialsMetadata
}
@@ -244,6 +244,7 @@ Cura.MachineAction
height: childrenRect.height
width: childrenRect.width
text: machineExtruderCountProvider.properties.description
+ visible: extruderCountModel.count >= 2
Row
{
@@ -307,7 +308,7 @@ Cura.MachineAction
width: settingsTabs.columnWidth
Label
{
- text: catalog.i18nc("@label", "Start Gcode")
+ text: catalog.i18nc("@label", "Start G-code")
font.bold: true
}
Loader
@@ -317,7 +318,7 @@ Cura.MachineAction
property int areaWidth: parent.width
property int areaHeight: parent.height - y
property string settingKey: "machine_start_gcode"
- property string tooltip: catalog.i18nc("@tooltip", "Gcode commands to be executed at the very start.")
+ property string tooltip: catalog.i18nc("@tooltip", "G-code commands to be executed at the very start.")
}
}
@@ -326,7 +327,7 @@ Cura.MachineAction
width: settingsTabs.columnWidth
Label
{
- text: catalog.i18nc("@label", "End Gcode")
+ text: catalog.i18nc("@label", "End G-code")
font.bold: true
}
Loader
@@ -336,7 +337,7 @@ Cura.MachineAction
property int areaWidth: parent.width
property int areaHeight: parent.height - y
property string settingKey: "machine_end_gcode"
- property string tooltip: catalog.i18nc("@tooltip", "Gcode commands to be executed at the very end.")
+ property string tooltip: catalog.i18nc("@tooltip", "G-code commands to be executed at the very end.")
}
}
}
@@ -381,6 +382,11 @@ Cura.MachineAction
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
}
@@ -390,7 +396,7 @@ Cura.MachineAction
visible: Cura.MachineManager.hasMaterials
sourceComponent: numericTextFieldWithUnit
property string settingKey: "material_diameter"
- property string label: catalog.i18nc("@label", "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()
@@ -441,7 +447,7 @@ Cura.MachineAction
width: settingsTabs.columnWidth
Label
{
- text: catalog.i18nc("@label", "Extruder Start Gcode")
+ text: catalog.i18nc("@label", "Extruder Start G-code")
font.bold: true
}
Loader
@@ -459,7 +465,7 @@ Cura.MachineAction
width: settingsTabs.columnWidth
Label
{
- text: catalog.i18nc("@label", "Extruder End Gcode")
+ text: catalog.i18nc("@label", "Extruder End G-code")
font.bold: true
}
Loader
@@ -591,7 +597,7 @@ Cura.MachineAction
const value = propertyProvider.properties.value;
return value ? value : "";
}
- validator: RegExpValidator { regExp: _allowNegative ? /-?[0-9\.]{0,6}/ : /[0-9\.]{0,6}/ }
+ validator: RegExpValidator { regExp: _allowNegative ? /-?[0-9\.,]{0,6}/ : /[0-9\.,]{0,6}/ }
onEditingFinished:
{
if (propertyProvider && text != propertyProvider.properties.value)
@@ -826,10 +832,10 @@ Cura.MachineAction
printHeadPolygon[axis][side] = result;
return result;
}
- validator: RegExpValidator { regExp: /[0-9\.]{0,6}/ }
+ validator: RegExpValidator { regExp: /[0-9\.,]{0,6}/ }
onEditingFinished:
{
- printHeadPolygon[axis][side] = parseFloat(textField.text);
+ 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"]]);
@@ -888,4 +894,4 @@ Cura.MachineAction
watchedProperties: [ "value" ]
storeIndex: manager.containerIndex
}
-}
\ No newline at end of file
+}
diff --git a/plugins/MonitorStage/MonitorStage.py b/plugins/MonitorStage/MonitorStage.py
index 1a999ca896..ed84a8d2ce 100644
--- a/plugins/MonitorStage/MonitorStage.py
+++ b/plugins/MonitorStage/MonitorStage.py
@@ -22,14 +22,7 @@ class MonitorStage(CuraStage):
def _setActivePrintJob(self, print_job):
if self._active_print_job != print_job:
- if self._active_print_job:
- self._active_print_job.stateChanged.disconnect(self._updateIconSource)
self._active_print_job = print_job
- if self._active_print_job:
- self._active_print_job.stateChanged.connect(self._updateIconSource)
-
- # Ensure that the right icon source is returned.
- self._updateIconSource()
def _setActivePrinter(self, printer):
if self._active_printer != printer:
@@ -43,9 +36,6 @@ class MonitorStage(CuraStage):
else:
self._setActivePrintJob(None)
- # Ensure that the right icon source is returned.
- self._updateIconSource()
-
def _onActivePrintJobChanged(self):
self._setActivePrintJob(self._active_printer.activePrintJob)
@@ -58,19 +48,12 @@ class MonitorStage(CuraStage):
new_output_device = Application.getInstance().getMachineManager().printerOutputDevices[0]
if new_output_device != self._printer_output_device:
if self._printer_output_device:
- self._printer_output_device.acceptsCommandsChanged.disconnect(self._updateIconSource)
- self._printer_output_device.connectionStateChanged.disconnect(self._updateIconSource)
self._printer_output_device.printersChanged.disconnect(self._onActivePrinterChanged)
self._printer_output_device = new_output_device
- self._printer_output_device.acceptsCommandsChanged.connect(self._updateIconSource)
self._printer_output_device.printersChanged.connect(self._onActivePrinterChanged)
- self._printer_output_device.connectionStateChanged.connect(self._updateIconSource)
self._setActivePrinter(self._printer_output_device.activePrinter)
-
- # Force an update of the icon source
- self._updateIconSource()
except IndexError:
pass
@@ -80,7 +63,6 @@ class MonitorStage(CuraStage):
self._onOutputDevicesChanged()
self._updateMainOverlay()
self._updateSidebar()
- self._updateIconSource()
def _updateMainOverlay(self):
main_component_path = os.path.join(PluginRegistry.getInstance().getPluginPath("MonitorStage"), "MonitorMainView.qml")
@@ -90,46 +72,3 @@ class MonitorStage(CuraStage):
# TODO: currently the sidebar component for prepare and monitor stages is the same, this will change with the printer output device refactor!
sidebar_component_path = os.path.join(Resources.getPath(Application.getInstance().ResourceTypes.QmlFiles), "Sidebar.qml")
self.addDisplayComponent("sidebar", sidebar_component_path)
-
- def _updateIconSource(self):
- if Application.getInstance().getTheme() is not None:
- icon_name = self._getActiveOutputDeviceStatusIcon()
- self.setIconSource(Application.getInstance().getTheme().getIcon(icon_name))
-
- ## Find the correct status icon depending on the active output device state
- def _getActiveOutputDeviceStatusIcon(self):
- # We assume that you are monitoring the device with the highest priority.
- try:
- output_device = Application.getInstance().getMachineManager().printerOutputDevices[0]
- except IndexError:
- return "tab_status_unknown"
-
- if not output_device.acceptsCommands:
- return "tab_status_unknown"
-
- if output_device.activePrinter is None:
- return "tab_status_connected"
-
- # TODO: refactor to use enum instead of hardcoded strings?
- if output_device.activePrinter.state == "maintenance":
- return "tab_status_busy"
-
- if output_device.activePrinter.activePrintJob is None:
- return "tab_status_connected"
-
- if output_device.activePrinter.activePrintJob.state in ["printing", "pre_print", "pausing", "resuming"]:
- return "tab_status_busy"
-
- if output_device.activePrinter.activePrintJob.state == "wait_cleanup":
- return "tab_status_finished"
-
- if output_device.activePrinter.activePrintJob.state in ["ready", ""]:
- return "tab_status_connected"
-
- if output_device.activePrinter.activePrintJob.state == "paused":
- return "tab_status_paused"
-
- if output_device.activePrinter.activePrintJob.state == "error":
- return "tab_status_stopped"
-
- return "tab_status_unknown"
diff --git a/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml b/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml
index 0976dd5df6..7872908ee8 100644
--- a/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml
+++ b/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml
@@ -246,7 +246,7 @@ Item {
Button
{
- width: Math.floor(UM.Theme.getSize("setting").height / 2)
+ width: Math.round(UM.Theme.getSize("setting").height / 2)
height: UM.Theme.getSize("setting").height
onClicked: addedSettingsModel.setVisible(model.key, false)
diff --git a/plugins/PluginBrowser/PluginBrowser.py b/plugins/PluginBrowser/PluginBrowser.py
index 35b88b3465..c8a5e1e545 100644
--- a/plugins/PluginBrowser/PluginBrowser.py
+++ b/plugins/PluginBrowser/PluginBrowser.py
@@ -1,31 +1,36 @@
# Copyright (c) 2017 Ultimaker B.V.
# PluginBrowser is released under the terms of the LGPLv3 or higher.
+
+from PyQt5.QtCore import QUrl, QObject, Qt, pyqtProperty, pyqtSignal, pyqtSlot
+from PyQt5.QtNetwork import QNetworkAccessManager, QNetworkRequest, QNetworkReply
+
+from UM.Application import Application
+from UM.Qt.ListModel import ListModel
+from UM.Logger import Logger
+from UM.PluginRegistry import PluginRegistry
+from UM.Qt.Bindings.PluginsModel import PluginsModel
from UM.Extension import Extension
from UM.i18n import i18nCatalog
-from UM.Logger import Logger
-from UM.Qt.ListModel import ListModel
-from UM.PluginRegistry import PluginRegistry
-from UM.Application import Application
+
from UM.Version import Version
from UM.Message import Message
-from PyQt5.QtNetwork import QNetworkAccessManager, QNetworkRequest, QNetworkReply
-from PyQt5.QtCore import QUrl, QObject, Qt, pyqtProperty, pyqtSignal, pyqtSlot
-
import json
import os
import tempfile
import platform
import zipfile
+import shutil
+
+from cura.CuraApplication import CuraApplication
i18n_catalog = i18nCatalog("cura")
-
class PluginBrowser(QObject, Extension):
def __init__(self, parent=None):
super().__init__(parent)
- self._api_version = 2
+ self._api_version = 4
self._api_url = "http://software.ultimaker.com/cura/v%s/" % self._api_version
self._plugin_list_request = None
@@ -34,11 +39,18 @@ class PluginBrowser(QObject, Extension):
self._download_plugin_reply = None
self._network_manager = None
+ self._plugin_registry = Application.getInstance().getPluginRegistry()
self._plugins_metadata = []
self._plugins_model = None
+ # Can be 'installed' or 'availble'
+ self._view = "available"
+
+ self._restart_required = False
+
self._dialog = None
+ self._restartDialog = None
self._download_progress = 0
self._is_downloading = False
@@ -52,16 +64,29 @@ class PluginBrowser(QObject, Extension):
)
]
- # Installed plugins are really installed after reboot. In order to prevent the user from downloading the
- # same file over and over again, we keep track of the upgraded plugins.
+ # Installed plugins are really installed after reboot. In order to
+ # prevent the user from downloading the same file over and over again,
+ # we keep track of the upgraded plugins.
+
+ # NOTE: This will be depreciated in favor of the 'status' system.
self._newly_installed_plugin_ids = []
+ self._newly_uninstalled_plugin_ids = []
+
+ self._plugin_statuses = {} # type: Dict[str, str]
# variables for the license agreement dialog
self._license_dialog_plugin_name = ""
self._license_dialog_license_content = ""
self._license_dialog_plugin_file_location = ""
+ self._restart_dialog_message = ""
showLicenseDialog = pyqtSignal()
+ showRestartDialog = pyqtSignal()
+ pluginsMetadataChanged = pyqtSignal()
+ onDownloadProgressChanged = pyqtSignal()
+ onIsDownloadingChanged = pyqtSignal()
+ restartRequiredChanged = pyqtSignal()
+ viewChanged = pyqtSignal()
@pyqtSlot(result = str)
def getLicenseDialogPluginName(self):
@@ -75,15 +100,19 @@ class PluginBrowser(QObject, Extension):
def getLicenseDialogLicenseContent(self):
return self._license_dialog_license_content
+ @pyqtSlot(result = str)
+ def getRestartDialogMessage(self):
+ return self._restart_dialog_message
+
def openLicenseDialog(self, plugin_name, license_content, plugin_file_location):
self._license_dialog_plugin_name = plugin_name
self._license_dialog_license_content = license_content
self._license_dialog_plugin_file_location = plugin_file_location
self.showLicenseDialog.emit()
- pluginsMetadataChanged = pyqtSignal()
- onDownloadProgressChanged = pyqtSignal()
- onIsDownloadingChanged = pyqtSignal()
+ def openRestartDialog(self, message):
+ self._restart_dialog_message = message
+ self.showRestartDialog.emit()
@pyqtProperty(bool, notify = onIsDownloadingChanged)
def isDownloading(self):
@@ -179,17 +208,46 @@ class PluginBrowser(QObject, Extension):
@pyqtSlot(str)
def installPlugin(self, file_path):
+ # Ensure that it starts with a /, as otherwise it doesn't work on windows.
if not file_path.startswith("/"):
- location = "/" + file_path # Ensure that it starts with a /, as otherwise it doesn't work on windows.
+ location = "/" + file_path
else:
location = file_path
+
result = PluginRegistry.getInstance().installPlugin("file://" + location)
self._newly_installed_plugin_ids.append(result["id"])
self.pluginsMetadataChanged.emit()
+ self.openRestartDialog(result["message"])
+ self._restart_required = True
+ self.restartRequiredChanged.emit()
+ # Application.getInstance().messageBox(i18n_catalog.i18nc("@window:title", "Plugin browser"), result["message"])
+
+ @pyqtSlot(str)
+ def removePlugin(self, plugin_id):
+ result = PluginRegistry.getInstance().uninstallPlugin(plugin_id)
+
+ self._newly_uninstalled_plugin_ids.append(result["id"])
+ self.pluginsMetadataChanged.emit()
+
+ self._restart_required = True
+ self.restartRequiredChanged.emit()
+
Application.getInstance().messageBox(i18n_catalog.i18nc("@window:title", "Plugin browser"), result["message"])
+ @pyqtSlot(str)
+ def enablePlugin(self, plugin_id):
+ self._plugin_registry.enablePlugin(plugin_id)
+ self.pluginsMetadataChanged.emit()
+ Logger.log("i", "%s was set as 'active'", id)
+
+ @pyqtSlot(str)
+ def disablePlugin(self, plugin_id):
+ self._plugin_registry.disablePlugin(plugin_id)
+ self.pluginsMetadataChanged.emit()
+ Logger.log("i", "%s was set as 'deactive'", id)
+
@pyqtProperty(int, notify = onDownloadProgressChanged)
def downloadProgress(self):
return self._download_progress
@@ -221,55 +279,70 @@ class PluginBrowser(QObject, Extension):
self.setDownloadProgress(0)
self.setIsDownloading(False)
+ @pyqtSlot(str)
+ def setView(self, view):
+ self._view = view
+ self.viewChanged.emit()
+ self.pluginsMetadataChanged.emit()
+
@pyqtProperty(QObject, notify=pluginsMetadataChanged)
def pluginsModel(self):
- if self._plugins_model is None:
- self._plugins_model = ListModel()
- self._plugins_model.addRoleName(Qt.UserRole + 1, "name")
- self._plugins_model.addRoleName(Qt.UserRole + 2, "version")
- self._plugins_model.addRoleName(Qt.UserRole + 3, "short_description")
- self._plugins_model.addRoleName(Qt.UserRole + 4, "author")
- self._plugins_model.addRoleName(Qt.UserRole + 5, "already_installed")
- self._plugins_model.addRoleName(Qt.UserRole + 6, "file_location")
- self._plugins_model.addRoleName(Qt.UserRole + 7, "can_upgrade")
- else:
- self._plugins_model.clear()
- items = []
- for metadata in self._plugins_metadata:
- items.append({
- "name": metadata["label"],
- "version": metadata["version"],
- "short_description": metadata["short_description"],
- "author": metadata["author"],
- "already_installed": self._checkAlreadyInstalled(metadata["id"]),
- "file_location": metadata["file_location"],
- "can_upgrade": self._checkCanUpgrade(metadata["id"], metadata["version"])
- })
- self._plugins_model.setItems(items)
+ self._plugins_model = PluginsModel(None, self._view)
+ # self._plugins_model.update()
+
+ # Check each plugin the registry for matching plugin from server
+ # metadata, and if found, compare the versions. Higher version sets
+ # 'can_upgrade' to 'True':
+ for plugin in self._plugins_model.items:
+ if self._checkCanUpgrade(plugin["id"], plugin["version"]):
+ plugin["can_upgrade"] = True
+
+ for item in self._plugins_metadata:
+ if item["id"] == plugin["id"]:
+ plugin["update_url"] = item["file_location"]
+
return self._plugins_model
+
+
def _checkCanUpgrade(self, id, version):
- plugin_registry = PluginRegistry.getInstance()
- metadata = plugin_registry.getMetaData(id)
- if metadata != {}:
- if id in self._newly_installed_plugin_ids:
- return False # We already updated this plugin.
- current_version = Version(metadata["plugin"]["version"])
- new_version = Version(version)
- if new_version > current_version:
- return True
+
+ # TODO: This could maybe be done more efficiently using a dictionary...
+
+ # Scan plugin server data for plugin with the given id:
+ for plugin in self._plugins_metadata:
+ if id == plugin["id"]:
+ reg_version = Version(version)
+ new_version = Version(plugin["version"])
+ if new_version > reg_version:
+ Logger.log("i", "%s has an update availible: %s", plugin["id"], plugin["version"])
+ return True
return False
def _checkAlreadyInstalled(self, id):
- plugin_registry = PluginRegistry.getInstance()
- metadata = plugin_registry.getMetaData(id)
- if metadata != {}:
+ metadata = self._plugin_registry.getMetaData(id)
+ # We already installed this plugin, but the registry just doesn't know it yet.
+ if id in self._newly_installed_plugin_ids:
+ return True
+ # We already uninstalled this plugin, but the registry just doesn't know it yet:
+ elif id in self._newly_uninstalled_plugin_ids:
+ return False
+ elif metadata != {}:
return True
else:
- if id in self._newly_installed_plugin_ids:
- return True # We already installed this plugin, but the registry just doesn't know it yet.
return False
+ def _checkInstallStatus(self, plugin_id):
+ if plugin_id in self._plugin_registry.getInstalledPlugins():
+ return "installed"
+ else:
+ return "uninstalled"
+
+ def _checkEnabled(self, id):
+ if id in self._plugin_registry.getActivePlugins():
+ return True
+ return False
+
def _onRequestFinished(self, reply):
reply_url = reply.url().toString()
if reply.error() == QNetworkReply.TimeoutError:
@@ -290,7 +363,10 @@ class PluginBrowser(QObject, Extension):
if reply_url == self._api_url + "plugins":
try:
json_data = json.loads(bytes(reply.readAll()).decode("utf-8"))
+
+ # Add metadata to the manager:
self._plugins_metadata = json_data
+ self._plugin_registry.addExternalPlugins(self._plugins_metadata)
self.pluginsMetadataChanged.emit()
except json.decoder.JSONDecodeError:
Logger.log("w", "Received an invalid print job state message: Not valid JSON.")
@@ -316,3 +392,15 @@ class PluginBrowser(QObject, Extension):
self._network_manager = QNetworkAccessManager()
self._network_manager.finished.connect(self._onRequestFinished)
self._network_manager.networkAccessibleChanged.connect(self._onNetworkAccesibleChanged)
+
+ @pyqtProperty(bool, notify=restartRequiredChanged)
+ def restartRequired(self):
+ return self._restart_required
+
+ @pyqtProperty(str, notify=viewChanged)
+ def viewing(self):
+ return self._view
+
+ @pyqtSlot()
+ def restart(self):
+ CuraApplication.getInstance().quit()
diff --git a/plugins/PluginBrowser/PluginBrowser.qml b/plugins/PluginBrowser/PluginBrowser.qml
index 13000d23ad..ec4c2a9135 100644
--- a/plugins/PluginBrowser/PluginBrowser.qml
+++ b/plugins/PluginBrowser/PluginBrowser.qml
@@ -1,191 +1,209 @@
-import UM 1.1 as UM
+// Copyright (c) 2017 Ultimaker B.V.
+// PluginBrowser is released under the terms of the LGPLv3 or higher.
+
import QtQuick 2.2
import QtQuick.Dialogs 1.1
import QtQuick.Window 2.2
-import QtQuick.Controls 1.1
+import QtQuick.Controls 1.4
+import QtQuick.Controls.Styles 1.4
-UM.Dialog
-{
+// TODO: Switch to QtQuick.Controls 2.x and remove QtQuick.Controls.Styles
+
+import UM 1.1 as UM
+
+Window {
id: base
- title: catalog.i18nc("@title:window", "Find & Update plugins")
- width: 600 * screenScaleFactor
- height: 450 * screenScaleFactor
+ title: catalog.i18nc("@title:tab", "Plugins");
+ width: 800 * screenScaleFactor
+ height: 640 * screenScaleFactor
minimumWidth: 350 * screenScaleFactor
minimumHeight: 350 * screenScaleFactor
- Item
- {
- anchors.fill: parent
- Item
- {
- id: topBar
- height: childrenRect.height;
- width: parent.width
- Label
- {
- id: introText
- text: catalog.i18nc("@label", "Here you can find a list of Third Party plugins.")
- width: parent.width
- height: 30
- }
+ color: UM.Theme.getColor("sidebar")
- Button
- {
- id: refresh
- text: catalog.i18nc("@action:button", "Refresh")
- onClicked: manager.requestPluginList()
- anchors.right: parent.right
- enabled: !manager.isDownloading
+ Item {
+ id: view
+ anchors {
+ fill: parent
+ leftMargin: UM.Theme.getSize("default_margin").width
+ rightMargin: UM.Theme.getSize("default_margin").width
+ topMargin: UM.Theme.getSize("default_margin").height
+ bottomMargin: UM.Theme.getSize("default_margin").height
+ }
+
+ Rectangle {
+ id: topBar
+ width: parent.width
+ color: "transparent"
+ height: childrenRect.height
+
+ Row {
+ spacing: 12
+ height: childrenRect.height
+ width: childrenRect.width
+ anchors.horizontalCenter: parent.horizontalCenter
+
+ Button {
+ text: "Install"
+ style: ButtonStyle {
+ background: Rectangle {
+ color: "transparent"
+ implicitWidth: 96
+ implicitHeight: 48
+ Rectangle {
+ visible: manager.viewing == "available" ? true : false
+ color: UM.Theme.getColor("primary")
+ anchors.bottom: parent.bottom
+ width: parent.width
+ height: 3
+ }
+ }
+ label: Text {
+ text: control.text
+ color: UM.Theme.getColor("text")
+ font {
+ pixelSize: 15
+ }
+ verticalAlignment: Text.AlignVCenter
+ horizontalAlignment: Text.AlignHCenter
+ }
+ }
+ onClicked: manager.setView("available")
+ }
+
+ Button {
+ text: "Manage"
+ style: ButtonStyle {
+ background: Rectangle {
+ color: "transparent"
+ implicitWidth: 96
+ implicitHeight: 48
+ Rectangle {
+ visible: manager.viewing == "installed" ? true : false
+ color: UM.Theme.getColor("primary")
+ anchors.bottom: parent.bottom
+ width: parent.width
+ height: 3
+ }
+ }
+ label: Text {
+ text: control.text
+ color: UM.Theme.getColor("text")
+ font {
+ pixelSize: 15
+ }
+ verticalAlignment: Text.AlignVCenter
+ horizontalAlignment: Text.AlignHCenter
+ }
+ }
+ onClicked: manager.setView("installed")
+ }
}
}
- ScrollView
- {
+
+ // Scroll view breaks in QtQuick.Controls 2.x
+ ScrollView {
+ id: installedPluginList
width: parent.width
- anchors.top: topBar.bottom
- anchors.bottom: bottomBar.top
- anchors.bottomMargin: UM.Theme.getSize("default_margin").height
+ height: 400
+
+ anchors {
+ top: topBar.bottom
+ topMargin: UM.Theme.getSize("default_margin").height
+ bottom: bottomBar.top
+ bottomMargin: UM.Theme.getSize("default_margin").height
+ }
+
frameVisible: true
- ListView
- {
+
+ ListView {
id: pluginList
- model: manager.pluginsModel
+ property var activePlugin
+ property var filter: "installed"
+
anchors.fill: parent
- property var activePlugin
- delegate: pluginDelegate
+ model: manager.pluginsModel
+ delegate: PluginEntry {}
}
}
- Item
- {
+
+ Rectangle {
id: bottomBar
width: parent.width
- height: closeButton.height
+ height: childrenRect.height
+ color: "transparent"
anchors.bottom: parent.bottom
- anchors.left: parent.left
- ProgressBar
- {
- id: progressbar
- anchors.bottom: parent.bottom
- minimumValue: 0;
- maximumValue: 100
- anchors.left:parent.left
+
+ Label {
+ visible: manager.restartRequired
+ text: "You will need to restart Cura before changes in plugins have effect."
+ height: 30
+ verticalAlignment: Text.AlignVCenter
+ }
+ Button {
+ id: restartChangedButton
+ text: "Quit Cura"
anchors.right: closeButton.left
anchors.rightMargin: UM.Theme.getSize("default_margin").width
- value: manager.isDownloading ? manager.downloadProgress : 0
+ visible: manager.restartRequired
+ iconName: "dialog-restart"
+ onClicked: manager.restart()
+ style: ButtonStyle {
+ background: Rectangle {
+ implicitWidth: 96
+ implicitHeight: 30
+ color: UM.Theme.getColor("primary")
+ }
+ label: Text {
+ verticalAlignment: Text.AlignVCenter
+ color: UM.Theme.getColor("button_text")
+ font {
+ pixelSize: 13
+ bold: true
+ }
+ text: control.text
+ horizontalAlignment: Text.AlignHCenter
+ }
+ }
}
- Button
- {
+ Button {
id: closeButton
text: catalog.i18nc("@action:button", "Close")
iconName: "dialog-close"
- onClicked:
- {
- if (manager.isDownloading)
- {
+ onClicked: {
+ if ( manager.isDownloading ) {
manager.cancelDownload()
}
base.close();
}
- anchors.bottom: parent.bottom
anchors.right: parent.right
- }
- }
-
- Item
- {
- SystemPalette { id: palette }
- Component
- {
- id: pluginDelegate
- Rectangle
- {
- width: pluginList.width;
- height: texts.height;
- color: index % 2 ? palette.base : palette.alternateBase
- Column
- {
- id: texts
- width: parent.width
- height: childrenRect.height
- anchors.left: parent.left
- anchors.leftMargin: UM.Theme.getSize("default_margin").width
- anchors.right: downloadButton.left
- anchors.rightMargin: UM.Theme.getSize("default_margin").width
- Label
- {
- text: "" + model.name + "" + ((model.author !== "") ? (" - " + model.author) : "")
- width: contentWidth
- height: contentHeight + UM.Theme.getSize("default_margin").height
- verticalAlignment: Text.AlignVCenter
- }
-
- Label
- {
- text: model.short_description
- width: parent.width
- height: contentHeight + UM.Theme.getSize("default_margin").height
- wrapMode: Text.WordWrap
- verticalAlignment: Text.AlignVCenter
+ style: ButtonStyle {
+ background: Rectangle {
+ color: "transparent"
+ implicitWidth: 96
+ implicitHeight: 30
+ border {
+ width: 1
+ color: UM.Theme.getColor("lining")
}
}
- Button
- {
- id: downloadButton
- text:
- {
- if (manager.isDownloading && pluginList.activePlugin == model)
- {
- return catalog.i18nc("@action:button", "Cancel");
- }
- else if (model.already_installed)
- {
- if (model.can_upgrade)
- {
- return catalog.i18nc("@action:button", "Upgrade");
- }
- return catalog.i18nc("@action:button", "Installed");
- }
- return catalog.i18nc("@action:button", "Download");
- }
- onClicked:
- {
- if(!manager.isDownloading)
- {
- pluginList.activePlugin = model;
- manager.downloadAndInstallPlugin(model.file_location);
- }
- else
- {
- manager.cancelDownload();
- }
- }
- anchors.right: parent.right
- anchors.rightMargin: UM.Theme.getSize("default_margin").width
- anchors.verticalCenter: parent.verticalCenter
- enabled:
- {
- if (manager.isDownloading)
- {
- return (pluginList.activePlugin == model);
- }
- else
- {
- return (!model.already_installed || model.can_upgrade);
- }
- }
+ label: Text {
+ verticalAlignment: Text.AlignVCenter
+ color: UM.Theme.getColor("text")
+ text: control.text
+ horizontalAlignment: Text.AlignHCenter
}
}
-
}
}
+
UM.I18nCatalog { id: catalog; name: "cura" }
- Connections
- {
+ Connections {
target: manager
- onShowLicenseDialog:
- {
+ onShowLicenseDialog: {
licenseDialog.pluginName = manager.getLicenseDialogPluginName();
licenseDialog.licenseContent = manager.getLicenseDialogLicenseContent();
licenseDialog.pluginFileLocation = manager.getLicenseDialogPluginFileLocation();
@@ -193,8 +211,7 @@ UM.Dialog
}
}
- UM.Dialog
- {
+ UM.Dialog {
id: licenseDialog
title: catalog.i18nc("@title:window", "Plugin License Agreement")
@@ -258,5 +275,94 @@ UM.Dialog
}
]
}
+
+ Connections {
+ target: manager
+ onShowRestartDialog: {
+ restartDialog.message = manager.getRestartDialogMessage();
+ restartDialog.show();
+ }
+ }
+
+ Window {
+ id: restartDialog
+ // title: catalog.i18nc("@title:tab", "Plugins");
+ width: 360 * screenScaleFactor
+ height: 120 * screenScaleFactor
+ minimumWidth: 360 * screenScaleFactor
+ minimumHeight: 120 * screenScaleFactor
+ color: UM.Theme.getColor("sidebar")
+ property var message;
+
+ Text {
+ id: message
+ anchors {
+ left: parent.left
+ leftMargin: UM.Theme.getSize("default_margin").width
+ top: parent.top
+ topMargin: UM.Theme.getSize("default_margin").height
+ }
+ text: restartDialog.message != null ? restartDialog.message : ""
+ }
+ Button {
+ id: laterButton
+ text: "Later"
+ onClicked: restartDialog.close();
+ anchors {
+ left: parent.left
+ leftMargin: UM.Theme.getSize("default_margin").width
+ bottom: parent.bottom
+ bottomMargin: UM.Theme.getSize("default_margin").height
+ }
+ style: ButtonStyle {
+ background: Rectangle {
+ color: "transparent"
+ implicitWidth: 96
+ implicitHeight: 30
+ border {
+ width: 1
+ color: UM.Theme.getColor("lining")
+ }
+ }
+ label: Text {
+ verticalAlignment: Text.AlignVCenter
+ color: UM.Theme.getColor("text")
+ text: control.text
+ horizontalAlignment: Text.AlignHCenter
+ }
+ }
+ }
+
+
+ Button {
+ id: restartButton
+ text: "Quit Cura"
+ anchors {
+ right: parent.right
+ rightMargin: UM.Theme.getSize("default_margin").width
+ bottom: parent.bottom
+ bottomMargin: UM.Theme.getSize("default_margin").height
+ }
+ onClicked: manager.restart()
+ style: ButtonStyle {
+ background: Rectangle {
+ implicitWidth: 96
+ implicitHeight: 30
+ color: UM.Theme.getColor("primary")
+ }
+ label: Text {
+ verticalAlignment: Text.AlignVCenter
+ color: UM.Theme.getColor("button_text")
+ font {
+ pixelSize: 13
+ bold: true
+ }
+ text: control.text
+ horizontalAlignment: Text.AlignHCenter
+ }
+ }
+ }
+ }
+
}
}
diff --git a/plugins/PluginBrowser/PluginEntry.qml b/plugins/PluginBrowser/PluginEntry.qml
new file mode 100644
index 0000000000..eff9eb8943
--- /dev/null
+++ b/plugins/PluginBrowser/PluginEntry.qml
@@ -0,0 +1,474 @@
+// Copyright (c) 2017 Ultimaker B.V.
+// PluginBrowser is released under the terms of the LGPLv3 or higher.
+
+import QtQuick 2.2
+import QtQuick.Dialogs 1.1
+import QtQuick.Window 2.2
+import QtQuick.Controls 1.4
+import QtQuick.Controls.Styles 1.4
+
+// TODO: Switch to QtQuick.Controls 2.x and remove QtQuick.Controls.Styles
+
+import UM 1.1 as UM
+
+Component {
+ id: pluginDelegate
+
+ Rectangle {
+
+ // Don't show required plugins as they can't be managed anyway:
+ height: !model.required ? 84 : 0
+ visible: !model.required ? true : false
+ color: "transparent"
+ anchors {
+ left: parent.left
+ leftMargin: UM.Theme.getSize("default_margin").width
+ right: parent.right
+ rightMargin: UM.Theme.getSize("default_margin").width
+ }
+
+
+ // Bottom border:
+ Rectangle {
+ color: UM.Theme.getColor("lining")
+ width: parent.width
+ height: 1
+ anchors.bottom: parent.bottom
+ }
+
+ // Plugin info
+ Column {
+ id: pluginInfo
+
+ property var color: model.enabled ? UM.Theme.getColor("text") : UM.Theme.getColor("lining")
+
+ // Styling:
+ height: parent.height
+ anchors {
+ left: parent.left
+ top: parent.top
+ topMargin: UM.Theme.getSize("default_margin").height
+ right: authorInfo.left
+ rightMargin: UM.Theme.getSize("default_margin").width
+ }
+
+
+ Label {
+ text: model.name
+ width: parent.width
+ height: 24
+ wrapMode: Text.WordWrap
+ verticalAlignment: Text.AlignVCenter
+ font {
+ pixelSize: 13
+ bold: true
+ }
+ color: pluginInfo.color
+
+ }
+
+ Text {
+ text: model.description
+ width: parent.width
+ height: 36
+ clip: true
+ wrapMode: Text.WordWrap
+ color: pluginInfo.color
+ elide: Text.ElideRight
+ }
+ }
+
+ // Author info
+ Column {
+ id: authorInfo
+ width: 192
+ height: parent.height
+ anchors {
+ top: parent.top
+ topMargin: UM.Theme.getSize("default_margin").height
+ right: pluginActions.left
+ rightMargin: UM.Theme.getSize("default_margin").width
+ }
+
+ Label {
+ text: ""+model.author+""
+ width: parent.width
+ height: 24
+ wrapMode: Text.WordWrap
+ verticalAlignment: Text.AlignVCenter
+ horizontalAlignment: Text.AlignLeft
+ onLinkActivated: Qt.openUrlExternally("mailto:"+model.author_email+"?Subject=Cura: "+model.name+" Plugin")
+ color: model.enabled ? UM.Theme.getColor("text") : UM.Theme.getColor("lining")
+ }
+ }
+
+ // Plugin actions
+ Row {
+ id: pluginActions
+
+ width: 96
+ height: parent.height
+ anchors {
+ top: parent.top
+ right: parent.right
+ topMargin: UM.Theme.getSize("default_margin").height
+ }
+ layoutDirection: Qt.RightToLeft
+ spacing: UM.Theme.getSize("default_margin").width
+
+ // For 3rd-Party Plugins:
+ Button {
+ id: installButton
+ text: {
+ if ( manager.isDownloading && pluginList.activePlugin == model ) {
+ return catalog.i18nc( "@action:button", "Cancel" );
+ } else {
+ if (model.can_upgrade) {
+ return catalog.i18nc("@action:button", "Update");
+ }
+ return catalog.i18nc("@action:button", "Install");
+ }
+ }
+ visible: model.external && ((model.status !== "installed") || model.can_upgrade)
+ style: ButtonStyle {
+ background: Rectangle {
+ implicitWidth: 96
+ implicitHeight: 30
+ color: "transparent"
+ border {
+ width: 1
+ color: UM.Theme.getColor("lining")
+ }
+ }
+ label: Label {
+ text: control.text
+ color: UM.Theme.getColor("text")
+ verticalAlignment: Text.AlignVCenter
+ horizontalAlignment: Text.AlignHCenter
+ }
+ }
+ onClicked: {
+ if ( manager.isDownloading && pluginList.activePlugin == model ) {
+ manager.cancelDownload();
+ } else {
+ pluginList.activePlugin = model;
+ if ( model.can_upgrade ) {
+ manager.downloadAndInstallPlugin( model.update_url );
+ } else {
+ manager.downloadAndInstallPlugin( model.file_location );
+ }
+
+ }
+ }
+ }
+ Button {
+ id: removeButton
+ text: "Uninstall"
+ visible: model.can_uninstall && model.status == "installed"
+ enabled: !manager.isDownloading
+ style: ButtonStyle {
+ background: Rectangle {
+ implicitWidth: 96
+ implicitHeight: 30
+ color: "transparent"
+ border {
+ width: 1
+ color: UM.Theme.getColor("lining")
+ }
+ }
+ label: Text {
+ text: control.text
+ color: UM.Theme.getColor("text")
+ verticalAlignment: Text.AlignVCenter
+ horizontalAlignment: Text.AlignHCenter
+ }
+ }
+ onClicked: manager.removePlugin( model.id )
+ }
+
+ // For Ultimaker Plugins:
+ Button {
+ id: enableButton
+ text: "Enable"
+ visible: !model.external && model.enabled == false
+ style: ButtonStyle {
+ background: Rectangle {
+ implicitWidth: 96
+ implicitHeight: 30
+ color: "transparent"
+ border {
+ width: 1
+ color: UM.Theme.getColor("lining")
+ }
+ }
+ label: Text {
+ text: control.text
+ color: UM.Theme.getColor("text")
+ verticalAlignment: Text.AlignVCenter
+ horizontalAlignment: Text.AlignHCenter
+ }
+ }
+ onClicked: {
+ manager.enablePlugin(model.id);
+ }
+ }
+ Button {
+ id: disableButton
+ text: "Disable"
+ visible: !model.external && model.enabled == true
+ style: ButtonStyle {
+ background: Rectangle {
+ implicitWidth: 96
+ implicitHeight: 30
+ color: "transparent"
+ border {
+ width: 1
+ color: UM.Theme.getColor("lining")
+ }
+ }
+ label: Text {
+ text: control.text
+ color: UM.Theme.getColor("text")
+ verticalAlignment: Text.AlignVCenter
+ horizontalAlignment: Text.AlignHCenter
+ }
+ }
+ onClicked: {
+ manager.disablePlugin(model.id);
+ }
+ }
+ /*
+ Rectangle {
+ id: removeControls
+ visible: model.status == "installed" && model.enabled
+ width: 96
+ height: 30
+ color: "transparent"
+ Button {
+ id: removeButton
+ text: "Disable"
+ enabled: {
+ if ( manager.isDownloading && pluginList.activePlugin == model ) {
+ return false;
+ } else if ( model.required ) {
+ return false;
+ } else {
+ return true;
+ }
+ }
+ onClicked: {
+ manager.disablePlugin(model.id);
+ }
+ style: ButtonStyle {
+ background: Rectangle {
+ color: "white"
+ implicitWidth: 96
+ implicitHeight: 30
+ border {
+ width: 1
+ color: UM.Theme.getColor("lining")
+ }
+ }
+ label: Text {
+ verticalAlignment: Text.AlignVCenter
+ color: "grey"
+ text: control.text
+ horizontalAlignment: Text.AlignLeft
+ }
+ }
+ }
+ Button {
+ id: removeDropDown
+ property bool open: false
+ UM.RecolorImage {
+ anchors.centerIn: parent
+ height: 10
+ width: 10
+ source: UM.Theme.getIcon("arrow_bottom")
+ color: "grey"
+ }
+ enabled: {
+ if ( manager.isDownloading && pluginList.activePlugin == model ) {
+ return false;
+ } else if ( model.required ) {
+ return false;
+ } else {
+ return true;
+ }
+ }
+ anchors.right: parent.right
+ style: ButtonStyle {
+ background: Rectangle {
+ color: "transparent"
+ implicitWidth: 30
+ implicitHeight: 30
+ }
+ label: Text {
+ verticalAlignment: Text.AlignVCenter
+ color: "grey"
+ text: control.text
+ horizontalAlignment: Text.AlignHCenter
+ }
+ }
+
+
+
+ // For the disable option:
+ // onClicked: pluginList.model.setEnabled(model.id, checked)
+
+ onClicked: {
+ if ( !removeDropDown.open ) {
+ removeDropDown.open = true
+ }
+ else {
+ removeDropDown.open = false
+ }
+ }
+ }
+
+ Rectangle {
+ id: divider
+ width: 1
+ height: parent.height
+ anchors.right: removeDropDown.left
+ color: UM.Theme.getColor("lining")
+ }
+
+ Column {
+ id: options
+ anchors {
+ top: removeButton.bottom
+ left: parent.left
+ right: parent.right
+ }
+ height: childrenRect.height
+ visible: removeDropDown.open
+
+ Button {
+ id: disableButton
+ text: "Remove"
+ height: 30
+ width: parent.width
+ onClicked: {
+ removeDropDown.open = false;
+ manager.removePlugin( model.id );
+ }
+ }
+ }
+ }
+ */
+ /*
+ Button {
+ id: enableButton
+ visible: !model.enabled && model.status == "installed"
+ onClicked: manager.enablePlugin( model.id );
+
+ text: "Enable"
+ style: ButtonStyle {
+ background: Rectangle {
+ color: "transparent"
+ implicitWidth: 96
+ implicitHeight: 30
+ border {
+ width: 1
+ color: UM.Theme.getColor("lining")
+ }
+ }
+ label: Text {
+ verticalAlignment: Text.AlignVCenter
+ color: UM.Theme.getColor("text")
+ text: control.text
+ horizontalAlignment: Text.AlignHCenter
+ }
+ }
+ }
+
+ Button {
+ id: updateButton
+ visible: model.status == "installed" && model.can_upgrade && model.enabled
+ // visible: model.already_installed
+ text: {
+ // If currently downloading:
+ if ( manager.isDownloading && pluginList.activePlugin == model ) {
+ return catalog.i18nc( "@action:button", "Cancel" );
+ } else {
+ return catalog.i18nc("@action:button", "Update");
+ }
+ }
+ style: ButtonStyle {
+ background: Rectangle {
+ color: UM.Theme.getColor("primary")
+ implicitWidth: 96
+ implicitHeight: 30
+ // radius: 4
+ }
+ label: Text {
+ verticalAlignment: Text.AlignVCenter
+ color: "white"
+ text: control.text
+ horizontalAlignment: Text.AlignHCenter
+ }
+ }
+ }
+ Button {
+ id: externalControls
+ visible: model.status == "available" ? true : false
+ text: {
+ // If currently downloading:
+ if ( manager.isDownloading && pluginList.activePlugin == model ) {
+ return catalog.i18nc( "@action:button", "Cancel" );
+ } else {
+ return catalog.i18nc("@action:button", "Install");
+ }
+ }
+ onClicked: {
+ if ( manager.isDownloading && pluginList.activePlugin == model ) {
+ manager.cancelDownload();
+ } else {
+ pluginList.activePlugin = model;
+ manager.downloadAndInstallPlugin( model.file_location );
+ }
+ }
+ style: ButtonStyle {
+ background: Rectangle {
+ color: "transparent"
+ implicitWidth: 96
+ implicitHeight: 30
+ border {
+ width: 1
+ color: UM.Theme.getColor("lining")
+ }
+ }
+ label: Text {
+ verticalAlignment: Text.AlignVCenter
+ color: "grey"
+ text: control.text
+ horizontalAlignment: Text.AlignHCenter
+ }
+ }
+ }
+ */
+ ProgressBar {
+ id: progressbar
+ minimumValue: 0;
+ maximumValue: 100
+ anchors.left: installButton.left
+ anchors.right: installButton.right
+ anchors.top: installButton.bottom
+ anchors.topMargin: 4
+ value: manager.isDownloading ? manager.downloadProgress : 0
+ visible: manager.isDownloading && pluginList.activePlugin == model
+ style: ProgressBarStyle {
+ background: Rectangle {
+ color: "lightgray"
+ implicitHeight: 6
+ }
+ progress: Rectangle {
+ color: UM.Theme.getColor("primary")
+ }
+ }
+ }
+
+ }
+ }
+}
diff --git a/plugins/PostProcessingPlugin/PostProcessingPlugin.py b/plugins/PostProcessingPlugin/PostProcessingPlugin.py
index fa519f48be..c4b760724b 100644
--- a/plugins/PostProcessingPlugin/PostProcessingPlugin.py
+++ b/plugins/PostProcessingPlugin/PostProcessingPlugin.py
@@ -54,16 +54,15 @@ class PostProcessingPlugin(QObject, Extension):
## Execute all post-processing scripts on the gcode.
def execute(self, output_device):
scene = Application.getInstance().getController().getScene()
- gcode_dict = None
-
- if hasattr(scene, "gcode_dict"):
- gcode_dict = getattr(scene, "gcode_dict")
-
+ # If the scene does not have a gcode, do nothing
+ if not hasattr(scene, "gcode_dict"):
+ return
+ gcode_dict = getattr(scene, "gcode_dict")
if not gcode_dict:
return
# get gcode list for the active build plate
- active_build_plate_id = Application.getInstance().getBuildPlateModel().activeBuildPlate
+ active_build_plate_id = Application.getInstance().getMultiBuildPlateModel().activeBuildPlate
gcode_list = gcode_dict[active_build_plate_id]
if not gcode_list:
return
@@ -119,27 +118,30 @@ class PostProcessingPlugin(QObject, Extension):
for loader, script_name, ispkg in scripts:
# Iterate over all scripts.
if script_name not in sys.modules:
- spec = importlib.util.spec_from_file_location(__name__ + "." + script_name, os.path.join(path, script_name + ".py"))
- loaded_script = importlib.util.module_from_spec(spec)
- spec.loader.exec_module(loaded_script)
- sys.modules[script_name] = loaded_script
-
- loaded_class = getattr(loaded_script, script_name)
- temp_object = loaded_class()
- Logger.log("d", "Begin loading of script: %s", script_name)
try:
- setting_data = temp_object.getSettingData()
- if "name" in setting_data and "key" in setting_data:
- self._script_labels[setting_data["key"]] = setting_data["name"]
- self._loaded_scripts[setting_data["key"]] = loaded_class
- else:
- Logger.log("w", "Script %s.py has no name or key", script_name)
- self._script_labels[script_name] = script_name
- self._loaded_scripts[script_name] = loaded_class
- except AttributeError:
- Logger.log("e", "Script %s.py is not a recognised script type. Ensure it inherits Script", script_name)
- except NotImplementedError:
- Logger.log("e", "Script %s.py has no implemented settings", script_name)
+ spec = importlib.util.spec_from_file_location(__name__ + "." + script_name, os.path.join(path, script_name + ".py"))
+ loaded_script = importlib.util.module_from_spec(spec)
+ spec.loader.exec_module(loaded_script)
+ sys.modules[script_name] = loaded_script
+
+ loaded_class = getattr(loaded_script, script_name)
+ temp_object = loaded_class()
+ Logger.log("d", "Begin loading of script: %s", script_name)
+ try:
+ setting_data = temp_object.getSettingData()
+ if "name" in setting_data and "key" in setting_data:
+ self._script_labels[setting_data["key"]] = setting_data["name"]
+ self._loaded_scripts[setting_data["key"]] = loaded_class
+ else:
+ Logger.log("w", "Script %s.py has no name or key", script_name)
+ self._script_labels[script_name] = script_name
+ self._loaded_scripts[script_name] = loaded_class
+ except AttributeError:
+ Logger.log("e", "Script %s.py is not a recognised script type. Ensure it inherits Script", script_name)
+ except NotImplementedError:
+ Logger.log("e", "Script %s.py has no implemented settings", script_name)
+ except Exception as e:
+ Logger.logException("e", "Exception occurred while loading post processing plugin: {error_msg}".format(error_msg = str(e)))
self.loadedScriptListChanged.emit()
loadedScriptListChanged = pyqtSignal()
@@ -171,19 +173,19 @@ class PostProcessingPlugin(QObject, Extension):
Logger.log("d", "Creating post processing plugin view.")
## Load all scripts in the scripts folders
- for root in [PluginRegistry.getInstance().getPluginPath("PostProcessingPlugin"), Resources.getStoragePath(Resources.Preferences)]:
- try:
- path = os.path.join(root, "scripts")
- if not os.path.isdir(path):
- try:
- os.makedirs(path)
- except OSError:
- Logger.log("w", "Unable to create a folder for scripts: " + path)
- continue
+ # The PostProcessingPlugin path is for built-in scripts.
+ # The Resources path is where the user should store custom scripts.
+ # The Preferences path is legacy, where the user may previously have stored scripts.
+ for root in [PluginRegistry.getInstance().getPluginPath("PostProcessingPlugin"), Resources.getStoragePath(Resources.Resources), Resources.getStoragePath(Resources.Preferences)]:
+ path = os.path.join(root, "scripts")
+ if not os.path.isdir(path):
+ try:
+ os.makedirs(path)
+ except OSError:
+ Logger.log("w", "Unable to create a folder for scripts: " + path)
+ continue
- self.loadAllScripts(path)
- except Exception as e:
- Logger.logException("e", "Exception occurred while loading post processing plugin: {error_msg}".format(error_msg = str(e)))
+ self.loadAllScripts(path)
# Create the plugin dialog component
path = os.path.join(PluginRegistry.getInstance().getPluginPath("PostProcessingPlugin"), "PostProcessingPlugin.qml")
diff --git a/plugins/PostProcessingPlugin/PostProcessingPlugin.qml b/plugins/PostProcessingPlugin/PostProcessingPlugin.qml
index d64d60a04a..489ea6dcfb 100644
--- a/plugins/PostProcessingPlugin/PostProcessingPlugin.qml
+++ b/plugins/PostProcessingPlugin/PostProcessingPlugin.qml
@@ -25,8 +25,8 @@ UM.Dialog
{
UM.I18nCatalog{id: catalog; name:"cura"}
id: base
- property int columnWidth: Math.floor((base.width / 2) - UM.Theme.getSize("default_margin").width)
- property int textMargin: Math.floor(UM.Theme.getSize("default_margin").width / 2)
+ 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)
property string activeScriptName
SystemPalette{ id: palette }
SystemPalette{ id: disabledPalette; colorGroup: SystemPalette.Disabled }
@@ -129,8 +129,8 @@ UM.Dialog
{
anchors.verticalCenter: parent.verticalCenter
anchors.horizontalCenter: parent.horizontalCenter
- width: Math.floor(control.width / 2.7)
- height: Math.floor(control.height / 2.7)
+ width: Math.round(control.width / 2.7)
+ height: Math.round(control.height / 2.7)
sourceSize.width: width
sourceSize.height: width
color: palette.text
@@ -164,8 +164,8 @@ UM.Dialog
{
anchors.verticalCenter: parent.verticalCenter
anchors.horizontalCenter: parent.horizontalCenter
- width: Math.floor(control.width / 2.5)
- height: Math.floor(control.height / 2.5)
+ 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
@@ -199,8 +199,8 @@ UM.Dialog
{
anchors.verticalCenter: parent.verticalCenter
anchors.horizontalCenter: parent.horizontalCenter
- width: Math.floor(control.width / 2.5)
- height: Math.floor(control.height / 2.5)
+ 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
@@ -478,15 +478,15 @@ UM.Dialog
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.floor(UM.Theme.getSize("save_button_text_margin").width / 2);
+ 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.floor(parent.width / 2)
- height: Math.floor(parent.height / 2)
+ 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") :
diff --git a/plugins/PostProcessingPlugin/Script.py b/plugins/PostProcessingPlugin/Script.py
index 7d603ba11f..7f419cd422 100644
--- a/plugins/PostProcessingPlugin/Script.py
+++ b/plugins/PostProcessingPlugin/Script.py
@@ -105,6 +105,58 @@ class Script:
except:
return default
+ ## Convenience function to produce a line of g-code.
+ #
+ # You can put in an original g-code line and it'll re-use all the values
+ # in that line.
+ # All other keyword parameters are put in the result in g-code's format.
+ # For instance, if you put ``G=1`` in the parameters, it will output
+ # ``G1``. If you put ``G=1, X=100`` in the parameters, it will output
+ # ``G1 X100``. The parameters G and M will always be put first. The
+ # parameters T and S will be put second (or first if there is no G or M).
+ # The rest of the parameters will be put in arbitrary order.
+ # \param line The original g-code line that must be modified. If not
+ # provided, an entirely new g-code line will be produced.
+ # \return A line of g-code with the desired parameters filled in.
+ def putValue(self, line = "", **kwargs):
+ #Strip the comment.
+ comment = ""
+ if ";" in line:
+ comment = line[line.find(";"):]
+ line = line[:line.find(";")] #Strip the comment.
+
+ #Parse the original g-code line.
+ for part in line.split(" "):
+ if part == "":
+ continue
+ parameter = part[0]
+ if parameter in kwargs:
+ continue #Skip this one. The user-provided parameter overwrites the one in the line.
+ value = part[1:]
+ kwargs[parameter] = value
+
+ #Write the new g-code line.
+ result = ""
+ priority_parameters = ["G", "M", "T", "S", "F", "X", "Y", "Z", "E"] #First some parameters that get priority. In order of priority!
+ for priority_key in priority_parameters:
+ if priority_key in kwargs:
+ if result != "":
+ result += " "
+ result += priority_key + str(kwargs[priority_key])
+ del kwargs[priority_key]
+ for key, value in kwargs.items():
+ if result != "":
+ result += " "
+ result += key + str(value)
+
+ #Put the comment back in.
+ if comment != "":
+ if result != "":
+ result += " "
+ result += ";" + comment
+
+ return result
+
## This is called when the script is executed.
# It gets a list of g-code strings and needs to return a (modified) list.
def execute(self, data):
diff --git a/plugins/PostProcessingPlugin/scripts/TweakAtZ.py b/plugins/PostProcessingPlugin/scripts/ChangeAtZ.py
similarity index 78%
rename from plugins/PostProcessingPlugin/scripts/TweakAtZ.py
rename to plugins/PostProcessingPlugin/scripts/ChangeAtZ.py
index 7b714f6ee0..54d6fdb155 100644
--- a/plugins/PostProcessingPlugin/scripts/TweakAtZ.py
+++ b/plugins/PostProcessingPlugin/scripts/ChangeAtZ.py
@@ -1,10 +1,10 @@
-# TweakAtZ script - Change printing parameters at a given height
+# ChangeAtZ script - Change printing parameters at a given height
# This script is the successor of the TweakAtZ plugin for legacy Cura.
# It contains code from the TweakAtZ plugin V1.0-V4.x and from the ExampleScript by Jaime van Kessel, Ultimaker B.V.
# It runs with the PostProcessingPlugin which is released under the terms of the AGPLv3 or higher.
# This script is licensed under the Creative Commons - Attribution - Share Alike (CC BY-SA) terms
-#Authors of the TweakAtZ plugin / script:
+#Authors of the ChangeAtZ plugin / script:
# Written by Steven Morlock, smorloc@gmail.com
# Modified by Ricardo Gomez, ricardoga@otulook.com, to add Bed Temperature and make it work with Cura_13.06.04+
# Modified by Stefan Heule, Dim3nsioneer@gmx.ch since V3.0 (see changelog below)
@@ -46,15 +46,15 @@ from ..Script import Script
#from UM.Logger import Logger
import re
-class TweakAtZ(Script):
+class ChangeAtZ(Script):
version = "5.1.1"
def __init__(self):
super().__init__()
def getSettingDataString(self):
return """{
- "name":"TweakAtZ """ + self.version + """ (Experimental)",
- "key":"TweakAtZ",
+ "name":"ChangeAtZ """ + self.version + """ (Experimental)",
+ "key":"ChangeAtZ",
"metadata": {},
"version": 2,
"settings":
@@ -69,8 +69,8 @@ class TweakAtZ(Script):
},
"b_targetZ":
{
- "label": "Tweak Height",
- "description": "Z height to tweak at",
+ "label": "Change Height",
+ "description": "Z height to change at",
"unit": "mm",
"type": "float",
"default_value": 5.0,
@@ -81,8 +81,8 @@ class TweakAtZ(Script):
},
"b_targetL":
{
- "label": "Tweak Layer",
- "description": "Layer no. to tweak at",
+ "label": "Change Layer",
+ "description": "Layer no. to change at",
"unit": "",
"type": "int",
"default_value": 1,
@@ -93,7 +93,7 @@ class TweakAtZ(Script):
"c_behavior":
{
"label": "Behavior",
- "description": "Select behavior: Tweak value and keep it for the rest, Tweak value for single layer only",
+ "description": "Select behavior: Change value and keep it for the rest, Change value for single layer only",
"type": "enum",
"options": {"keep_value":"Keep value","single_layer":"Single Layer"},
"default_value": "keep_value"
@@ -101,7 +101,7 @@ class TweakAtZ(Script):
"d_twLayers":
{
"label": "No. Layers",
- "description": "No. of layers used to tweak",
+ "description": "No. of layers used to change",
"unit": "",
"type": "int",
"default_value": 1,
@@ -109,10 +109,10 @@ class TweakAtZ(Script):
"maximum_value_warning": "50",
"enabled": "c_behavior == 'keep_value'"
},
- "e1_Tweak_speed":
+ "e1_Change_speed":
{
- "label": "Tweak Speed",
- "description": "Select if total speed (print and travel) has to be tweaked",
+ "label": "Change Speed",
+ "description": "Select if total speed (print and travel) has to be cahnged",
"type": "bool",
"default_value": false
},
@@ -126,12 +126,12 @@ class TweakAtZ(Script):
"minimum_value": "1",
"minimum_value_warning": "10",
"maximum_value_warning": "200",
- "enabled": "e1_Tweak_speed"
+ "enabled": "e1_Change_speed"
},
- "f1_Tweak_printspeed":
+ "f1_Change_printspeed":
{
- "label": "Tweak Print Speed",
- "description": "Select if print speed has to be tweaked",
+ "label": "Change Print Speed",
+ "description": "Select if print speed has to be changed",
"type": "bool",
"default_value": false
},
@@ -145,12 +145,12 @@ class TweakAtZ(Script):
"minimum_value": "1",
"minimum_value_warning": "10",
"maximum_value_warning": "200",
- "enabled": "f1_Tweak_printspeed"
+ "enabled": "f1_Change_printspeed"
},
- "g1_Tweak_flowrate":
+ "g1_Change_flowrate":
{
- "label": "Tweak Flow Rate",
- "description": "Select if flow rate has to be tweaked",
+ "label": "Change Flow Rate",
+ "description": "Select if flow rate has to be changed",
"type": "bool",
"default_value": false
},
@@ -164,12 +164,12 @@ class TweakAtZ(Script):
"minimum_value": "1",
"minimum_value_warning": "10",
"maximum_value_warning": "200",
- "enabled": "g1_Tweak_flowrate"
+ "enabled": "g1_Change_flowrate"
},
- "g3_Tweak_flowrateOne":
+ "g3_Change_flowrateOne":
{
- "label": "Tweak Flow Rate 1",
- "description": "Select if first extruder flow rate has to be tweaked",
+ "label": "Change Flow Rate 1",
+ "description": "Select if first extruder flow rate has to be changed",
"type": "bool",
"default_value": false
},
@@ -183,12 +183,12 @@ class TweakAtZ(Script):
"minimum_value": "1",
"minimum_value_warning": "10",
"maximum_value_warning": "200",
- "enabled": "g3_Tweak_flowrateOne"
+ "enabled": "g3_Change_flowrateOne"
},
- "g5_Tweak_flowrateTwo":
+ "g5_Change_flowrateTwo":
{
- "label": "Tweak Flow Rate 2",
- "description": "Select if second extruder flow rate has to be tweaked",
+ "label": "Change Flow Rate 2",
+ "description": "Select if second extruder flow rate has to be changed",
"type": "bool",
"default_value": false
},
@@ -202,12 +202,12 @@ class TweakAtZ(Script):
"minimum_value": "1",
"minimum_value_warning": "10",
"maximum_value_warning": "200",
- "enabled": "g5_Tweak_flowrateTwo"
+ "enabled": "g5_Change_flowrateTwo"
},
- "h1_Tweak_bedTemp":
+ "h1_Change_bedTemp":
{
- "label": "Tweak Bed Temp",
- "description": "Select if Bed Temperature has to be tweaked",
+ "label": "Change Bed Temp",
+ "description": "Select if Bed Temperature has to be changed",
"type": "bool",
"default_value": false
},
@@ -221,12 +221,12 @@ class TweakAtZ(Script):
"minimum_value": "0",
"minimum_value_warning": "30",
"maximum_value_warning": "120",
- "enabled": "h1_Tweak_bedTemp"
+ "enabled": "h1_Change_bedTemp"
},
- "i1_Tweak_extruderOne":
+ "i1_Change_extruderOne":
{
- "label": "Tweak Extruder 1 Temp",
- "description": "Select if First Extruder Temperature has to be tweaked",
+ "label": "Change Extruder 1 Temp",
+ "description": "Select if First Extruder Temperature has to be changed",
"type": "bool",
"default_value": false
},
@@ -240,12 +240,12 @@ class TweakAtZ(Script):
"minimum_value": "0",
"minimum_value_warning": "160",
"maximum_value_warning": "250",
- "enabled": "i1_Tweak_extruderOne"
+ "enabled": "i1_Change_extruderOne"
},
- "i3_Tweak_extruderTwo":
+ "i3_Change_extruderTwo":
{
- "label": "Tweak Extruder 2 Temp",
- "description": "Select if Second Extruder Temperature has to be tweaked",
+ "label": "Change Extruder 2 Temp",
+ "description": "Select if Second Extruder Temperature has to be changed",
"type": "bool",
"default_value": false
},
@@ -259,12 +259,12 @@ class TweakAtZ(Script):
"minimum_value": "0",
"minimum_value_warning": "160",
"maximum_value_warning": "250",
- "enabled": "i3_Tweak_extruderTwo"
+ "enabled": "i3_Change_extruderTwo"
},
- "j1_Tweak_fanSpeed":
+ "j1_Change_fanSpeed":
{
- "label": "Tweak Fan Speed",
- "description": "Select if Fan Speed has to be tweaked",
+ "label": "Change Fan Speed",
+ "description": "Select if Fan Speed has to be changed",
"type": "bool",
"default_value": false
},
@@ -278,17 +278,17 @@ class TweakAtZ(Script):
"minimum_value": "0",
"minimum_value_warning": "15",
"maximum_value_warning": "255",
- "enabled": "j1_Tweak_fanSpeed"
+ "enabled": "j1_Change_fanSpeed"
}
}
}"""
def getValue(self, line, key, default = None): #replace default getvalue due to comment-reading feature
if not key in line or (";" in line and line.find(key) > line.find(";") and
- not ";TweakAtZ" in key and not ";LAYER:" in key):
+ not ";ChangeAtZ" in key and not ";LAYER:" in key):
return default
subPart = line[line.find(key) + len(key):] #allows for string lengths larger than 1
- if ";TweakAtZ" in key:
+ if ";ChangeAtZ" in key:
m = re.search("^[0-4]", subPart)
elif ";LAYER:" in key:
m = re.search("^[+-]?[0-9]*", subPart)
@@ -303,17 +303,17 @@ class TweakAtZ(Script):
return default
def execute(self, data):
- #Check which tweaks should apply
- TweakProp = {"speed": self.getSettingValueByKey("e1_Tweak_speed"),
- "flowrate": self.getSettingValueByKey("g1_Tweak_flowrate"),
- "flowrateOne": self.getSettingValueByKey("g3_Tweak_flowrateOne"),
- "flowrateTwo": self.getSettingValueByKey("g5_Tweak_flowrateTwo"),
- "bedTemp": self.getSettingValueByKey("h1_Tweak_bedTemp"),
- "extruderOne": self.getSettingValueByKey("i1_Tweak_extruderOne"),
- "extruderTwo": self.getSettingValueByKey("i3_Tweak_extruderTwo"),
- "fanSpeed": self.getSettingValueByKey("j1_Tweak_fanSpeed")}
- TweakPrintSpeed = self.getSettingValueByKey("f1_Tweak_printspeed")
- TweakStrings = {"speed": "M220 S%f\n",
+ #Check which changes should apply
+ ChangeProp = {"speed": self.getSettingValueByKey("e1_Change_speed"),
+ "flowrate": self.getSettingValueByKey("g1_Change_flowrate"),
+ "flowrateOne": self.getSettingValueByKey("g3_Change_flowrateOne"),
+ "flowrateTwo": self.getSettingValueByKey("g5_Change_flowrateTwo"),
+ "bedTemp": self.getSettingValueByKey("h1_Change_bedTemp"),
+ "extruderOne": self.getSettingValueByKey("i1_Change_extruderOne"),
+ "extruderTwo": self.getSettingValueByKey("i3_Change_extruderTwo"),
+ "fanSpeed": self.getSettingValueByKey("j1_Change_fanSpeed")}
+ ChangePrintSpeed = self.getSettingValueByKey("f1_Change_printspeed")
+ ChangeStrings = {"speed": "M220 S%f\n",
"flowrate": "M221 S%f\n",
"flowrateOne": "M221 T0 S%f\n",
"flowrateTwo": "M221 T1 S%f\n",
@@ -369,14 +369,14 @@ class TweakAtZ(Script):
for line in lines:
if ";Generated with Cura_SteamEngine" in line:
TWinstances += 1
- modified_gcode += ";TweakAtZ instances: %d\n" % TWinstances
- if not ("M84" in line or "M25" in line or ("G1" in line and TweakPrintSpeed and (state==3 or state==4)) or
- ";TweakAtZ instances:" in line):
+ modified_gcode += ";ChangeAtZ instances: %d\n" % TWinstances
+ if not ("M84" in line or "M25" in line or ("G1" in line and ChangePrintSpeed and (state==3 or state==4)) or
+ ";ChangeAtZ instances:" in line):
modified_gcode += line + "\n"
IsUM2 = ("FLAVOR:UltiGCode" in line) or IsUM2 #Flavor is UltiGCode!
- if ";TweakAtZ-state" in line: #checks for state change comment
- state = self.getValue(line, ";TweakAtZ-state", state)
- if ";TweakAtZ instances:" in line:
+ if ";ChangeAtZ-state" in line: #checks for state change comment
+ state = self.getValue(line, ";ChangeAtZ-state", state)
+ if ";ChangeAtZ instances:" in line:
try:
tempTWi = int(line[20:])
except:
@@ -390,7 +390,7 @@ class TweakAtZ(Script):
state = old["state"]
layer = self.getValue(line, ";LAYER:", layer)
if targetL_i > -100000: #target selected by layer no.
- if (state == 2 or targetL_i == 0) and layer == targetL_i: #determine targetZ from layer no.; checks for tweak on layer 0
+ if (state == 2 or targetL_i == 0) and layer == targetL_i: #determine targetZ from layer no.; checks for change on layer 0
state = 2
targetZ = z + 0.001
if (self.getValue(line, "T", None) is not None) and (self.getValue(line, "M", None) is None): #looking for single T-cmd
@@ -415,7 +415,7 @@ class TweakAtZ(Script):
elif tmp_extruder == 1: #second extruder
old["flowrateOne"] = self.getValue(line, "S", old["flowrateOne"])
if ("M84" in line or "M25" in line):
- if state>0 and TweakProp["speed"]: #"finish" commands for UM Original and UM2
+ 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"
modified_gcode += "M117 \n"
modified_gcode += line + "\n"
@@ -425,14 +425,14 @@ class TweakAtZ(Script):
y = self.getValue(line, "Y", None)
e = self.getValue(line, "E", None)
f = self.getValue(line, "F", None)
- if 'G1' in line and TweakPrintSpeed and (state==3 or state==4):
+ if 'G1' in line and ChangePrintSpeed and (state==3 or state==4):
# check for pure print movement in target range:
if x != None and y != None and f != None and e != None and newZ==z:
modified_gcode += "G1 F%d X%1.3f Y%1.3f E%1.5f\n" % (int(f / 100.0 * float(target_values["printspeed"])), self.getValue(line, "X"),
self.getValue(line, "Y"), self.getValue(line, "E"))
else: #G1 command but not a print movement
modified_gcode += line + "\n"
- # no tweaking on retraction hops which have no x and y coordinate:
+ # no changing on retraction hops which have no x and y coordinate:
if (newZ != z) and (x is not None) and (y is not None):
z = newZ
if z < targetZ and state == 1:
@@ -440,56 +440,56 @@ class TweakAtZ(Script):
if z >= targetZ and state == 2:
state = 3
done_layers = 0
- for key in TweakProp:
- if TweakProp[key] and old[key]==-1: #old value is not known
+ for key in ChangeProp:
+ if ChangeProp[key] and old[key]==-1: #old value is not known
oldValueUnknown = True
- if oldValueUnknown: #the tweaking has to happen within one layer
+ if oldValueUnknown: #the changing has to happen within one layer
twLayers = 1
if IsUM2: #Parameters have to be stored in the printer (UltiGCode=UM2)
- modified_gcode += "M605 S%d;stores parameters before tweaking\n" % (TWinstances-1)
- if behavior == 1: #single layer tweak only and then reset
+ modified_gcode += "M605 S%d;stores parameters before changing\n" % (TWinstances-1)
+ if behavior == 1: #single layer change only and then reset
twLayers = 1
- if TweakPrintSpeed and behavior == 0:
+ if ChangePrintSpeed and behavior == 0:
twLayers = done_layers + 1
if state==3:
if twLayers-done_layers>0: #still layers to go?
if targetL_i > -100000:
- modified_gcode += ";TweakAtZ V%s: executed at Layer %d\n" % (self.version,layer)
- modified_gcode += "M117 Printing... tw@L%4d\n" % layer
+ modified_gcode += ";ChangeAtZ V%s: executed at Layer %d\n" % (self.version,layer)
+ modified_gcode += "M117 Printing... ch@L%4d\n" % layer
else:
- modified_gcode += (";TweakAtZ V%s: executed at %1.2f mm\n" % (self.version,z))
- modified_gcode += "M117 Printing... tw@%5.1f\n" % z
- for key in TweakProp:
- if TweakProp[key]:
- modified_gcode += TweakStrings[key] % float(old[key]+(float(target_values[key])-float(old[key]))/float(twLayers)*float(done_layers+1))
+ modified_gcode += (";ChangeAtZ V%s: executed at %1.2f mm\n" % (self.version,z))
+ modified_gcode += "M117 Printing... ch@%5.1f\n" % z
+ for key in ChangeProp:
+ if ChangeProp[key]:
+ modified_gcode += ChangeStrings[key] % float(old[key]+(float(target_values[key])-float(old[key]))/float(twLayers)*float(done_layers+1))
done_layers += 1
else:
state = 4
if behavior == 1: #reset values after one layer
if targetL_i > -100000:
- modified_gcode += ";TweakAtZ V%s: reset on Layer %d\n" % (self.version,layer)
+ modified_gcode += ";ChangeAtZ V%s: reset on Layer %d\n" % (self.version,layer)
else:
- modified_gcode += ";TweakAtZ V%s: reset at %1.2f mm\n" % (self.version,z)
+ modified_gcode += ";ChangeAtZ V%s: reset at %1.2f mm\n" % (self.version,z)
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
- for key in TweakProp:
- if TweakProp[key]:
- modified_gcode += TweakStrings[key] % float(old[key])
+ for key in ChangeProp:
+ if ChangeProp[key]:
+ modified_gcode += ChangeStrings[key] % float(old[key])
# re-activates the plugin if executed by pre-print G-command, resets settings:
- if (z < targetZ or layer == 0) and state >= 3: #resets if below tweak level or at level 0
+ if (z < targetZ or layer == 0) and state >= 3: #resets if below change level or at level 0
state = 2
done_layers = 0
if targetL_i > -100000:
- modified_gcode += ";TweakAtZ 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 += ";TweakAtZ 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
- for key in TweakProp:
- if TweakProp[key]:
- modified_gcode += TweakStrings[key] % float(old[key])
+ for key in ChangeProp:
+ if ChangeProp[key]:
+ modified_gcode += ChangeStrings[key] % float(old[key])
data[index] = modified_gcode
index += 1
return data
diff --git a/plugins/PostProcessingPlugin/scripts/ColorChange.py b/plugins/PostProcessingPlugin/scripts/FilamentChange.py
similarity index 79%
rename from plugins/PostProcessingPlugin/scripts/ColorChange.py
rename to plugins/PostProcessingPlugin/scripts/FilamentChange.py
index 8db45f4033..2bb7891634 100644
--- a/plugins/PostProcessingPlugin/scripts/ColorChange.py
+++ b/plugins/PostProcessingPlugin/scripts/FilamentChange.py
@@ -2,17 +2,15 @@
# under the terms of the AGPLv3 or higher
from ..Script import Script
-#from UM.Logger import Logger
-# from cura.Settings.ExtruderManager import ExtruderManager
-class ColorChange(Script):
+class FilamentChange(Script):
def __init__(self):
super().__init__()
def getSettingDataString(self):
return """{
- "name":"Color Change",
- "key": "ColorChange",
+ "name":"Filament Change",
+ "key": "FilamentChange",
"metadata": {},
"version": 2,
"settings":
@@ -60,17 +58,17 @@ class ColorChange(Script):
if later_retract is not None and later_retract > 0.:
color_change = color_change + (" L%.2f" % later_retract)
- color_change = color_change + " ; Generated by ColorChange plugin"
+ color_change = color_change + " ; Generated by FilamentChange plugin"
- layer_targets = layer_nums.split(',')
+ layer_targets = layer_nums.split(",")
if len(layer_targets) > 0:
for layer_num in layer_targets:
- layer_num = int( layer_num.strip() )
+ layer_num = int(layer_num.strip())
if layer_num < len(data):
- layer = data[ layer_num - 1 ]
+ layer = data[layer_num - 1]
lines = layer.split("\n")
- lines.insert(2, color_change )
- final_line = "\n".join( lines )
- data[ layer_num - 1 ] = final_line
+ lines.insert(2, color_change)
+ final_line = "\n".join(lines)
+ data[layer_num - 1] = final_line
return data
diff --git a/plugins/PostProcessingPlugin/scripts/PauseAtHeight.py b/plugins/PostProcessingPlugin/scripts/PauseAtHeight.py
index 925a5a7ac5..805ab0a2c3 100644
--- a/plugins/PostProcessingPlugin/scripts/PauseAtHeight.py
+++ b/plugins/PostProcessingPlugin/scripts/PauseAtHeight.py
@@ -7,19 +7,40 @@ class PauseAtHeight(Script):
def getSettingDataString(self):
return """{
- "name":"Pause at height",
+ "name": "Pause at height",
"key": "PauseAtHeight",
"metadata": {},
"version": 2,
"settings":
{
+ "pause_at":
+ {
+ "label": "Pause at",
+ "description": "Whether to pause at a certain height or at a certain layer.",
+ "type": "enum",
+ "options": {"height": "Height", "layer_no": "Layer No."},
+ "default_value": "height"
+ },
"pause_height":
{
"label": "Pause Height",
"description": "At what height should the pause occur",
"unit": "mm",
"type": "float",
- "default_value": 5.0
+ "default_value": 5.0,
+ "minimum_value": "0",
+ "minimum_value_warning": "0.27",
+ "enabled": "pause_at == 'height'"
+ },
+ "pause_layer":
+ {
+ "label": "Pause Layer",
+ "description": "At what layer should the pause occur",
+ "type": "int",
+ "value": "math.floor((pause_height - 0.27) / 0.1) + 1",
+ "minimum_value": "0",
+ "minimum_value_warning": "1",
+ "enabled": "pause_at == 'layer_no'"
},
"head_park_x":
{
@@ -102,8 +123,9 @@ class PauseAtHeight(Script):
x = 0.
y = 0.
- current_z = 0.
+ pause_at = self.getSettingValueByKey("pause_at")
pause_height = self.getSettingValueByKey("pause_height")
+ pause_layer = self.getSettingValueByKey("pause_layer")
retraction_amount = self.getSettingValueByKey("retraction_amount")
retraction_speed = self.getSettingValueByKey("retraction_speed")
extrude_amount = self.getSettingValueByKey("extrude_amount")
@@ -121,101 +143,133 @@ class PauseAtHeight(Script):
# use offset to calculate the current height: = -
layer_0_z = 0.
+ current_z = 0
got_first_g_cmd_on_layer_0 = False
- for layer in data:
+ for index, layer in enumerate(data):
lines = layer.split("\n")
for line in lines:
if ";LAYER:0" in line:
layers_started = True
- continue
-
if not layers_started:
continue
- if self.getValue(line, 'G') == 1 or self.getValue(line, 'G') == 0:
- current_z = self.getValue(line, 'Z')
+ if self.getValue(line, "Z") is not None:
+ current_z = self.getValue(line, "Z")
+
+ if pause_at == "height":
+ if self.getValue(line, "G") != 1 and self.getValue(line, "G") != 0:
+ continue
+
if not got_first_g_cmd_on_layer_0:
layer_0_z = current_z
got_first_g_cmd_on_layer_0 = True
- x = self.getValue(line, 'X', x)
- y = self.getValue(line, 'Y', y)
- if current_z is not None:
- current_height = current_z - layer_0_z
- if current_height >= pause_height:
- index = data.index(layer)
- prevLayer = data[index - 1]
- prevLines = prevLayer.split("\n")
- current_e = 0.
- for prevLine in reversed(prevLines):
- current_e = self.getValue(prevLine, 'E', -1)
- if current_e >= 0:
- break
+ x = self.getValue(line, "X", x)
+ y = self.getValue(line, "Y", y)
- # include a number of previous layers
- for i in range(1, redo_layers + 1):
- prevLayer = data[index - i]
- layer = prevLayer + layer
+ current_height = current_z - layer_0_z
+ if current_height < pause_height:
+ break #Try the next layer.
+ else: #Pause at layer.
+ if not line.startswith(";LAYER:"):
+ continue
+ current_layer = line[len(";LAYER:"):]
+ try:
+ current_layer = int(current_layer)
+ except ValueError: #Couldn't cast to int. Something is wrong with this g-code data.
+ continue
+ if current_layer < pause_layer:
+ break #Try the next layer.
- prepend_gcode = ";TYPE:CUSTOM\n"
- prepend_gcode += ";added code by post processing\n"
- prepend_gcode += ";script: PauseAtHeight.py\n"
- prepend_gcode += ";current z: %f \n" % current_z
- prepend_gcode += ";current height: %f \n" % current_height
+ prevLayer = data[index - 1]
+ prevLines = prevLayer.split("\n")
+ current_e = 0.
- # Retraction
- prepend_gcode += "M83\n"
- if retraction_amount != 0:
- prepend_gcode += "G1 E-%f F%f\n" % (retraction_amount, retraction_speed * 60)
-
- # Move the head away
- prepend_gcode += "G1 Z%f F300\n" % (current_z + 1)
- prepend_gcode += "G1 X%f Y%f F9000\n" % (park_x, park_y)
- if current_z < 15:
- prepend_gcode += "G1 Z15 F300\n"
-
- # Disable the E steppers
- prepend_gcode += "M84 E0\n"
-
- # Set extruder standby temperature
- prepend_gcode += "M104 S%i; standby temperature\n" % (standby_temperature)
-
- # Wait till the user continues printing
- prepend_gcode += "M0 ;Do the actual pause\n"
-
- # Set extruder resume temperature
- prepend_gcode += "M109 S%i; resume temperature\n" % (resume_temperature)
-
- # Push the filament back,
- if retraction_amount != 0:
- prepend_gcode += "G1 E%f F%f\n" % (retraction_amount, retraction_speed * 60)
-
- # Optionally extrude material
- if extrude_amount != 0:
- prepend_gcode += "G1 E%f F%f\n" % (extrude_amount, extrude_speed * 60)
-
- # and retract again, the properly primes the nozzle
- # when changing filament.
- if retraction_amount != 0:
- prepend_gcode += "G1 E-%f F%f\n" % (retraction_amount, retraction_speed * 60)
-
- # Move the head back
- prepend_gcode += "G1 Z%f F300\n" % (current_z + 1)
- prepend_gcode += "G1 X%f Y%f F9000\n" % (x, y)
- if retraction_amount != 0:
- prepend_gcode += "G1 E%f F%f\n" % (retraction_amount, retraction_speed * 60)
- prepend_gcode += "G1 F9000\n"
- prepend_gcode += "M82\n"
-
- # reset extrude value to pre pause value
- prepend_gcode += "G92 E%f\n" % (current_e)
-
- layer = prepend_gcode + layer
-
-
- # Override the data of this layer with the
- # modified data
- data[index] = layer
- return data
+ # Access last layer, browse it backwards to find
+ # last extruder absolute position
+ for prevLine in reversed(prevLines):
+ current_e = self.getValue(prevLine, "E", -1)
+ if current_e >= 0:
break
+
+ # include a number of previous layers
+ for i in range(1, redo_layers + 1):
+ prevLayer = data[index - i]
+ layer = prevLayer + layer
+
+ # Get extruder's absolute position at the
+ # begining of the first layer redone
+ # see https://github.com/nallath/PostProcessingPlugin/issues/55
+ if i == redo_layers:
+ prevLines = prevLayer.split("\n")
+ for line in prevLines:
+ new_e = self.getValue(line, 'E', current_e)
+
+ if new_e != current_e:
+ current_e = new_e
+ break
+
+ prepend_gcode = ";TYPE:CUSTOM\n"
+ prepend_gcode += ";added code by post processing\n"
+ prepend_gcode += ";script: PauseAtHeight.py\n"
+ if pause_at == "height":
+ prepend_gcode += ";current z: {z}\n".format(z = current_z)
+ prepend_gcode += ";current height: {height}\n".format(height = current_height)
+ else:
+ prepend_gcode += ";current layer: {layer}\n".format(layer = current_layer)
+
+ # Retraction
+ prepend_gcode += self.putValue(M = 83) + "\n"
+ if retraction_amount != 0:
+ prepend_gcode += self.putValue(G = 1, E = -retraction_amount, F = retraction_speed * 60) + "\n"
+
+ # Move the head away
+ prepend_gcode += self.putValue(G = 1, Z = current_z + 1, F = 300) + "\n"
+ prepend_gcode += self.putValue(G = 1, X = park_x, Y = park_y, F = 9000) + "\n"
+ if current_z < 15:
+ prepend_gcode += self.putValue(G = 1, Z = 15, F = 300) + "\n"
+
+ # Disable the E steppers
+ prepend_gcode += self.putValue(M = 84, E = 0) + "\n"
+
+ # Set extruder standby temperature
+ prepend_gcode += self.putValue(M = 104, S = standby_temperature) + "; standby temperature\n"
+
+ # Wait till the user continues printing
+ prepend_gcode += self.putValue(M = 0) + ";Do the actual pause\n"
+
+ # Set extruder resume temperature
+ prepend_gcode += self.putValue(M = 109, S = resume_temperature) + "; resume temperature\n"
+
+ # Push the filament back,
+ if retraction_amount != 0:
+ prepend_gcode += self.putValue(G = 1, E = retraction_amount, F = retraction_speed * 60) + "\n"
+
+ # Optionally extrude material
+ if extrude_amount != 0:
+ prepend_gcode += self.putValue(G = 1, E = extrude_amount, F = extrude_speed * 60) + "\n"
+
+ # and retract again, the properly primes the nozzle
+ # when changing filament.
+ if retraction_amount != 0:
+ prepend_gcode += self.putValue(G = 1, E = -retraction_amount, F = retraction_speed * 60) + "\n"
+
+ # Move the head back
+ prepend_gcode += self.putValue(G = 1, Z = current_z + 1, F = 300) + "\n"
+ prepend_gcode += self.putValue(G = 1, X = x, Y = y, F = 9000) + "\n"
+ if retraction_amount != 0:
+ prepend_gcode += self.putValue(G = 1, E = retraction_amount, F = retraction_speed * 60) + "\n"
+ prepend_gcode += self.putValue(G = 1, F = 9000) + "\n"
+ prepend_gcode += self.putValue(M = 82) + "\n"
+
+ # reset extrude value to pre pause value
+ prepend_gcode += self.putValue(G = 92, E = current_e) + "\n"
+
+ layer = prepend_gcode + layer
+
+
+ # Override the data of this layer with the
+ # modified data
+ data[index] = layer
+ return data
return data
diff --git a/plugins/PostProcessingPlugin/scripts/PauseAtHeightforRepetier.py b/plugins/PostProcessingPlugin/scripts/PauseAtHeightforRepetier.py
index 710baab26a..f6c93d9ae6 100644
--- a/plugins/PostProcessingPlugin/scripts/PauseAtHeightforRepetier.py
+++ b/plugins/PostProcessingPlugin/scripts/PauseAtHeightforRepetier.py
@@ -35,7 +35,7 @@ class PauseAtHeightforRepetier(Script):
"type": "float",
"default_value": 5.0
},
- "head_move_Z":
+ "head_move_Z":
{
"label": "Head move Z",
"description": "The Hieght of Z-axis retraction before parking.",
diff --git a/plugins/SimulationView/SimulationPass.py b/plugins/SimulationView/SimulationPass.py
index 76d7127534..cd0eda2929 100644
--- a/plugins/SimulationView/SimulationPass.py
+++ b/plugins/SimulationView/SimulationPass.py
@@ -93,7 +93,7 @@ class SimulationPass(RenderPass):
self.bind()
tool_handle_batch = RenderBatch(self._tool_handle_shader, type = RenderBatch.RenderType.Overlay, backface_cull = True)
- active_build_plate = Application.getInstance().getBuildPlateModel().activeBuildPlate
+ active_build_plate = Application.getInstance().getMultiBuildPlateModel().activeBuildPlate
head_position = None # Indicates the current position of the print head
nozzle_node = None
diff --git a/plugins/SimulationView/SimulationSliderLabel.qml b/plugins/SimulationView/SimulationSliderLabel.qml
index 1c8daf867f..6f7749df63 100644
--- a/plugins/SimulationView/SimulationSliderLabel.qml
+++ b/plugins/SimulationView/SimulationSliderLabel.qml
@@ -49,7 +49,7 @@ UM.PointingRectangle {
anchors {
left: parent.left
- leftMargin: Math.floor(UM.Theme.getSize("default_margin").width / 2)
+ leftMargin: Math.round(UM.Theme.getSize("default_margin").width / 2)
verticalCenter: parent.verticalCenter
}
@@ -91,7 +91,7 @@ UM.PointingRectangle {
anchors {
left: parent.right
- leftMargin: Math.floor(UM.Theme.getSize("default_margin").width / 2)
+ leftMargin: Math.round(UM.Theme.getSize("default_margin").width / 2)
verticalCenter: parent.verticalCenter
}
diff --git a/plugins/SimulationView/SimulationView.py b/plugins/SimulationView/SimulationView.py
index dfecda06bb..5c3dca9fae 100644
--- a/plugins/SimulationView/SimulationView.py
+++ b/plugins/SimulationView/SimulationView.py
@@ -98,11 +98,14 @@ class SimulationView(View):
self._solid_layers = int(Preferences.getInstance().getValue("view/top_layer_count"))
self._only_show_top_layers = bool(Preferences.getInstance().getValue("view/only_show_top_layers"))
- self._compatibility_mode = True # for safety
+ self._compatibility_mode = self._evaluateCompatibilityMode()
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"))
+ def _evaluateCompatibilityMode(self):
+ return OpenGLContext.isLegacyOpenGL() or bool(Preferences.getInstance().getValue("view/force_layer_view_compatibility_mode"))
+
def _resetSettings(self):
self._layer_view_type = 0 # 0 is material color, 1 is color by linetype, 2 is speed, 3 is layer thickness
self._extruder_count = 0
@@ -127,7 +130,7 @@ class SimulationView(View):
# Currently the RenderPass constructor requires a size > 0
# This should be fixed in RenderPass's constructor.
self._layer_pass = SimulationPass(1, 1)
- self._compatibility_mode = OpenGLContext.isLegacyOpenGL() or bool(Preferences.getInstance().getValue("view/force_layer_view_compatibility_mode"))
+ self._compatibility_mode = self._evaluateCompatibilityMode()
self._layer_pass.setSimulationView(self)
return self._layer_pass
@@ -155,9 +158,10 @@ class SimulationView(View):
return self._nozzle_node
def _onSceneChanged(self, node):
- self.setActivity(False)
- self.calculateMaxLayers()
- self.calculateMaxPathsOnLayer(self._current_layer_num)
+ if node.getMeshData() is not None:
+ self.setActivity(False)
+ self.calculateMaxLayers()
+ self.calculateMaxPathsOnLayer(self._current_layer_num)
def isBusy(self):
return self._busy
@@ -339,6 +343,11 @@ class SimulationView(View):
min_layer_number = sys.maxsize
max_layer_number = -sys.maxsize
for layer_id in layer_data.getLayers():
+
+ # If a layer doesn't contain any polygons, skip it (for infill meshes taller than print objects
+ if len(layer_data.getLayer(layer_id).polygons) < 1:
+ continue
+
# Store the max and min feedrates and thicknesses for display purposes
for p in layer_data.getLayer(layer_id).polygons:
self._max_feedrate = max(float(p.lineFeedrates.max()), self._max_feedrate)
@@ -534,8 +543,7 @@ class SimulationView(View):
def _updateWithPreferences(self):
self._solid_layers = int(Preferences.getInstance().getValue("view/top_layer_count"))
self._only_show_top_layers = bool(Preferences.getInstance().getValue("view/only_show_top_layers"))
- self._compatibility_mode = OpenGLContext.isLegacyOpenGL() or bool(
- Preferences.getInstance().getValue("view/force_layer_view_compatibility_mode"))
+ self._compatibility_mode = self._evaluateCompatibilityMode()
self.setSimulationViewType(int(float(Preferences.getInstance().getValue("layerview/layer_view_type"))));
@@ -632,4 +640,3 @@ class _CreateTopLayersJob(Job):
def cancel(self):
self._cancel = True
super().cancel()
-
diff --git a/plugins/SimulationView/SimulationView.qml b/plugins/SimulationView/SimulationView.qml
index 11b985f77c..6aad413f9b 100644
--- a/plugins/SimulationView/SimulationView.qml
+++ b/plugins/SimulationView/SimulationView.qml
@@ -61,7 +61,7 @@ Item
Button {
id: collapseButton
anchors.top: parent.top
- anchors.topMargin: Math.floor(UM.Theme.getSize("default_margin").height + (UM.Theme.getSize("layerview_row").height - UM.Theme.getSize("default_margin").height) / 2)
+ 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
@@ -193,7 +193,7 @@ Item
Item
{
- height: Math.floor(UM.Theme.getSize("default_margin").width / 2)
+ height: Math.round(UM.Theme.getSize("default_margin").width / 2)
width: width
}
@@ -231,7 +231,7 @@ Item
width: UM.Theme.getSize("layerview_legend_size").width
height: UM.Theme.getSize("layerview_legend_size").height
color: model.color
- radius: width / 2
+ 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
@@ -249,7 +249,7 @@ Item
anchors.verticalCenter: parent.verticalCenter
anchors.left: extrudersModelCheckBox.left;
anchors.right: extrudersModelCheckBox.right;
- anchors.leftMargin: UM.Theme.getSize("checkbox").width + UM.Theme.getSize("default_margin").width /2
+ 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
}
}
@@ -316,7 +316,7 @@ Item
anchors.verticalCenter: parent.verticalCenter
anchors.left: legendModelCheckBox.left;
anchors.right: legendModelCheckBox.right;
- anchors.leftMargin: UM.Theme.getSize("checkbox").width + UM.Theme.getSize("default_margin").width /2
+ 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
}
}
@@ -461,7 +461,7 @@ Item
visible: viewSettings.show_feedrate_gradient
anchors.left: parent.right
height: parent.width
- width: UM.Theme.getSize("layerview_row").height * 1.5
+ 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}
@@ -485,37 +485,37 @@ Item
}
}
- // Gradient colors for layer thickness
+ // 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: UM.Theme.getSize("layerview_row").height * 1.5
+ 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, 0, 1)
+ color: Qt.rgba(1, 1, 0, 1)
}
GradientStop {
position: 0.25
- color: Qt.rgba(0.5, 0.5, 0, 1)
+ color: Qt.rgba(1, 0.75, 0.25, 1)
}
GradientStop {
position: 0.5
- color: Qt.rgba(0, 1, 0, 1)
+ color: Qt.rgba(0, 0.75, 0.5, 1)
}
GradientStop {
position: 0.75
- color: Qt.rgba(0, 0.5, 0.5, 1)
+ color: Qt.rgba(0, 0.375, 0.75, 1)
}
GradientStop {
position: 1.0
- color: Qt.rgba(0, 0, 1, 1)
+ color: Qt.rgba(0, 0, 0.5, 1)
}
}
}
diff --git a/plugins/SimulationView/layers3d.shader b/plugins/SimulationView/layers3d.shader
index 95dc604389..03e279e9eb 100644
--- a/plugins/SimulationView/layers3d.shader
+++ b/plugins/SimulationView/layers3d.shader
@@ -54,9 +54,13 @@ vertex41core =
vec4 layerThicknessGradientColor(float abs_value, float min_value, float max_value)
{
float value = (abs_value - min_value)/(max_value - min_value);
- float red = max(2*value-1, 0);
- float green = 1-abs(1-2*value);
- float blue = max(1-2*value, 0);
+ float red = min(max(4*value-2, 0), 1);
+ float green = min(1.5*value, 0.75);
+ if (value > 0.75)
+ {
+ green = value;
+ }
+ float blue = 0.75-abs(0.25-value);
return vec4(red, green, blue, 1.0);
}
diff --git a/plugins/SliceInfoPlugin/SliceInfo.py b/plugins/SliceInfoPlugin/SliceInfo.py
index bcdb1bb407..971a324aa2 100755
--- a/plugins/SliceInfoPlugin/SliceInfo.py
+++ b/plugins/SliceInfoPlugin/SliceInfo.py
@@ -107,7 +107,7 @@ class SliceInfo(Extension):
"brand": extruder.material.getMetaData().get("brand", "")
}
extruder_position = int(extruder.getMetaDataEntry("position", "0"))
- if extruder_position in print_information.materialLengths:
+ if len(print_information.materialLengths) > extruder_position:
extruder_dict["material_used"] = print_information.materialLengths[extruder_position]
extruder_dict["variant"] = extruder.variant.getName()
extruder_dict["nozzle_size"] = extruder.getProperty("machine_nozzle_size", "value")
diff --git a/plugins/SolidView/SolidView.py b/plugins/SolidView/SolidView.py
index 50ff2864b7..de9f922267 100644
--- a/plugins/SolidView/SolidView.py
+++ b/plugins/SolidView/SolidView.py
@@ -78,17 +78,13 @@ class SolidView(View):
for node in DepthFirstIterator(scene.getRoot()):
if not node.render(renderer):
- if node.getMeshData() and node.isVisible():
+ if node.getMeshData() and node.isVisible() and not node.callDecoration("getLayerData"):
uniforms = {}
shade_factor = 1.0
per_mesh_stack = node.callDecoration("getStack")
- # Get color to render this mesh in from ExtrudersModel
- extruder_index = 0
- extruder_id = node.callDecoration("getActiveExtruder")
- if extruder_id:
- extruder_index = max(0, self._extruders_model.find("id", extruder_id))
+ extruder_index = int(node.callDecoration("getActiveExtruderPosition"))
# Use the support extruder instead of the active extruder if this is a support_mesh
if per_mesh_stack:
diff --git a/plugins/SupportEraser/SupportEraser.py b/plugins/SupportEraser/SupportEraser.py
new file mode 100644
index 0000000000..8b3ad0f4dd
--- /dev/null
+++ b/plugins/SupportEraser/SupportEraser.py
@@ -0,0 +1,71 @@
+# Copyright (c) 2018 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+from UM.Math.Vector import Vector
+from UM.Tool import Tool
+from PyQt5.QtCore import Qt, QUrl
+from UM.Application import Application
+from UM.Event import Event
+from UM.Mesh.MeshBuilder import MeshBuilder
+from UM.Operations.AddSceneNodeOperation import AddSceneNodeOperation
+from UM.Settings.SettingInstance import SettingInstance
+from cura.Scene.CuraSceneNode import CuraSceneNode
+from cura.Scene.SliceableObjectDecorator import SliceableObjectDecorator
+from cura.Scene.BuildPlateDecorator import BuildPlateDecorator
+from cura.Settings.SettingOverrideDecorator import SettingOverrideDecorator
+
+import os
+import os.path
+
+class SupportEraser(Tool):
+ def __init__(self):
+ super().__init__()
+ self._shortcut_key = Qt.Key_G
+ self._controller = Application.getInstance().getController()
+
+ def event(self, event):
+ super().event(event)
+
+ if event.type == Event.ToolActivateEvent:
+
+ # Load the remover mesh:
+ self._createEraserMesh()
+
+ # After we load the mesh, deactivate the tool again:
+ self.getController().setActiveTool(None)
+
+ def _createEraserMesh(self):
+ node = CuraSceneNode()
+
+ node.setName("Eraser")
+ node.setSelectable(True)
+ mesh = MeshBuilder()
+ mesh.addCube(10,10,10)
+ node.setMeshData(mesh.build())
+ # Place the cube in the platform. Do it manually so it works if the "automatic drop models" is OFF
+ move_vector = Vector(0, 5, 0)
+ node.setPosition(move_vector)
+
+ active_build_plate = Application.getInstance().getMultiBuildPlateModel().activeBuildPlate
+
+ node.addDecorator(SettingOverrideDecorator())
+ node.addDecorator(BuildPlateDecorator(active_build_plate))
+ node.addDecorator(SliceableObjectDecorator())
+
+ stack = node.callDecoration("getStack") #Don't try to get the active extruder since it may be None anyway.
+ if not stack:
+ node.addDecorator(SettingOverrideDecorator())
+ stack = node.callDecoration("getStack")
+
+ settings = stack.getTop()
+
+ if not (settings.getInstance("anti_overhang_mesh") and settings.getProperty("anti_overhang_mesh", "value")):
+ definition = stack.getSettingDefinition("anti_overhang_mesh")
+ new_instance = SettingInstance(definition, settings)
+ new_instance.setProperty("value", True)
+ new_instance.resetState() # Ensure that the state is not seen as a user state.
+ settings.addInstance(new_instance)
+
+ scene = self._controller.getScene()
+ op = AddSceneNodeOperation(node, scene.getRoot())
+ op.push()
+ Application.getInstance().getController().getScene().sceneChanged.emit(node)
diff --git a/plugins/SupportEraser/__init__.py b/plugins/SupportEraser/__init__.py
new file mode 100644
index 0000000000..72700571fe
--- /dev/null
+++ b/plugins/SupportEraser/__init__.py
@@ -0,0 +1,20 @@
+# Copyright (c) 2018 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+
+from . import SupportEraser
+
+from UM.i18n import i18nCatalog
+i18n_catalog = i18nCatalog("uranium")
+
+def getMetaData():
+ return {
+ "tool": {
+ "name": i18n_catalog.i18nc("@label", "Support Blocker"),
+ "description": i18n_catalog.i18nc("@info:tooltip", "Create a volume in which supports are not printed."),
+ "icon": "tool_icon.svg",
+ "weight": 4
+ }
+ }
+
+def register(app):
+ return { "tool": SupportEraser.SupportEraser() }
diff --git a/plugins/SupportEraser/plugin.json b/plugins/SupportEraser/plugin.json
new file mode 100644
index 0000000000..5ccb639913
--- /dev/null
+++ b/plugins/SupportEraser/plugin.json
@@ -0,0 +1,8 @@
+{
+ "name": "Support Eraser",
+ "author": "Ultimaker B.V.",
+ "version": "1.0.0",
+ "description": "Creates an eraser mesh to block the printing of support in certain places",
+ "api": 4,
+ "i18n-catalog": "cura"
+}
diff --git a/plugins/SupportEraser/tool_icon.svg b/plugins/SupportEraser/tool_icon.svg
new file mode 100644
index 0000000000..a0f8a3e3c3
--- /dev/null
+++ b/plugins/SupportEraser/tool_icon.svg
@@ -0,0 +1,11 @@
+
diff --git a/plugins/UFPWriter/UFPWriter.py b/plugins/UFPWriter/UFPWriter.py
new file mode 100644
index 0000000000..aca293e25a
--- /dev/null
+++ b/plugins/UFPWriter/UFPWriter.py
@@ -0,0 +1,56 @@
+#Copyright (c) 2018 Ultimaker B.V.
+#Cura is released under the terms of the LGPLv3 or higher.
+
+from Charon.VirtualFile import VirtualFile #To open UFP files.
+from Charon.OpenMode import OpenMode #To indicate that we want to write to UFP files.
+from io import StringIO #For converting g-code to bytes.
+
+from UM.Application import Application
+from UM.Logger import Logger
+from UM.Mesh.MeshWriter import MeshWriter #The writer we need to implement.
+from UM.PluginRegistry import PluginRegistry #To get the g-code writer.
+from PyQt5.QtCore import QBuffer
+
+from cura.Snapshot import Snapshot
+
+
+class UFPWriter(MeshWriter):
+ def __init__(self):
+ super().__init__()
+ self._snapshot = None
+ Application.getInstance().getOutputDeviceManager().writeStarted.connect(self._createSnapshot)
+
+ def _createSnapshot(self, *args):
+ # must be called from the main thread because of OpenGL
+ Logger.log("d", "Creating thumbnail image...")
+ self._snapshot = Snapshot.snapshot(width = 300, height = 300)
+
+ def write(self, stream, nodes, mode = MeshWriter.OutputMode.BinaryMode):
+ archive = VirtualFile()
+ archive.openStream(stream, "application/x-ufp", OpenMode.WriteOnly)
+
+ #Store the g-code from the scene.
+ archive.addContentType(extension = "gcode", mime_type = "text/x-gcode")
+ gcode_textio = StringIO() #We have to convert the g-code into bytes.
+ PluginRegistry.getInstance().getPluginObject("GCodeWriter").write(gcode_textio, None)
+ gcode = archive.getStream("/3D/model.gcode")
+ gcode.write(gcode_textio.getvalue().encode("UTF-8"))
+ archive.addRelation(virtual_path = "/3D/model.gcode", relation_type = "http://schemas.ultimaker.org/package/2018/relationships/gcode")
+
+ #Store the thumbnail.
+ if self._snapshot:
+ archive.addContentType(extension = "png", mime_type = "image/png")
+ thumbnail = archive.getStream("/Metadata/thumbnail.png")
+
+ thumbnail_buffer = QBuffer()
+ thumbnail_buffer.open(QBuffer.ReadWrite)
+ thumbnail_image = self._snapshot
+ thumbnail_image.save(thumbnail_buffer, "PNG")
+
+ thumbnail.write(thumbnail_buffer.data())
+ archive.addRelation(virtual_path = "/Metadata/thumbnail.png", relation_type = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail", origin = "/3D/model.gcode")
+ else:
+ Logger.log("d", "Thumbnail not created, cannot save it")
+
+ archive.close()
+ return True
diff --git a/plugins/UFPWriter/__init__.py b/plugins/UFPWriter/__init__.py
new file mode 100644
index 0000000000..9db6b042f8
--- /dev/null
+++ b/plugins/UFPWriter/__init__.py
@@ -0,0 +1,38 @@
+#Copyright (c) 2018 Ultimaker B.V.
+#Cura is released under the terms of the LGPLv3 or higher.
+
+import sys
+
+from UM.Logger import Logger
+try:
+ from . import UFPWriter
+except ImportError:
+ Logger.log("w", "Could not import UFPWriter; libCharon may be missing")
+
+from UM.i18n import i18nCatalog #To translate the file format description.
+from UM.Mesh.MeshWriter import MeshWriter #For the binary mode flag.
+
+i18n_catalog = i18nCatalog("cura")
+
+def getMetaData():
+ if "UFPWriter.UFPWriter" not in sys.modules:
+ return {}
+
+ return {
+ "mesh_writer": {
+ "output": [
+ {
+ "mime_type": "application/x-ufp",
+ "mode": MeshWriter.OutputMode.BinaryMode,
+ "extension": "ufp",
+ "description": i18n_catalog.i18nc("@item:inlistbox", "Ultimaker Format Package")
+ }
+ ]
+ }
+ }
+
+def register(app):
+ if "UFPWriter.UFPWriter" not in sys.modules:
+ return {}
+
+ return { "mesh_writer": UFPWriter.UFPWriter() }
diff --git a/plugins/UFPWriter/kitten.png b/plugins/UFPWriter/kitten.png
new file mode 100644
index 0000000000..44738f94f0
Binary files /dev/null and b/plugins/UFPWriter/kitten.png differ
diff --git a/plugins/UFPWriter/plugin.json b/plugins/UFPWriter/plugin.json
new file mode 100644
index 0000000000..7d10b89ad4
--- /dev/null
+++ b/plugins/UFPWriter/plugin.json
@@ -0,0 +1,8 @@
+{
+ "name": "UFP Writer",
+ "author": "Ultimaker B.V.",
+ "version": "1.0.0",
+ "description": "Provides support for writing Ultimaker Format Packages.",
+ "api": 4,
+ "i18n-catalog": "cura"
+}
\ No newline at end of file
diff --git a/plugins/UM3NetworkPrinting/ClusterUM3OutputDevice.py b/plugins/UM3NetworkPrinting/ClusterUM3OutputDevice.py
index b5cbc33d51..c19c86d6ce 100644
--- a/plugins/UM3NetworkPrinting/ClusterUM3OutputDevice.py
+++ b/plugins/UM3NetworkPrinting/ClusterUM3OutputDevice.py
@@ -22,7 +22,7 @@ from PyQt5.QtCore import pyqtSlot, QUrl, pyqtSignal, pyqtProperty, QObject
from time import time
from datetime import datetime
-from typing import Optional
+from typing import Optional, Dict, List
import json
import os
@@ -77,11 +77,13 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice):
self._cluster_size = int(properties.get(b"cluster_size", 0))
+ self._latest_reply_handler = None
+
def requestWrite(self, nodes, file_name=None, filter_by_machine=False, file_handler=None, **kwargs):
self.writeStarted.emit(self)
gcode_dict = getattr(Application.getInstance().getController().getScene(), "gcode_dict", [])
- active_build_plate_id = Application.getInstance().getBuildPlateModel().activeBuildPlate
+ active_build_plate_id = Application.getInstance().getMultiBuildPlateModel().activeBuildPlate
gcode_list = gcode_dict[active_build_plate_id]
if not gcode_list:
@@ -90,13 +92,15 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice):
self._gcode = gcode_list
+ is_job_sent = True
if len(self._printers) > 1:
self._spawnPrinterSelectionDialog()
else:
- self.sendPrintJob()
+ is_job_sent = self.sendPrintJob()
# Notify the UI that a switch to the print monitor should happen
- Application.getInstance().getController().setActiveStage("MonitorStage")
+ if is_job_sent:
+ Application.getInstance().getController().setActiveStage("MonitorStage")
def _spawnPrinterSelectionDialog(self):
if self._printer_selection_dialog is None:
@@ -111,14 +115,14 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice):
@pyqtSlot()
@pyqtSlot(str)
- def sendPrintJob(self, target_printer = ""):
+ def sendPrintJob(self, target_printer: str = ""):
Logger.log("i", "Sending print job to printer.")
if self._sending_gcode:
self._error_message = Message(
i18n_catalog.i18nc("@info:status",
"Sending new jobs (temporarily) blocked, still sending the previous print job."))
self._error_message.show()
- return
+ return False
self._sending_gcode = True
@@ -131,7 +135,7 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice):
compressed_gcode = self._compressGCode()
if compressed_gcode is None:
# Abort was called.
- return
+ return False
parts = []
@@ -147,14 +151,16 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice):
parts.append(self._createFormPart("name=\"file\"; filename=\"%s\"" % file_name, compressed_gcode))
- self.postFormWithParts("print_jobs/", parts, onFinished=self._onPostPrintJobFinished, onProgress=self._onUploadPrintJobProgress)
+ self._latest_reply_handler = self.postFormWithParts("print_jobs/", parts, onFinished=self._onPostPrintJobFinished, onProgress=self._onUploadPrintJobProgress)
+
+ return True
@pyqtProperty(QObject, notify=activePrinterChanged)
- def activePrinter(self) -> Optional["PrinterOutputModel"]:
+ def activePrinter(self) -> Optional[PrinterOutputModel]:
return self._active_printer
@pyqtSlot(QObject)
- def setActivePrinter(self, printer):
+ def setActivePrinter(self, printer: Optional[PrinterOutputModel]):
if self._active_printer != printer:
if self._active_printer and self._active_printer.camera:
self._active_printer.camera.stop()
@@ -166,7 +172,7 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice):
self._compressing_gcode = False
self._sending_gcode = False
- def _onUploadPrintJobProgress(self, bytes_sent, bytes_total):
+ def _onUploadPrintJobProgress(self, bytes_sent:int, bytes_total:int):
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
@@ -179,7 +185,7 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice):
self._progress_message.setProgress(0)
self._progress_message.hide()
- def _progressMessageActionTriggered(self, message_id=None, action_id=None):
+ def _progressMessageActionTriggered(self, message_id: Optional[str]=None, action_id: Optional[str]=None) -> None:
if action_id == "Abort":
Logger.log("d", "User aborted sending print to remote.")
self._progress_message.hide()
@@ -187,30 +193,37 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice):
self._sending_gcode = False
Application.getInstance().getController().setActiveStage("PrepareStage")
+ # After compressing the sliced model Cura sends data to printer, to stop receiving updates from the request
+ # the "reply" should be disconnected
+ if self._latest_reply_handler:
+ self._latest_reply_handler.disconnect()
+ self._latest_reply_handler = None
+
+
@pyqtSlot()
- def openPrintJobControlPanel(self):
+ def openPrintJobControlPanel(self) -> None:
Logger.log("d", "Opening print job control panel...")
QDesktopServices.openUrl(QUrl("http://" + self._address + "/print_jobs"))
@pyqtSlot()
- def openPrinterControlPanel(self):
+ def openPrinterControlPanel(self) -> None:
Logger.log("d", "Opening printer control panel...")
QDesktopServices.openUrl(QUrl("http://" + self._address + "/printers"))
@pyqtProperty("QVariantList", notify=printJobsChanged)
- def printJobs(self):
+ def printJobs(self)-> List[PrintJobOutputModel] :
return self._print_jobs
@pyqtProperty("QVariantList", notify=printJobsChanged)
- def queuedPrintJobs(self):
- return [print_job for print_job in self._print_jobs if print_job.assignedPrinter is None]
+ def queuedPrintJobs(self) -> List[PrintJobOutputModel]:
+ return [print_job for print_job in self._print_jobs if print_job.assignedPrinter is None or print_job.state == "queued"]
@pyqtProperty("QVariantList", notify=printJobsChanged)
- def activePrintJobs(self):
- return [print_job for print_job in self._print_jobs if print_job.assignedPrinter is not None]
+ def activePrintJobs(self) -> List[PrintJobOutputModel]:
+ return [print_job for print_job in self._print_jobs if print_job.assignedPrinter is not None and print_job.state != "queued"]
@pyqtProperty("QVariantList", notify=clusterPrintersChanged)
- def connectedPrintersTypeCount(self):
+ def connectedPrintersTypeCount(self) -> List[PrinterOutputModel]:
printer_count = {}
for printer in self._printers:
if printer.type in printer_count:
@@ -223,22 +236,22 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice):
return result
@pyqtSlot(int, result=str)
- def formatDuration(self, seconds):
+ def formatDuration(self, seconds: int) -> str:
return Duration(seconds).getDisplayString(DurationFormat.Format.Short)
@pyqtSlot(int, result=str)
- def getTimeCompleted(self, time_remaining):
+ 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)
@pyqtSlot(int, result=str)
- def getDateCompleted(self, time_remaining):
+ 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()
- def _printJobStateChanged(self):
+ def _printJobStateChanged(self) -> None:
username = self._getUserName()
if username is None:
@@ -261,13 +274,13 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice):
# Keep a list of all completed jobs so we know if something changed next time.
self._finished_jobs = finished_jobs
- def _update(self):
+ def _update(self) -> None:
if not super()._update():
return
self.get("printers/", onFinished=self._onGetPrintersDataFinished)
self.get("print_jobs/", onFinished=self._onGetPrintJobsFinished)
- def _onGetPrintJobsFinished(self, reply: QNetworkReply):
+ def _onGetPrintJobsFinished(self, reply: QNetworkReply) -> None:
if not checkValidGetReply(reply):
return
@@ -287,7 +300,11 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice):
self._updatePrintJob(print_job, print_job_data)
if print_job.state != "queued": # Print job should be assigned to a printer.
- printer = self._getPrinterByKey(print_job_data["printer_uuid"])
+ if print_job.state in ["failed", "finished", "aborted"]:
+ # Print job was already completed, so don't attach it to a printer.
+ printer = None
+ else:
+ printer = self._getPrinterByKey(print_job_data["printer_uuid"])
else: # The job can "reserve" a printer if some changes are required.
printer = self._getPrinterByKey(print_job_data["assigned_to"])
@@ -305,7 +322,7 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice):
if job_list_changed:
self.printJobsChanged.emit() # Do a single emit for all print job changes.
- def _onGetPrintersDataFinished(self, reply: QNetworkReply):
+ def _onGetPrintersDataFinished(self, reply: QNetworkReply) -> None:
if not checkValidGetReply(reply):
return
@@ -334,34 +351,45 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice):
if removed_printers or printer_list_changed:
self.printersChanged.emit()
- def _createPrinterModel(self, data):
+ def _createPrinterModel(self, data: Dict) -> PrinterOutputModel:
printer = PrinterOutputModel(output_controller=ClusterUM3PrinterOutputController(self),
number_of_extruders=self._number_of_extruders)
printer.setCamera(NetworkCamera("http://" + data["ip_address"] + ":8080/?action=stream"))
self._printers.append(printer)
return printer
- def _createPrintJobModel(self, data):
+ def _createPrintJobModel(self, data: Dict) -> PrintJobOutputModel:
print_job = PrintJobOutputModel(output_controller=ClusterUM3PrinterOutputController(self),
key=data["uuid"], name= data["name"])
print_job.stateChanged.connect(self._printJobStateChanged)
self._print_jobs.append(print_job)
return print_job
- def _updatePrintJob(self, print_job, data):
+ def _updatePrintJob(self, print_job: PrintJobOutputModel, data: Dict) -> None:
print_job.updateTimeTotal(data["time_total"])
print_job.updateTimeElapsed(data["time_elapsed"])
print_job.updateState(data["status"])
print_job.updateOwner(data["owner"])
- def _updatePrinter(self, printer, data):
+ def _updatePrinter(self, printer: PrinterOutputModel, data: Dict) -> None:
# For some unknown reason the cluster wants UUID for everything, except for sending a job directly to a printer.
# Then we suddenly need the unique name. So in order to not have to mess up all the other code, we save a mapping.
self._printer_uuid_to_unique_name_mapping[data["uuid"]] = data["unique_name"]
+ definitions = ContainerRegistry.getInstance().findDefinitionContainers(name = data["machine_variant"])
+ if not definitions:
+ Logger.log("w", "Unable to find definition for machine variant %s", data["machine_variant"])
+ return
+
+ machine_definition = definitions[0]
+
printer.updateName(data["friendly_name"])
printer.updateKey(data["uuid"])
printer.updateType(data["machine_variant"])
+
+ # Do not store the buildplate information that comes from connect if the current printer has not buildplate information
+ if "build_plate" in data and machine_definition.getMetaDataEntry("has_variant_buildplates", False):
+ printer.updateBuildplateName(data["build_plate"]["type"])
if not data["enabled"]:
printer.updateState("disabled")
else:
@@ -392,13 +420,13 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice):
color = material_data["color"]
brand = material_data["brand"]
material_type = material_data["material"]
- name = "Unknown"
+ name = "Empty" if material_data["material"] == "empty" else "Unknown"
material = MaterialOutputModel(guid=material_data["guid"], type=material_type,
brand=brand, color=color, name=name)
extruder.updateActiveMaterial(material)
- def _removeJob(self, job):
+ def _removeJob(self, job: PrintJobOutputModel):
if job not in self._print_jobs:
return False
@@ -409,7 +437,7 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice):
return True
- def _removePrinter(self, printer):
+ def _removePrinter(self, printer: PrinterOutputModel):
self._printers.remove(printer)
if self._active_printer == printer:
self._active_printer = None
diff --git a/plugins/UM3NetworkPrinting/DiscoverUM3Action.py b/plugins/UM3NetworkPrinting/DiscoverUM3Action.py
index 0e872fed43..76e8721fdd 100644
--- a/plugins/UM3NetworkPrinting/DiscoverUM3Action.py
+++ b/plugins/UM3NetworkPrinting/DiscoverUM3Action.py
@@ -97,6 +97,25 @@ class DiscoverUM3Action(MachineAction):
else:
return []
+ @pyqtSlot(str)
+ def setGroupName(self, group_name):
+ Logger.log("d", "Attempting to set the group name of the active machine to %s", group_name)
+ global_container_stack = Application.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
+ Application.getInstance().getMachineManager().replaceContainersMetadata(key = "connect_group_name", value = previous_connect_group_name, new_value = group_name)
+ else:
+ global_container_stack.addMetaDataEntry("connect_group_name", group_name)
+ global_container_stack.addMetaDataEntry("hidden", False)
+
+ if self._network_plugin:
+ # Ensure that the connection states are refreshed.
+ self._network_plugin.reCheckConnections()
+
@pyqtSlot(str)
def setKey(self, key):
Logger.log("d", "Attempting to set the network key of the active machine to %s", key)
@@ -104,11 +123,13 @@ class DiscoverUM3Action(MachineAction):
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")
+ Application.getInstance().getMachineManager().replaceContainersMetadata(key = "um_network_key", value = previous_network_key, new_value = key)
else:
global_container_stack.addMetaDataEntry("um_network_key", key)
diff --git a/plugins/UM3NetworkPrinting/DiscoverUM3Action.qml b/plugins/UM3NetworkPrinting/DiscoverUM3Action.qml
index 0e58d8e991..079e5dcdd3 100644
--- a/plugins/UM3NetworkPrinting/DiscoverUM3Action.qml
+++ b/plugins/UM3NetworkPrinting/DiscoverUM3Action.qml
@@ -32,10 +32,12 @@ Cura.MachineAction
if(base.selectedDevice && base.completeProperties)
{
var printerKey = base.selectedDevice.key
+ var printerName = base.selectedDevice.name // TODO To change when the groups have a name
if(manager.getStoredKey() != printerKey)
{
- manager.setKey(printerKey);
- completed();
+ manager.setKey(printerKey)
+ manager.setGroupName(printerName) // TODO To change when the groups have a name
+ completed()
}
}
}
@@ -114,7 +116,7 @@ Cura.MachineAction
Column
{
- width: Math.floor(parent.width * 0.5)
+ width: Math.round(parent.width * 0.5)
spacing: UM.Theme.getSize("default_margin").height
ScrollView
@@ -198,7 +200,7 @@ Cura.MachineAction
}
Column
{
- width: Math.floor(parent.width * 0.5)
+ width: Math.round(parent.width * 0.5)
visible: base.selectedDevice ? true : false
spacing: UM.Theme.getSize("default_margin").height
Label
@@ -216,13 +218,13 @@ Cura.MachineAction
columns: 2
Label
{
- width: Math.floor(parent.width * 0.5)
+ width: Math.round(parent.width * 0.5)
wrapMode: Text.WordWrap
text: catalog.i18nc("@label", "Type")
}
Label
{
- width: Math.floor(parent.width * 0.5)
+ width: Math.round(parent.width * 0.5)
wrapMode: Text.WordWrap
text:
{
@@ -247,25 +249,25 @@ Cura.MachineAction
}
Label
{
- width: Math.floor(parent.width * 0.5)
+ width: Math.round(parent.width * 0.5)
wrapMode: Text.WordWrap
text: catalog.i18nc("@label", "Firmware version")
}
Label
{
- width: Math.floor(parent.width * 0.5)
+ width: Math.round(parent.width * 0.5)
wrapMode: Text.WordWrap
text: base.selectedDevice ? base.selectedDevice.firmwareVersion : ""
}
Label
{
- width: Math.floor(parent.width * 0.5)
+ width: Math.round(parent.width * 0.5)
wrapMode: Text.WordWrap
text: catalog.i18nc("@label", "Address")
}
Label
{
- width: Math.floor(parent.width * 0.5)
+ width: Math.round(parent.width * 0.5)
wrapMode: Text.WordWrap
text: base.selectedDevice ? base.selectedDevice.ipAddress : ""
}
@@ -303,7 +305,7 @@ Cura.MachineAction
Button
{
text: catalog.i18nc("@action:button", "Connect")
- enabled: (base.selectedDevice && base.completeProperties) ? true : false
+ enabled: (base.selectedDevice && base.completeProperties && base.selectedDevice.clusterSize > 0) ? true : false
onClicked: connectToPrinter()
}
}
diff --git a/plugins/UM3NetworkPrinting/LegacyUM3OutputDevice.py b/plugins/UM3NetworkPrinting/LegacyUM3OutputDevice.py
index 647a7f822c..42f00beceb 100644
--- a/plugins/UM3NetworkPrinting/LegacyUM3OutputDevice.py
+++ b/plugins/UM3NetworkPrinting/LegacyUM3OutputDevice.py
@@ -184,7 +184,7 @@ class LegacyUM3OutputDevice(NetworkedPrinterOutputDevice):
self.writeStarted.emit(self)
gcode_dict = getattr(Application.getInstance().getController().getScene(), "gcode_dict", [])
- active_build_plate_id = Application.getInstance().getBuildPlateModel().activeBuildPlate
+ active_build_plate_id = Application.getInstance().getMultiBuildPlateModel().activeBuildPlate
gcode_list = gcode_dict[active_build_plate_id]
if not gcode_list:
@@ -419,8 +419,6 @@ class LegacyUM3OutputDevice(NetworkedPrinterOutputDevice):
self._authentication_failed_message.show()
elif status_code == 200:
self.setAuthenticationState(AuthState.Authenticated)
- # Now we know for sure that we are authenticated, send the material profiles to the machine.
- self._sendMaterialProfiles()
def _checkAuthentication(self):
Logger.log("d", "Checking if authentication is correct for id %s and key %s", self._authentication_id, self._getSafeAuthKey())
diff --git a/plugins/UM3NetworkPrinting/PrintCoreConfiguration.qml b/plugins/UM3NetworkPrinting/PrintCoreConfiguration.qml
index 70fa65da5e..267516091b 100644
--- a/plugins/UM3NetworkPrinting/PrintCoreConfiguration.qml
+++ b/plugins/UM3NetworkPrinting/PrintCoreConfiguration.qml
@@ -10,7 +10,7 @@ Item
id: extruderInfo
property var printCoreConfiguration
- width: Math.floor(parent.width / 2)
+ width: Math.round(parent.width / 2)
height: childrenRect.height
Label
{
diff --git a/plugins/UM3NetworkPrinting/PrinterInfoBlock.qml b/plugins/UM3NetworkPrinting/PrinterInfoBlock.qml
index 6d7d6c8a7d..54a34fae46 100644
--- a/plugins/UM3NetworkPrinting/PrinterInfoBlock.qml
+++ b/plugins/UM3NetworkPrinting/PrinterInfoBlock.qml
@@ -78,7 +78,7 @@ Rectangle
Rectangle
{
- width: Math.floor(parent.width / 3)
+ width: Math.round(parent.width / 3)
height: parent.height
Label // Print job name
@@ -123,7 +123,7 @@ Rectangle
Rectangle
{
- width: Math.floor(parent.width / 3 * 2)
+ width: Math.round(parent.width / 3 * 2)
height: parent.height
Label // Friendly machine name
@@ -131,7 +131,7 @@ Rectangle
id: printerNameLabel
anchors.top: parent.top
anchors.left: parent.left
- width: Math.floor(parent.width / 2 - UM.Theme.getSize("default_margin").width - showCameraIcon.width)
+ width: Math.round(parent.width / 2 - UM.Theme.getSize("default_margin").width - showCameraIcon.width)
text: printer.name
font: UM.Theme.getFont("default_bold")
elide: Text.ElideRight
@@ -141,7 +141,7 @@ Rectangle
{
id: printerTypeLabel
anchors.top: printerNameLabel.bottom
- width: Math.floor(parent.width / 2 - UM.Theme.getSize("default_margin").width)
+ width: Math.round(parent.width / 2 - UM.Theme.getSize("default_margin").width)
text: printer.type
anchors.left: parent.left
elide: Text.ElideRight
@@ -175,7 +175,7 @@ Rectangle
id: extruderInfo
anchors.bottom: parent.bottom
- width: Math.floor(parent.width / 2 - UM.Theme.getSize("default_margin").width)
+ width: Math.round(parent.width / 2 - UM.Theme.getSize("default_margin").width)
height: childrenRect.height
spacing: UM.Theme.getSize("default_margin").width
@@ -183,7 +183,7 @@ Rectangle
PrintCoreConfiguration
{
id: leftExtruderInfo
- width: Math.floor((parent.width - extruderSeperator.width) / 2)
+ width: Math.round((parent.width - extruderSeperator.width) / 2)
printCoreConfiguration: printer.extruders[0]
}
@@ -198,7 +198,7 @@ Rectangle
PrintCoreConfiguration
{
id: rightExtruderInfo
- width: Math.floor((parent.width - extruderSeperator.width) / 2)
+ width: Math.round((parent.width - extruderSeperator.width) / 2)
printCoreConfiguration: printer.extruders[1]
}
}
@@ -209,7 +209,7 @@ Rectangle
anchors.right: parent.right
anchors.top: parent.top
height: showExtended ? parent.height: printProgressTitleBar.height
- width: Math.floor(parent.width / 2 - UM.Theme.getSize("default_margin").width)
+ width: Math.round(parent.width / 2 - UM.Theme.getSize("default_margin").width)
border.width: UM.Theme.getSize("default_lining").width
border.color: lineColor
radius: cornerRadius
@@ -264,6 +264,7 @@ Rectangle
case "wait_for_configuration":
return catalog.i18nc("@label:status", "Reserved")
case "wait_cleanup":
+ case "wait_user_action":
return catalog.i18nc("@label:status", "Finished")
case "pre_print":
case "sent_to_printer":
@@ -278,6 +279,7 @@ Rectangle
case "aborted":
return catalog.i18nc("@label:status", "Print aborted");
default:
+ // If print job has unknown status show printer.status
return printerStatusText(printer);
}
}
@@ -413,7 +415,7 @@ Rectangle
{
if(printJob.state == "printing" || printJob.state == "post_print")
{
- return OutputDevice.getDateCompleted(printJob.time_total - printJob.time_elapsed)
+ return OutputDevice.getDateCompleted(printJob.timeTotal - printJob.timeElapsed)
}
}
return "";
diff --git a/plugins/UM3NetworkPrinting/PrinterVideoStream.qml b/plugins/UM3NetworkPrinting/PrinterVideoStream.qml
index 3e6f6a8fd8..7f7b2ad546 100644
--- a/plugins/UM3NetworkPrinting/PrinterVideoStream.qml
+++ b/plugins/UM3NetworkPrinting/PrinterVideoStream.qml
@@ -57,7 +57,7 @@ Item
{
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)
+ height: Math.round((sourceSize.height === 0 ? 600 * screenScaleFactor : sourceSize.height) * width / sourceSize.width)
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
z: 1
diff --git a/plugins/UM3NetworkPrinting/UM3InfoComponents.qml b/plugins/UM3NetworkPrinting/UM3InfoComponents.qml
index 18b481a6ed..5a9cc096e7 100644
--- a/plugins/UM3NetworkPrinting/UM3InfoComponents.qml
+++ b/plugins/UM3NetworkPrinting/UM3InfoComponents.qml
@@ -10,7 +10,8 @@ Item
{
id: base
- property bool isUM3: Cura.MachineManager.activeQualityDefinitionId == "ultimaker3"
+ property string activeQualityDefinitionId: Cura.MachineManager.activeQualityDefinitionId
+ property bool isUM3: activeQualityDefinitionId == "ultimaker3" || activeQualityDefinitionId.match("ultimaker_") != null
property bool printerConnected: Cura.MachineManager.printerOutputDevices.length != 0
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.
diff --git a/plugins/UM3NetworkPrinting/UM3OutputDevicePlugin.py b/plugins/UM3NetworkPrinting/UM3OutputDevicePlugin.py
index c639c25007..5ff5eb9e3e 100644
--- a/plugins/UM3NetworkPrinting/UM3OutputDevicePlugin.py
+++ b/plugins/UM3NetworkPrinting/UM3OutputDevicePlugin.py
@@ -126,7 +126,7 @@ class UM3OutputDevicePlugin(OutputDevicePlugin):
def removeManualDevice(self, key, address = None):
if key in self._discovered_devices:
if not address:
- address = self._printers[key].ipAddress
+ address = self._discovered_devices[key].ipAddress
self._onRemoveDevice(key)
if address in self._manual_instances:
diff --git a/plugins/USBPrinting/AutoDetectBaudJob.py b/plugins/USBPrinting/AutoDetectBaudJob.py
index 72f4f20262..50bb831ba8 100644
--- a/plugins/USBPrinting/AutoDetectBaudJob.py
+++ b/plugins/USBPrinting/AutoDetectBaudJob.py
@@ -22,6 +22,7 @@ class AutoDetectBaudJob(Job):
def run(self):
Logger.log("d", "Auto detect baud rate started.")
timeout = 3
+ tries = 2
programmer = Stk500v2()
serial = None
@@ -31,36 +32,38 @@ class AutoDetectBaudJob(Job):
except:
programmer.close()
- for baud_rate in self._all_baud_rates:
- Logger.log("d", "Checking {serial} if baud rate {baud_rate} works".format(serial= self._serial_port, baud_rate = baud_rate))
+ for retry in range(tries):
+ for baud_rate in self._all_baud_rates:
+ Logger.log("d", "Checking {serial} if baud rate {baud_rate} works".format(serial= self._serial_port, baud_rate = baud_rate))
- if serial is None:
- try:
- serial = Serial(str(self._serial_port), baud_rate, timeout = timeout, writeTimeout = timeout)
- except SerialException as e:
- Logger.logException("w", "Unable to create serial")
- continue
- else:
- # We already have a serial connection, just change the baud rate.
- try:
- serial.baudrate = baud_rate
- except:
- continue
- sleep(1.5) # Ensure that we are not talking to the boot loader. 1.5 seconds seems to be the magic number
- successful_responses = 0
-
- serial.write(b"\n") # Ensure we clear out previous responses
- serial.write(b"M105\n")
-
- timeout_time = time() + timeout
-
- while timeout_time > time():
- line = serial.readline()
- if b"ok T:" in line:
- successful_responses += 1
- if successful_responses >= 3:
- self.setResult(baud_rate)
- return
+ if serial is None:
+ try:
+ serial = Serial(str(self._serial_port), baud_rate, timeout = timeout, writeTimeout = timeout)
+ except SerialException as e:
+ Logger.logException("w", "Unable to create serial")
+ continue
+ else:
+ # We already have a serial connection, just change the baud rate.
+ try:
+ serial.baudrate = baud_rate
+ except:
+ continue
+ sleep(1.5) # Ensure that we are not talking to the boot loader. 1.5 seconds seems to be the magic number
+ successful_responses = 0
+ serial.write(b"\n") # Ensure we clear out previous responses
serial.write(b"M105\n")
+
+ timeout_time = time() + timeout
+
+ while timeout_time > time():
+ line = serial.readline()
+ if b"ok T:" in line:
+ successful_responses += 1
+ if successful_responses >= 3:
+ self.setResult(baud_rate)
+ return
+
+ serial.write(b"M105\n")
+ 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/USBPrinterOutputController.py b/plugins/USBPrinting/USBPrinterOutputController.py
index ba45e7b0ca..f189ed5876 100644
--- a/plugins/USBPrinting/USBPrinterOutputController.py
+++ b/plugins/USBPrinting/USBPrinterOutputController.py
@@ -10,7 +10,7 @@ if MYPY:
from cura.PrinterOutput.PrinterOutputModel import PrinterOutputModel
-class USBPrinterOuptutController(PrinterOutputController):
+class USBPrinterOutputController(PrinterOutputController):
def __init__(self, output_device):
super().__init__(output_device)
diff --git a/plugins/USBPrinting/USBPrinterOutputDevice.py b/plugins/USBPrinting/USBPrinterOutputDevice.py
index d372b54c38..14098b66f8 100644
--- a/plugins/USBPrinting/USBPrinterOutputDevice.py
+++ b/plugins/USBPrinting/USBPrinterOutputDevice.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2016 Ultimaker B.V.
+# Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
from UM.Logger import Logger
@@ -12,12 +12,12 @@ from cura.PrinterOutput.PrinterOutputModel import PrinterOutputModel
from cura.PrinterOutput.PrintJobOutputModel import PrintJobOutputModel
from .AutoDetectBaudJob import AutoDetectBaudJob
-from .USBPrinterOutputController import USBPrinterOuptutController
+from .USBPrinterOutputController import USBPrinterOutputController
from .avr_isp import stk500v2, intelHex
from PyQt5.QtCore import pyqtSlot, pyqtSignal, pyqtProperty
-from serial import Serial, SerialException
+from serial import Serial, SerialException, SerialTimeoutException
from threading import Thread
from time import time, sleep
from queue import Queue
@@ -99,7 +99,7 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
Application.getInstance().getController().setActiveStage("MonitorStage")
# find the G-code for the active build plate to print
- active_build_plate_id = Application.getInstance().getBuildPlateModel().activeBuildPlate
+ active_build_plate_id = Application.getInstance().getMultiBuildPlateModel().activeBuildPlate
gcode_dict = getattr(Application.getInstance().getController().getScene(), "gcode_dict")
gcode_list = gcode_dict[active_build_plate_id]
@@ -116,7 +116,8 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
@pyqtSlot(str)
def updateFirmware(self, file):
- self._firmware_location = file
+ # the file path is qurl encoded.
+ self._firmware_location = file.replace("file://", "")
self.showFirmwareInterface()
self.setFirmwareUpdateState(FirmwareUpdateState.updating)
self._update_firmware_thread.start()
@@ -126,9 +127,11 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
if self._connection_state != ConnectionState.closed:
self.close()
- hex_file = intelHex.readHex(self._firmware_location)
- if len(hex_file) == 0:
- Logger.log("e", "Unable to read provided hex file. Could not update firmware")
+ 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)
return
@@ -198,7 +201,6 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
# Reset line number. If this is not done, first line is sometimes ignored
self._gcode.insert(0, "M110")
self._gcode_position = 0
- self._is_printing = True
self._print_start_time = time()
self._print_estimated_time = int(Application.getInstance().getPrintInformation().currentPrintTime.getDisplayString(DurationFormat.Format.Seconds))
@@ -206,6 +208,7 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
for i in range(0, 4): # Push first 4 entries before accepting other inputs
self._sendNextGcodeLine()
+ self._is_printing = True
self.writeFinished.emit(self)
def _autoDetectFinished(self, job: AutoDetectBaudJob):
@@ -237,7 +240,7 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
container_stack = Application.getInstance().getGlobalContainerStack()
num_extruders = container_stack.getProperty("machine_extruder_count", "value")
# Ensure that a printer is created.
- self._printers = [PrinterOutputModel(output_controller=USBPrinterOuptutController(self), number_of_extruders=num_extruders)]
+ self._printers = [PrinterOutputModel(output_controller=USBPrinterOutputController(self), number_of_extruders=num_extruders)]
self._printers[0].updateName(container_stack.getName())
self.setConnectionState(ConnectionState.connected)
self._update_thread.start()
@@ -266,8 +269,10 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
command = (command + "\n").encode()
if not command.endswith(b"\n"):
command += b"\n"
- self._serial.write(b"\n")
- self._serial.write(command)
+ try:
+ self._serial.write(command)
+ except SerialTimeoutException:
+ Logger.log("w", "Timeout when sending command to printer via USB.")
def _update(self):
while self._connection_state == ConnectionState.connected and self._serial is not None:
@@ -281,7 +286,7 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
self.sendCommand("M105")
self._last_temperature_request = time()
- if b"ok T:" in line or line.startswith(b"T:"): # Temperature message
+ if b"ok T:" in line or line.startswith(b"T:") or b"ok B:" in line or line.startswith(b"B:"): # Temperature message. 'T:' for extruder and 'B:' for bed
extruder_temperature_matches = re.findall(b"T(\d*): ?([\d\.]+) ?\/?([\d\.]+)?", line)
# Update all temperature values
for match, extruder in zip(extruder_temperature_matches, self._printers[0].extruders):
@@ -299,6 +304,9 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
self._printers[0].updateTargetBedTemperature(float(match[1]))
if self._is_printing:
+ if line.startswith(b'!!'):
+ Logger.log('e', "Printer signals fatal error. Cancelling print. {}".format(line))
+ self.cancelPrint()
if b"ok" in line:
if not self._command_queue.empty():
self._sendCommand(self._command_queue.get())
@@ -364,7 +372,7 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
elapsed_time = int(time() - self._print_start_time)
print_job = self._printers[0].activePrintJob
if print_job is None:
- print_job = PrintJobOutputModel(output_controller = USBPrinterOuptutController(self), name= Application.getInstance().getPrintInformation().jobName)
+ print_job = PrintJobOutputModel(output_controller = USBPrinterOutputController(self), name= Application.getInstance().getPrintInformation().jobName)
print_job.updateState("printing")
self._printers[0].updateActivePrintJob(print_job)
diff --git a/plugins/UltimakerMachineActions/BedLevelMachineAction.py b/plugins/UltimakerMachineActions/BedLevelMachineAction.py
index 04b6cf1acc..6a8a337d8c 100644
--- a/plugins/UltimakerMachineActions/BedLevelMachineAction.py
+++ b/plugins/UltimakerMachineActions/BedLevelMachineAction.py
@@ -1,3 +1,8 @@
+# Copyright (c) 2018 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+
+from typing import List
+
from cura.MachineAction import MachineAction
from cura.PrinterOutputDevice import PrinterOutputDevice
@@ -5,6 +10,7 @@ from UM.FlameProfiler import pyqtSlot
from UM.Application import Application
from UM.i18n import i18nCatalog
+from UM.Logger import Logger
catalog = i18nCatalog("cura")
@@ -26,38 +32,45 @@ class BedLevelMachineAction(MachineAction):
@pyqtSlot()
def startBedLeveling(self):
self._bed_level_position = 0
- printer_output_devices = self._getPrinterOutputDevices()
- if printer_output_devices:
- printer_output_devices[0].homeBed()
- printer_output_devices[0].moveHead(0, 0, 3)
- printer_output_devices[0].homeHead()
- def _getPrinterOutputDevices(self):
+ printer_output_devices = self._getPrinterOutputDevices()
+ if not printer_output_devices:
+ Logger.log("e", "Can't start bed levelling. The printer connection seems to have been lost.")
+ return
+ printer = printer_output_devices[0].activePrinter
+
+ printer.homeBed()
+ printer.moveHead(0, 0, 3)
+ printer.homeHead()
+
+ def _getPrinterOutputDevices(self) -> List[PrinterOutputDevice]:
return [printer_output_device for printer_output_device in Application.getInstance().getOutputDeviceManager().getOutputDevices() if isinstance(printer_output_device, PrinterOutputDevice)]
@pyqtSlot()
def moveToNextLevelPosition(self):
output_devices = self._getPrinterOutputDevices()
- if output_devices: # We found at least one output device
- output_device = output_devices[0]
+ if not output_devices: #No output devices. Can't move.
+ Logger.log("e", "Can't move to the next position. The printer connection seems to have been lost.")
+ return
+ printer = output_devices[0].activePrinter
- if self._bed_level_position == 0:
- output_device.moveHead(0, 0, 3)
- output_device.homeHead()
- output_device.moveHead(0, 0, 3)
- output_device.moveHead(Application.getInstance().getGlobalContainerStack().getProperty("machine_width", "value") - 10, 0, 0)
- output_device.moveHead(0, 0, -3)
- self._bed_level_position += 1
- elif self._bed_level_position == 1:
- output_device.moveHead(0, 0, 3)
- output_device.moveHead(-Application.getInstance().getGlobalContainerStack().getProperty("machine_width", "value" ) / 2, Application.getInstance().getGlobalContainerStack().getProperty("machine_depth", "value") - 10, 0)
- output_device.moveHead(0, 0, -3)
- self._bed_level_position += 1
- elif self._bed_level_position == 2:
- output_device.moveHead(0, 0, 3)
- output_device.moveHead(-Application.getInstance().getGlobalContainerStack().getProperty("machine_width", "value") / 2 + 10, -(Application.getInstance().getGlobalContainerStack().getProperty("machine_depth", "value") + 10), 0)
- output_device.moveHead(0, 0, -3)
- self._bed_level_position += 1
- elif self._bed_level_position >= 3:
- output_device.sendCommand("M18") # Turn off all motors so the user can move the axes
- self.setFinished()
\ No newline at end of file
+ if self._bed_level_position == 0:
+ printer.moveHead(0, 0, 3)
+ printer.homeHead()
+ printer.moveHead(0, 0, 3)
+ printer.moveHead(Application.getInstance().getGlobalContainerStack().getProperty("machine_width", "value") - 10, 0, 0)
+ printer.moveHead(0, 0, -3)
+ self._bed_level_position += 1
+ elif self._bed_level_position == 1:
+ printer.moveHead(0, 0, 3)
+ printer.moveHead(-Application.getInstance().getGlobalContainerStack().getProperty("machine_width", "value" ) / 2, Application.getInstance().getGlobalContainerStack().getProperty("machine_depth", "value") - 10, 0)
+ printer.moveHead(0, 0, -3)
+ self._bed_level_position += 1
+ elif self._bed_level_position == 2:
+ printer.moveHead(0, 0, 3)
+ printer.moveHead(-Application.getInstance().getGlobalContainerStack().getProperty("machine_width", "value") / 2 + 10, -(Application.getInstance().getGlobalContainerStack().getProperty("machine_depth", "value") + 10), 0)
+ printer.moveHead(0, 0, -3)
+ self._bed_level_position += 1
+ elif self._bed_level_position >= 3:
+ output_devices[0].sendCommand("M18") # Turn off all motors so the user can move the axes
+ self.setFinished()
\ No newline at end of file
diff --git a/plugins/UltimakerMachineActions/UM2UpgradeSelection.py b/plugins/UltimakerMachineActions/UM2UpgradeSelection.py
index 1bf0b98217..e21256f6bd 100644
--- a/plugins/UltimakerMachineActions/UM2UpgradeSelection.py
+++ b/plugins/UltimakerMachineActions/UM2UpgradeSelection.py
@@ -1,8 +1,7 @@
-# Copyright (c) 2017 Ultimaker B.V.
+# Copyright (c) 2018 Ultimaker B.V.
# Uranium is released under the terms of the LGPLv3 or higher.
from UM.Settings.ContainerRegistry import ContainerRegistry
-from UM.Settings.InstanceContainer import InstanceContainer
from cura.MachineAction import MachineAction
from PyQt5.QtCore import pyqtSlot, pyqtSignal, pyqtProperty
@@ -11,8 +10,6 @@ from UM.Application import Application
from UM.Util import parseBool
catalog = i18nCatalog("cura")
-import UM.Settings.InstanceContainer
-
## The Ultimaker 2 can have a few revisions & upgrades.
class UM2UpgradeSelection(MachineAction):
@@ -22,18 +19,28 @@ class UM2UpgradeSelection(MachineAction):
self._container_registry = ContainerRegistry.getInstance()
+ self._current_global_stack = None
+
+ Application.getInstance().globalContainerStackChanged.connect(self._onGlobalStackChanged)
+ self._reset()
+
def _reset(self):
self.hasVariantsChanged.emit()
+ def _onGlobalStackChanged(self):
+ if self._current_global_stack:
+ self._current_global_stack.metaDataChanged.disconnect(self._onGlobalStackMetaDataChanged)
+
+ self._current_global_stack = Application.getInstance().getGlobalContainerStack()
+ if self._current_global_stack:
+ self._current_global_stack.metaDataChanged.connect(self._onGlobalStackMetaDataChanged)
+ self._reset()
+
+ def _onGlobalStackMetaDataChanged(self):
+ self._reset()
+
hasVariantsChanged = pyqtSignal()
- @pyqtProperty(bool, notify = hasVariantsChanged)
- def hasVariants(self):
- global_container_stack = Application.getInstance().getGlobalContainerStack()
- if global_container_stack:
- return parseBool(global_container_stack.getMetaDataEntry("has_variants", "false"))
-
- @pyqtSlot(bool)
def setHasVariants(self, has_variants = True):
global_container_stack = Application.getInstance().getGlobalContainerStack()
if global_container_stack:
@@ -62,3 +69,9 @@ class UM2UpgradeSelection(MachineAction):
global_container_stack.extruders["0"].variant = ContainerRegistry.getInstance().getEmptyInstanceContainer()
Application.getInstance().globalContainerStackChanged.emit()
+ self._reset()
+
+ @pyqtProperty(bool, fset = setHasVariants, notify = hasVariantsChanged)
+ def hasVariants(self):
+ if self._current_global_stack:
+ return parseBool(self._current_global_stack.getMetaDataEntry("has_variants", "false"))
diff --git a/plugins/UltimakerMachineActions/UM2UpgradeSelectionMachineAction.qml b/plugins/UltimakerMachineActions/UM2UpgradeSelectionMachineAction.qml
index 988c9d6128..793f3f00a8 100644
--- a/plugins/UltimakerMachineActions/UM2UpgradeSelectionMachineAction.qml
+++ b/plugins/UltimakerMachineActions/UM2UpgradeSelectionMachineAction.qml
@@ -13,6 +13,7 @@ import Cura 1.0 as Cura
Cura.MachineAction
{
anchors.fill: parent;
+
Item
{
id: upgradeSelectionMachineAction
@@ -39,12 +40,19 @@ Cura.MachineAction
CheckBox
{
+ id: olssonBlockCheckBox
anchors.top: pageDescription.bottom
anchors.topMargin: UM.Theme.getSize("default_margin").height
text: catalog.i18nc("@label", "Olsson Block")
checked: manager.hasVariants
- onClicked: manager.setHasVariants(checked)
+ onClicked: manager.hasVariants = checked
+
+ Connections
+ {
+ target: manager
+ onHasVariantsChanged: olssonBlockCheckBox.checked = manager.hasVariants
+ }
}
UM.I18nCatalog { id: catalog; name: "cura"; }
diff --git a/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml b/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml
index 5a1f8f26a7..b92638aa12 100644
--- a/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml
+++ b/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml
@@ -180,7 +180,7 @@ Cura.MachineAction
height: childrenRect.height
anchors.top: nozzleTempLabel.top
anchors.left: bedTempStatus.right
- anchors.leftMargin: UM.Theme.getSize("default_margin").width/2
+ anchors.leftMargin: Math.round(UM.Theme.getSize("default_margin").width/2)
visible: checkupMachineAction.usbConnected
Button
{
@@ -241,7 +241,7 @@ Cura.MachineAction
height: childrenRect.height
anchors.top: bedTempLabel.top
anchors.left: bedTempStatus.right
- anchors.leftMargin: UM.Theme.getSize("default_margin").width/2
+ anchors.leftMargin: Math.round(UM.Theme.getSize("default_margin").width/2)
visible: checkupMachineAction.usbConnected && manager.hasHeatedBed
Button
{
diff --git a/plugins/UserAgreementPlugin/UserAgreement.qml b/plugins/UserAgreementPlugin/UserAgreement.qml
index c7f3f165e3..4ee03f4ad5 100644
--- a/plugins/UserAgreementPlugin/UserAgreement.qml
+++ b/plugins/UserAgreementPlugin/UserAgreement.qml
@@ -9,8 +9,8 @@ import UM 1.3 as UM
UM.Dialog
{
id: baseDialog
- minimumWidth: Math.floor(UM.Theme.getSize("modal_window_minimum").width * 0.75)
- minimumHeight: Math.floor(UM.Theme.getSize("modal_window_minimum").height * 0.5)
+ 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")
diff --git a/plugins/VersionUpgrade/VersionUpgrade22to24/VersionUpgrade.py b/plugins/VersionUpgrade/VersionUpgrade22to24/VersionUpgrade.py
index 19f0563f10..7505911049 100644
--- a/plugins/VersionUpgrade/VersionUpgrade22to24/VersionUpgrade.py
+++ b/plugins/VersionUpgrade/VersionUpgrade22to24/VersionUpgrade.py
@@ -74,7 +74,7 @@ class VersionUpgrade22to24(VersionUpgrade):
def __convertVariant(self, variant_path):
# Copy the variant to the machine_instances/*_settings.inst.cfg
variant_config = configparser.ConfigParser(interpolation=None)
- with open(variant_path, "r") as fhandle:
+ with open(variant_path, "r", encoding = "utf-8") as fhandle:
variant_config.read_file(fhandle)
config_name = "Unknown Variant"
diff --git a/plugins/VersionUpgrade/VersionUpgrade30to31/VersionUpgrade30to31.py b/plugins/VersionUpgrade/VersionUpgrade30to31/VersionUpgrade30to31.py
index 8c5a160ff4..a88ff5ac1c 100644
--- a/plugins/VersionUpgrade/VersionUpgrade30to31/VersionUpgrade30to31.py
+++ b/plugins/VersionUpgrade/VersionUpgrade30to31/VersionUpgrade30to31.py
@@ -3,14 +3,9 @@
import configparser #To parse preference files.
import io #To serialise the preference files afterwards.
-import os
-from urllib.parse import quote_plus
-from UM.Resources import Resources
from UM.VersionUpgrade import VersionUpgrade #We're inheriting from this.
-from cura.CuraApplication import CuraApplication
-
# a list of all legacy "Not Supported" quality profiles
_OLD_NOT_SUPPORTED_PROFILES = [
@@ -59,6 +54,12 @@ _EMPTY_CONTAINER_DICT = {
}
+# Renamed definition files
+_RENAMED_DEFINITION_DICT = {
+ "jellybox": "imade3d_jellybox",
+}
+
+
class VersionUpgrade30to31(VersionUpgrade):
## Gets the version number from a CFG file in Uranium's 3.0 format.
#
@@ -111,16 +112,9 @@ class VersionUpgrade30to31(VersionUpgrade):
if not parser.has_section(each_section):
parser.add_section(each_section)
- # Copy global quality changes to extruder quality changes for single extrusion machines
- if parser["metadata"]["type"] == "quality_changes":
- all_quality_changes = self._getSingleExtrusionMachineQualityChanges(parser)
- # Note that DO NOT!!! use the quality_changes returned from _getSingleExtrusionMachineQualityChanges().
- # Those are loaded from the hard drive which are original files that haven't been upgraded yet.
- # NOTE 2: The number can be 0 or 1 depends on whether you are loading it from the qualities folder or
- # from a project file. When you load from a project file, the custom profile may not be in cura
- # yet, so you will get 0.
- if len(all_quality_changes) <= 1 and not parser.has_option("metadata", "extruder"):
- self._createExtruderQualityChangesForSingleExtrusionMachine(filename, parser)
+ # Check renamed definitions
+ if "definition" in parser["general"] and parser["general"]["definition"] in _RENAMED_DEFINITION_DICT:
+ parser["general"]["definition"] = _RENAMED_DEFINITION_DICT[parser["general"]["definition"]]
# Update version numbers
parser["general"]["version"] = "2"
@@ -131,7 +125,6 @@ class VersionUpgrade30to31(VersionUpgrade):
parser.write(output)
return [filename], [output.getvalue()]
-
## Upgrades a container stack from version 3.0 to 3.1.
#
# \param serialised The serialised form of a container stack.
@@ -156,6 +149,10 @@ class VersionUpgrade30to31(VersionUpgrade):
if parser.has_option("containers", key) and parser["containers"][key] == "empty":
parser["containers"][key] = specific_empty_container
+ # check renamed definition
+ if parser.has_option("containers", "6") and parser["containers"]["6"] in _RENAMED_DEFINITION_DICT:
+ parser["containers"]["6"] = _RENAMED_DEFINITION_DICT[parser["containers"]["6"]]
+
# Update version numbers
if "general" not in parser:
parser["general"] = {}
@@ -169,67 +166,3 @@ class VersionUpgrade30to31(VersionUpgrade):
output = io.StringIO()
parser.write(output)
return [filename], [output.getvalue()]
-
- def _getSingleExtrusionMachineQualityChanges(self, quality_changes_container):
- quality_changes_dir = Resources.getPath(CuraApplication.ResourceTypes.QualityInstanceContainer)
- quality_changes_containers = []
-
- for item in os.listdir(quality_changes_dir):
- file_path = os.path.join(quality_changes_dir, item)
- if not os.path.isfile(file_path):
- continue
-
- parser = configparser.ConfigParser(interpolation = None)
- try:
- parser.read([file_path])
- except:
- # skip, it is not a valid stack file
- continue
-
- if not parser.has_option("metadata", "type"):
- continue
- if "quality_changes" != parser["metadata"]["type"]:
- continue
-
- if not parser.has_option("general", "name"):
- continue
- if quality_changes_container["general"]["name"] != parser["general"]["name"]:
- continue
-
- quality_changes_containers.append(parser)
-
- return quality_changes_containers
-
- def _createExtruderQualityChangesForSingleExtrusionMachine(self, filename, global_quality_changes):
- suffix = "_" + quote_plus(global_quality_changes["general"]["name"].lower())
- machine_name = os.path.os.path.basename(filename).replace(".inst.cfg", "").replace(suffix, "")
-
- # Why is this here?!
- # When we load a .curaprofile file the deserialize will trigger a version upgrade, creating a dangling file.
- # This file can be recognized by it's lack of a machine name in the target filename.
- # So when we detect that situation here, we don't create the file and return.
- if machine_name == "":
- return
-
- new_filename = machine_name + "_" + "fdmextruder" + suffix
-
- extruder_quality_changes_parser = configparser.ConfigParser(interpolation = None)
- extruder_quality_changes_parser.add_section("general")
- extruder_quality_changes_parser["general"]["version"] = str(2)
- extruder_quality_changes_parser["general"]["name"] = global_quality_changes["general"]["name"]
- extruder_quality_changes_parser["general"]["definition"] = global_quality_changes["general"]["definition"]
-
- extruder_quality_changes_parser.add_section("metadata")
- extruder_quality_changes_parser["metadata"]["quality_type"] = global_quality_changes["metadata"]["quality_type"]
- extruder_quality_changes_parser["metadata"]["type"] = global_quality_changes["metadata"]["type"]
- extruder_quality_changes_parser["metadata"]["setting_version"] = str(4)
- extruder_quality_changes_parser["metadata"]["extruder"] = "fdmextruder"
-
- extruder_quality_changes_output = io.StringIO()
- extruder_quality_changes_parser.write(extruder_quality_changes_output)
- extruder_quality_changes_filename = quote_plus(new_filename) + ".inst.cfg"
-
- quality_changes_dir = Resources.getPath(CuraApplication.ResourceTypes.QualityInstanceContainer)
-
- with open(os.path.join(quality_changes_dir, extruder_quality_changes_filename), "w") as f:
- f.write(extruder_quality_changes_output.getvalue())
diff --git a/plugins/VersionUpgrade/VersionUpgrade30to31/__init__.py b/plugins/VersionUpgrade/VersionUpgrade30to31/__init__.py
index b4b75dddf7..c853e2b93b 100644
--- a/plugins/VersionUpgrade/VersionUpgrade30to31/__init__.py
+++ b/plugins/VersionUpgrade/VersionUpgrade30to31/__init__.py
@@ -33,6 +33,10 @@ def getMetaData():
"get_version": upgrade.getCfgVersion,
"location": {"./extruders"}
},
+ "quality": {
+ "get_version": upgrade.getCfgVersion,
+ "location": {"./quality"}
+ },
"quality_changes": {
"get_version": upgrade.getCfgVersion,
"location": {"./quality"}
diff --git a/plugins/VersionUpgrade/VersionUpgrade32to33/VersionUpgrade32to33.py b/plugins/VersionUpgrade/VersionUpgrade32to33/VersionUpgrade32to33.py
new file mode 100644
index 0000000000..620f367e25
--- /dev/null
+++ b/plugins/VersionUpgrade/VersionUpgrade32to33/VersionUpgrade32to33.py
@@ -0,0 +1,135 @@
+# 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 UM.VersionUpgrade import VersionUpgrade #We're inheriting from this.
+
+## Mapping extruder definition IDs to the positions that they are in.
+_EXTRUDER_TO_POSITION = {
+ "builder_premium_large_front": 1,
+ "builder_premium_large_rear": 0,
+ "builder_premium_medium_front": 1,
+ "builder_premium_medium_rear": 0,
+ "builder_premium_small_front": 1,
+ "builder_premium_small_rear": 0,
+ "cartesio_extruder_0": 0,
+ "cartesio_extruder_1": 1,
+ "cartesio_extruder_2": 2,
+ "cartesio_extruder_3": 3,
+ "custom_extruder_1": 0, #Warning, non-programmers are attempting to count here.
+ "custom_extruder_2": 1,
+ "custom_extruder_3": 2,
+ "custom_extruder_4": 3,
+ "custom_extruder_5": 4,
+ "custom_extruder_6": 5,
+ "custom_extruder_7": 6,
+ "custom_extruder_8": 7,
+ "hBp_extruder_left": 0,
+ "hBp_extruder_right": 1,
+ "makeit_dual_1st": 0,
+ "makeit_dual_2nd": 1,
+ "makeit_l_dual_1st": 0,
+ "makeit_l_dual_2nd": 1,
+ "ord_extruder_0": 0,
+ "ord_extruder_1": 1,
+ "ord_extruder_2": 2,
+ "ord_extruder_3": 3,
+ "ord_extruder_4": 4,
+ "punchtec_connect_xl_extruder_left": 0,
+ "punchtec_connect_xl_extruder_right": 1,
+ "raise3D_N2_dual_extruder_0": 0,
+ "raise3D_N2_dual_extruder_1": 1,
+ "raise3D_N2_plus_dual_extruder_0": 0,
+ "raise3D_N2_plus_dual_extruder_1": 1,
+ "ultimaker3_extended_extruder_left": 0,
+ "ultimaker3_extended_extruder_right": 1,
+ "ultimaker3_extruder_left": 0,
+ "ultimaker3_extruder_right": 1,
+ "ultimaker_original_dual_1st": 0,
+ "ultimaker_original_dual_2nd": 1,
+ "vertex_k8400_dual_1st": 0,
+ "vertex_k8400_dual_2nd": 1
+}
+
+## 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
+ # 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):
+ 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 a container stack from version 3.2 to 3.3.
+ #
+ # \param serialised The serialised form of a container stack.
+ # \param filename The name of the file to upgrade.
+ def upgradeStack(self, serialized, filename):
+ parser = configparser.ConfigParser(interpolation = None)
+ parser.read_string(serialized)
+
+ if "metadata" in parser and "um_network_key" in parser["metadata"]:
+ if "hidden" not in parser["metadata"]:
+ parser["metadata"]["hidden"] = "False"
+ if "connect_group_name" not in parser["metadata"]:
+ parser["metadata"]["connect_group_name"] = "Temporary group name #" + str(self.temporary_group_name_counter)
+ self.temporary_group_name_counter += 1
+
+ #Update version number.
+ parser["general"]["version"] = "4"
+
+ result = io.StringIO()
+ parser.write(result)
+ return [filename], [result.getvalue()]
+
+ ## Upgrades non-quality-changes instance containers to have the new version
+ # number.
+ def upgradeInstanceContainer(self, serialized, filename):
+ parser = configparser.ConfigParser(interpolation = None)
+ parser.read_string(serialized)
+
+ #Update version number.
+ parser["general"]["version"] = "3"
+
+ result = io.StringIO()
+ parser.write(result)
+ return [filename], [result.getvalue()]
+
+ ## Upgrades a quality changes container to the new format.
+ def upgradeQualityChanges(self, serialized, filename):
+ parser = configparser.ConfigParser(interpolation = None)
+ parser.read_string(serialized)
+
+ #Extruder quality changes profiles have the extruder position instead of the ID of the extruder definition.
+ if "metadata" in parser and "extruder" in parser["metadata"]: #Only do this for extruder profiles.
+ extruder_id = parser["metadata"]["extruder"]
+ if extruder_id in _EXTRUDER_TO_POSITION:
+ extruder_position = _EXTRUDER_TO_POSITION[extruder_id]
+ else:
+ extruder_position = 0 #The user was using custom extruder definitions. He's on his own then.
+
+ parser["metadata"]["position"] = str(extruder_position)
+ del parser["metadata"]["extruder"]
+
+ #Update version number.
+ parser["general"]["version"] = "3"
+
+ result = io.StringIO()
+ parser.write(result)
+ return [filename], [result.getvalue()]
\ No newline at end of file
diff --git a/plugins/VersionUpgrade/VersionUpgrade32to33/__init__.py b/plugins/VersionUpgrade/VersionUpgrade32to33/__init__.py
new file mode 100644
index 0000000000..72ff6e1de9
--- /dev/null
+++ b/plugins/VersionUpgrade/VersionUpgrade32to33/__init__.py
@@ -0,0 +1,44 @@
+# Copyright (c) 2018 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+
+from . import VersionUpgrade32to33
+
+upgrade = VersionUpgrade32to33.VersionUpgrade32to33()
+
+def getMetaData():
+ return {
+ "version_upgrade": {
+ # From To Upgrade function
+ ("machine_stack", 3000004): ("machine_stack", 4000004, upgrade.upgradeStack),
+ ("extruder_train", 3000004): ("extruder_train", 4000004, upgrade.upgradeStack),
+
+ ("definition_changes", 2000004): ("definition_changes", 3000004, upgrade.upgradeInstanceContainer),
+ ("quality_changes", 2000004): ("quality_changes", 3000004, upgrade.upgradeQualityChanges),
+ ("user", 2000004): ("user", 3000004, upgrade.upgradeInstanceContainer)
+ },
+ "sources": {
+ "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"}
+ },
+ "user": {
+ "get_version": upgrade.getCfgVersion,
+ "location": {"./user"}
+ }
+ }
+ }
+
+def register(app):
+ return { "version_upgrade": upgrade }
\ No newline at end of file
diff --git a/plugins/VersionUpgrade/VersionUpgrade32to33/plugin.json b/plugins/VersionUpgrade/VersionUpgrade32to33/plugin.json
new file mode 100644
index 0000000000..fbce09c807
--- /dev/null
+++ b/plugins/VersionUpgrade/VersionUpgrade32to33/plugin.json
@@ -0,0 +1,8 @@
+ {
+ "name": "Version Upgrade 3.2 to 3.3",
+ "author": "Ultimaker B.V.",
+ "version": "1.0.0",
+ "description": "Upgrades configurations from Cura 3.2 to Cura 3.3.",
+ "api": 4,
+ "i18n-catalog": "cura"
+}
diff --git a/plugins/XRayView/XRayPass.py b/plugins/XRayView/XRayPass.py
index 38c88a256e..a75d393b35 100644
--- a/plugins/XRayView/XRayPass.py
+++ b/plugins/XRayView/XRayPass.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2015 Ultimaker B.V.
+# Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
import os.path
@@ -10,7 +10,7 @@ from UM.View.RenderPass import RenderPass
from UM.View.RenderBatch import RenderBatch
from UM.View.GL.OpenGL import OpenGL
-from UM.Scene.SceneNode import SceneNode
+from cura.Scene.CuraSceneNode import CuraSceneNode
from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator
class XRayPass(RenderPass):
@@ -27,7 +27,7 @@ class XRayPass(RenderPass):
batch = RenderBatch(self._shader, type = RenderBatch.RenderType.NoType, backface_cull = False, blend_mode = RenderBatch.BlendMode.Additive)
for node in DepthFirstIterator(self._scene.getRoot()):
- if type(node) is SceneNode and node.getMeshData() and node.isVisible():
+ if isinstance(node, CuraSceneNode) and node.getMeshData() and node.isVisible():
batch.addItem(node.getWorldTransformation(), node.getMeshData())
self.bind()
diff --git a/plugins/XRayView/xray_composite.shader b/plugins/XRayView/xray_composite.shader
index 82dca52cf9..0a8f6364d7 100644
--- a/plugins/XRayView/xray_composite.shader
+++ b/plugins/XRayView/xray_composite.shader
@@ -13,9 +13,9 @@ vertex =
}
fragment =
- uniform sampler2D u_layer0;
- uniform sampler2D u_layer1;
- uniform sampler2D u_layer2;
+ uniform sampler2D u_layer0; //Default pass.
+ uniform sampler2D u_layer1; //Selection pass.
+ uniform sampler2D u_layer2; //X-ray pass.
uniform vec2 u_offset[9];
@@ -83,9 +83,9 @@ vertex41core =
fragment41core =
#version 410
- uniform sampler2D u_layer0;
- uniform sampler2D u_layer1;
- uniform sampler2D u_layer2;
+ uniform sampler2D u_layer0; //Default pass.
+ uniform sampler2D u_layer1; //Selection pass.
+ uniform sampler2D u_layer2; //X-ray pass.
uniform vec2 u_offset[9];
diff --git a/plugins/XmlMaterialProfile/XmlMaterialProfile.py b/plugins/XmlMaterialProfile/XmlMaterialProfile.py
index 8767377db0..8b17721794 100644
--- a/plugins/XmlMaterialProfile/XmlMaterialProfile.py
+++ b/plugins/XmlMaterialProfile/XmlMaterialProfile.py
@@ -17,6 +17,8 @@ import UM.Dictionary
from UM.Settings.InstanceContainer import InstanceContainer
from UM.Settings.ContainerRegistry import ContainerRegistry
+from .XmlMaterialValidator import XmlMaterialValidator
+
## Handles serializing and deserializing material containers from an XML file
class XmlMaterialProfile(InstanceContainer):
CurrentFdmMaterialVersion = "1.3"
@@ -46,18 +48,35 @@ class XmlMaterialProfile(InstanceContainer):
## Overridden from InstanceContainer
# set the meta data for all machine / variant combinations
- def setMetaDataEntry(self, key, value):
+ #
+ # The "apply_to_all" flag indicates whether this piece of metadata should be applied to all material containers
+ # or just this specific container.
+ # For example, when you change the material name, you want to apply it to all its derived containers, but for
+ # some specific settings, they should only be applied to a machine/variant-specific container.
+ #
+ def setMetaDataEntry(self, key, value, apply_to_all = True):
registry = ContainerRegistry.getInstance()
if registry.isReadOnly(self.getId()):
return
- super().setMetaDataEntry(key, value)
+ # Prevent recursion
+ if not apply_to_all:
+ super().setMetaDataEntry(key, value)
+ return
- basefile = self.getMetaDataEntry("base_file", self.getId()) #if basefile is self.getId, this is a basefile.
- # Update all containers that share basefile
- for container in registry.findInstanceContainers(base_file = basefile):
- if container.getMetaDataEntry(key, None) != value: # Prevent recursion
- container.setMetaDataEntry(key, value)
+ # 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)
+
+ # Update the root material container
+ root_material_container = material_group.root_material_node.getContainer()
+ root_material_container.setMetaDataEntry(key, value, apply_to_all = False)
+
+ # Update all containers derived from it
+ for node in material_group.derived_material_node_list:
+ container = node.getContainer()
+ container.setMetaDataEntry(key, value, apply_to_all = False)
## Overridden from InstanceContainer, similar to setMetaDataEntry.
# without this function the setName would only set the name of the specific nozzle / material / machine combination container
@@ -181,28 +200,39 @@ class XmlMaterialProfile(InstanceContainer):
## Begin Settings Block
builder.start("settings")
- if self.getDefinition().getId() == "fdmprinter":
+ if self.getMetaDataEntry("definition") == "fdmprinter":
for instance in self.findInstances():
self._addSettingElement(builder, instance)
machine_container_map = {}
- machine_nozzle_map = {}
+ machine_variant_map = {}
+
+ variant_manager = CuraApplication.getInstance().getVariantManager()
+ 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)
+
+ all_containers = []
+ for node in [material_group.root_material_node] + material_group.derived_material_node_list:
+ all_containers.append(node.getContainer())
- all_containers = registry.findInstanceContainers(GUID = self.getMetaDataEntry("GUID"), base_file = self.getId())
for container in all_containers:
- definition_id = container.getDefinition().getId()
+ definition_id = container.getMetaDataEntry("definition")
if definition_id == "fdmprinter":
continue
if definition_id not in machine_container_map:
machine_container_map[definition_id] = container
- if definition_id not in machine_nozzle_map:
- machine_nozzle_map[definition_id] = {}
+ if definition_id not in machine_variant_map:
+ machine_variant_map[definition_id] = {}
- variant = container.getMetaDataEntry("variant")
- if variant:
- machine_nozzle_map[definition_id][variant] = container
+ variant_name = container.getMetaDataEntry("variant_name")
+ if variant_name:
+ variant_dict = {"variant_node": variant_manager.getVariantNode(definition_id, variant_name),
+ "material_container": container}
+ machine_variant_map[definition_id][variant_name] = variant_dict
continue
machine_container_map[definition_id] = container
@@ -211,7 +241,8 @@ class XmlMaterialProfile(InstanceContainer):
product_id_map = self.getProductIdMap()
for definition_id, container in machine_container_map.items():
- definition = container.getDefinition()
+ definition_id = container.getMetaDataEntry("definition")
+ definition_metadata = ContainerRegistry.getInstance().findDefinitionContainersMetadata(id = definition_id)[0]
product = definition_id
for product_name, product_id_list in product_id_map.items():
@@ -221,45 +252,74 @@ class XmlMaterialProfile(InstanceContainer):
builder.start("machine")
builder.start("machine_identifier", {
- "manufacturer": container.getMetaDataEntry("machine_manufacturer", definition.getMetaDataEntry("manufacturer", "Unknown")),
+ "manufacturer": container.getMetaDataEntry("machine_manufacturer",
+ definition_metadata.get("manufacturer", "Unknown")),
"product": product
})
builder.end("machine_identifier")
for instance in container.findInstances():
- if self.getDefinition().getId() == "fdmprinter" and self.getInstance(instance.definition.key) and self.getProperty(instance.definition.key, "value") == instance.value:
+ if self.getMetaDataEntry("definition") == "fdmprinter" and self.getInstance(instance.definition.key) and self.getProperty(instance.definition.key, "value") == instance.value:
# If the settings match that of the base profile, just skip since we inherit the base profile.
continue
self._addSettingElement(builder, instance)
# Find all hotend sub-profiles corresponding to this material and machine and add them to this profile.
- for hotend_id, hotend in machine_nozzle_map[definition_id].items():
- variant_containers = registry.findInstanceContainersMetadata(id = hotend.getMetaDataEntry("variant"))
- if not variant_containers:
- continue
+ buildplate_dict = {}
+ for variant_name, variant_dict in machine_variant_map[definition_id].items():
+ variant_type = variant_dict["variant_node"].metadata["hardware_type"]
+ from cura.Machines.VariantManager import VariantType
+ variant_type = VariantType(variant_type)
+ if variant_type == VariantType.NOZZLE:
+ # The hotend identifier is not the containers name, but its "name".
+ builder.start("hotend", {"id": variant_name})
- # The hotend identifier is not the containers name, but its "name".
- builder.start("hotend", {"id": variant_containers[0]["name"]})
+ # Compatible is a special case, as it's added as a meta data entry (instead of an instance).
+ material_container = variant_dict["material_container"]
+ compatible = material_container.getMetaDataEntry("compatible")
+ if compatible is not None:
+ builder.start("setting", {"key": "hardware compatible"})
+ if compatible:
+ builder.data("yes")
+ else:
+ builder.data("no")
+ builder.end("setting")
- # Compatible is a special case, as it's added as a meta data entry (instead of an instance).
- compatible = hotend.getMetaDataEntry("compatible")
- if compatible is not None:
- builder.start("setting", {"key": "hardware compatible"})
- if compatible:
- builder.data("yes")
- else:
- builder.data("no")
- builder.end("setting")
+ for instance in material_container.findInstances():
+ if container.getInstance(instance.definition.key) and container.getProperty(instance.definition.key, "value") == instance.value:
+ # If the settings match that of the machine profile, just skip since we inherit the machine profile.
+ continue
- for instance in hotend.findInstances():
- if container.getInstance(instance.definition.key) and container.getProperty(instance.definition.key, "value") == instance.value:
- # If the settings match that of the machine profile, just skip since we inherit the machine profile.
- continue
+ self._addSettingElement(builder, instance)
- self._addSettingElement(builder, instance)
+ if material_container.getMetaDataEntry("buildplate_compatible") and not buildplate_dict:
+ buildplate_dict["buildplate_compatible"] = material_container.getMetaDataEntry("buildplate_compatible")
+ buildplate_dict["buildplate_recommended"] = material_container.getMetaDataEntry("buildplate_recommended")
+ buildplate_dict["material_container"] = material_container
- builder.end("hotend")
+ builder.end("hotend")
+
+ if buildplate_dict:
+ for variant_name in buildplate_dict["buildplate_compatible"]:
+ builder.start("buildplate", {"id": variant_name})
+
+ material_container = buildplate_dict["material_container"]
+ buildplate_compatible_dict = material_container.getMetaDataEntry("buildplate_compatible")
+ buildplate_recommended_dict = material_container.getMetaDataEntry("buildplate_recommended")
+ if buildplate_compatible_dict:
+ compatible = buildplate_compatible_dict[variant_name]
+ recommended = buildplate_recommended_dict[variant_name]
+
+ builder.start("setting", {"key": "hardware compatible"})
+ builder.data("yes" if compatible else "no")
+ builder.end("setting")
+
+ builder.start("setting", {"key": "hardware recommended"})
+ builder.data("yes" if recommended else "no")
+ builder.end("setting")
+
+ builder.end("buildplate")
builder.end("machine")
@@ -480,6 +540,10 @@ class XmlMaterialProfile(InstanceContainer):
if "adhesion_info" not in meta_data:
meta_data["adhesion_info"] = ""
+ validation_message = XmlMaterialValidator.validateMaterialMetaData(meta_data)
+ if validation_message is not None:
+ raise Exception("Not valid material profile: %s" % (validation_message))
+
property_values = {}
properties = data.iterfind("./um:properties/*", self.__namespaces)
for entry in properties:
@@ -538,10 +602,8 @@ class XmlMaterialProfile(InstanceContainer):
for machine_id in machine_id_list:
definitions = ContainerRegistry.getInstance().findDefinitionContainersMetadata(id = machine_id)
if not definitions:
- Logger.log("w", "No definition found for machine ID %s", machine_id)
continue
- Logger.log("d", "Found definition for machine ID %s", machine_id)
definition = definitions[0]
machine_manufacturer = identifier.get("manufacturer", definition.get("manufacturer", "Unknown")) #If the XML material doesn't specify a manufacturer, use the one in the actual printer definition.
@@ -586,14 +648,11 @@ class XmlMaterialProfile(InstanceContainer):
if buildplate_id is None:
continue
- variant_containers = ContainerRegistry.getInstance().findInstanceContainersMetadata(
- id = buildplate_id)
- if not variant_containers:
- # It is not really properly defined what "ID" is so also search for variants by name.
- variant_containers = ContainerRegistry.getInstance().findInstanceContainersMetadata(
- definition = machine_id, name = buildplate_id)
-
- if not variant_containers:
+ from cura.Machines.VariantManager import VariantType
+ variant_manager = CuraApplication.getInstance().getVariantManager()
+ variant_node = variant_manager.getVariantNode(machine_id, buildplate_id,
+ variant_type = VariantType.BUILD_PLATE)
+ if not variant_node:
continue
buildplate_compatibility = machine_compatibility
@@ -614,16 +673,14 @@ class XmlMaterialProfile(InstanceContainer):
hotends = machine.iterfind("./um:hotend", self.__namespaces)
for hotend in hotends:
- hotend_id = hotend.get("id")
- if hotend_id is None:
+ # The "id" field for hotends in material profiles are actually
+ hotend_name = hotend.get("id")
+ if hotend_name is None:
continue
- variant_containers = ContainerRegistry.getInstance().findInstanceContainersMetadata(id = hotend_id)
- if not variant_containers:
- # It is not really properly defined what "ID" is so also search for variants by name.
- variant_containers = ContainerRegistry.getInstance().findInstanceContainersMetadata(definition = machine_id, name = hotend_id)
-
- if not variant_containers:
+ variant_manager = CuraApplication.getInstance().getVariantManager()
+ variant_node = variant_manager.getVariantNode(machine_id, hotend_name)
+ if not variant_node:
continue
hotend_compatibility = machine_compatibility
@@ -639,20 +696,20 @@ class XmlMaterialProfile(InstanceContainer):
else:
Logger.log("d", "Unsupported material setting %s", key)
- new_hotend_id = self.getId() + "_" + machine_id + "_" + hotend_id.replace(" ", "_")
+ new_hotend_specific_material_id = self.getId() + "_" + machine_id + "_" + hotend_name.replace(" ", "_")
# Same as machine compatibility, keep the derived material containers consistent with the parent material
- if ContainerRegistry.getInstance().isLoaded(new_hotend_id):
- new_hotend_material = ContainerRegistry.getInstance().findContainers(id = new_hotend_id)[0]
+ if ContainerRegistry.getInstance().isLoaded(new_hotend_specific_material_id):
+ new_hotend_material = ContainerRegistry.getInstance().findContainers(id = new_hotend_specific_material_id)[0]
is_new_material = False
else:
- new_hotend_material = XmlMaterialProfile(new_hotend_id)
+ new_hotend_material = XmlMaterialProfile(new_hotend_specific_material_id)
is_new_material = True
new_hotend_material.setMetaData(copy.deepcopy(self.getMetaData()))
- new_hotend_material.getMetaData()["id"] = new_hotend_id
+ new_hotend_material.getMetaData()["id"] = new_hotend_specific_material_id
new_hotend_material.getMetaData()["name"] = self.getName()
- new_hotend_material.getMetaData()["variant"] = variant_containers[0]["id"]
+ new_hotend_material.getMetaData()["variant_name"] = hotend_name
new_hotend_material.setDefinition(machine_id)
# Don't use setMetadata, as that overrides it for all materials with same base file
new_hotend_material.getMetaData()["compatible"] = hotend_compatibility
@@ -772,7 +829,6 @@ class XmlMaterialProfile(InstanceContainer):
for machine_id in machine_id_list:
definition_metadata = ContainerRegistry.getInstance().findDefinitionContainersMetadata(id = machine_id)
if not definition_metadata:
- Logger.log("w", "No definition found for machine ID %s", machine_id)
continue
definition_metadata = definition_metadata[0]
@@ -782,15 +838,11 @@ class XmlMaterialProfile(InstanceContainer):
if machine_compatibility:
new_material_id = container_id + "_" + machine_id
- # The child or derived material container may already exist. This can happen when a material in a
- # project file and the a material in Cura have the same ID.
- # In the case if a derived material already exists, override that material container because if
- # the data in the parent material has been changed, the derived ones should be updated too.
- found_materials = ContainerRegistry.getInstance().findInstanceContainersMetadata(id = new_material_id)
- if found_materials:
- new_material_metadata = found_materials[0]
- else:
- new_material_metadata = {}
+ # Do not look for existing container/container metadata with the same ID although they may exist.
+ # In project loading and perhaps some other places, we only want to get information (metadata)
+ # from a file without changing the current state of the system. If we overwrite the existing
+ # metadata here, deserializeMetadata() will not be safe for retrieving information.
+ new_material_metadata = {}
new_material_metadata.update(base_metadata)
new_material_metadata["id"] = new_material_id
@@ -798,8 +850,7 @@ class XmlMaterialProfile(InstanceContainer):
new_material_metadata["machine_manufacturer"] = machine_manufacturer
new_material_metadata["definition"] = machine_id
- if len(found_materials) == 0: #This is a new material.
- result_metadata.append(new_material_metadata)
+ result_metadata.append(new_material_metadata)
buildplates = machine.iterfind("./um:buildplate", cls.__namespaces)
buildplate_map = {}
@@ -810,15 +861,17 @@ class XmlMaterialProfile(InstanceContainer):
if buildplate_id is None:
continue
- variant_containers = ContainerRegistry.getInstance().findInstanceContainersMetadata(id = buildplate_id)
- if not variant_containers:
+ variant_metadata = ContainerRegistry.getInstance().findInstanceContainersMetadata(id = buildplate_id)
+ if not variant_metadata:
# It is not really properly defined what "ID" is so also search for variants by name.
- variant_containers = ContainerRegistry.getInstance().findInstanceContainersMetadata(definition = machine_id, name = buildplate_id)
+ variant_metadata = ContainerRegistry.getInstance().findInstanceContainersMetadata(definition = machine_id, name = buildplate_id)
- if not variant_containers:
+ if not variant_metadata:
continue
settings = buildplate.iterfind("./um:setting", cls.__namespaces)
+ buildplate_compatibility = True
+ buildplate_recommended = True
for entry in settings:
key = entry.get("key")
if key == "hardware compatible":
@@ -826,50 +879,36 @@ class XmlMaterialProfile(InstanceContainer):
elif key == "hardware recommended":
buildplate_recommended = cls._parseCompatibleValue(entry.text)
- buildplate_map["buildplate_compatible"][buildplate_id] = buildplate_map["buildplate_compatible"]
- buildplate_map["buildplate_recommended"][buildplate_id] = buildplate_map["buildplate_recommended"]
+ buildplate_map["buildplate_compatible"][buildplate_id] = buildplate_compatibility
+ buildplate_map["buildplate_recommended"][buildplate_id] = buildplate_recommended
for hotend in machine.iterfind("./um:hotend", cls.__namespaces):
- hotend_id = hotend.get("id")
- if hotend_id is None:
+ hotend_name = hotend.get("id")
+ if hotend_name is None:
continue
- variant_containers = ContainerRegistry.getInstance().findInstanceContainersMetadata(id = hotend_id)
- if not variant_containers:
- # It is not really properly defined what "ID" is so also search for variants by name.
- variant_containers = ContainerRegistry.getInstance().findInstanceContainersMetadata(definition = machine_id, name = hotend_id)
-
hotend_compatibility = machine_compatibility
for entry in hotend.iterfind("./um:setting", cls.__namespaces):
key = entry.get("key")
if key == "hardware compatible":
hotend_compatibility = cls._parseCompatibleValue(entry.text)
- new_hotend_id = container_id + "_" + machine_id + "_" + hotend_id.replace(" ", "_")
+ new_hotend_specific_material_id = container_id + "_" + machine_id + "_" + hotend_name.replace(" ", "_")
- # Same as machine compatibility, keep the derived material containers consistent with the parent material
- found_materials = ContainerRegistry.getInstance().findInstanceContainersMetadata(id = new_hotend_id)
- if found_materials:
- new_hotend_material_metadata = found_materials[0]
- else:
- new_hotend_material_metadata = {}
+ # Same as above, do not overwrite existing metadata.
+ new_hotend_material_metadata = {}
new_hotend_material_metadata.update(base_metadata)
- if variant_containers:
- new_hotend_material_metadata["variant"] = variant_containers[0]["id"]
- else:
- new_hotend_material_metadata["variant"] = hotend_id
- _with_missing_variants.append(new_hotend_material_metadata)
+ new_hotend_material_metadata["variant_name"] = hotend_name
new_hotend_material_metadata["compatible"] = hotend_compatibility
new_hotend_material_metadata["machine_manufacturer"] = machine_manufacturer
- new_hotend_material_metadata["id"] = new_hotend_id
+ new_hotend_material_metadata["id"] = new_hotend_specific_material_id
new_hotend_material_metadata["definition"] = machine_id
if buildplate_map["buildplate_compatible"]:
new_hotend_material_metadata["buildplate_compatible"] = buildplate_map["buildplate_compatible"]
new_hotend_material_metadata["buildplate_recommended"] = buildplate_map["buildplate_recommended"]
- if len(found_materials) == 0:
- result_metadata.append(new_hotend_material_metadata)
+ result_metadata.append(new_hotend_material_metadata)
# there is only one ID for a machine. Once we have reached here, it means we have already found
# a workable ID for that machine, so there is no need to continue
@@ -911,11 +950,11 @@ class XmlMaterialProfile(InstanceContainer):
else:
merged_name_parts.append(part)
- id_list = [name.lower().replace(" ", ""), # simply removing all spaces
+ id_list = {name.lower().replace(" ", ""), # simply removing all spaces
name.lower().replace(" ", "_"), # simply replacing all spaces with underscores
"_".join(merged_name_parts),
- ]
-
+ }
+ id_list = list(id_list)
return id_list
## Gets a mapping from product names in the XML files to their definition
@@ -989,21 +1028,3 @@ def _indent(elem, level = 0):
# before the last }
def _tag_without_namespace(element):
return element.tag[element.tag.rfind("}") + 1:]
-
-#While loading XML profiles, some of these profiles don't know what variant
-#they belong to. We'd like to search by the machine ID and the variant's
-#name, but we don't know the variant's ID. Not all variants have been loaded
-#yet so we can't run a filter on the name and machine. The ID is unknown
-#so we can't lazily load the variant either. So we have to wait until all
-#the rest is loaded properly and then assign the correct variant to the
-#material files that were missing it.
-_with_missing_variants = []
-def _fillMissingVariants():
- registry = ContainerRegistry.getInstance()
- for variant_metadata in _with_missing_variants:
- variants = registry.findContainersMetadata(definition = variant_metadata["definition"], name = variant_metadata["variant"])
- if not variants:
- Logger.log("w", "Could not find variant for variant-specific material {material_id}.".format(material_id = variant_metadata["id"]))
- continue
- variant_metadata["variant"] = variants[0]["id"]
-ContainerRegistry.allMetadataLoaded.connect(_fillMissingVariants)
diff --git a/plugins/XmlMaterialProfile/XmlMaterialValidator.py b/plugins/XmlMaterialProfile/XmlMaterialValidator.py
new file mode 100644
index 0000000000..f11c8bea4b
--- /dev/null
+++ b/plugins/XmlMaterialProfile/XmlMaterialValidator.py
@@ -0,0 +1,25 @@
+# Copyright (c) 2017 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
+
+
+
+class XmlMaterialValidator():
+
+ @classmethod
+ def validateMaterialMetaData(cls, validation_metadata):
+
+ if validation_metadata.get("GUID") is None:
+ return "Missing GUID"
+
+ if validation_metadata.get("brand") is None:
+ return "Missing Brand"
+
+ if validation_metadata.get("material") is None:
+ return "Missing Material"
+
+ if validation_metadata.get("version") is None:
+ return "Missing Version"
+
+ return None
+
+
diff --git a/resources/definitions/anycubic_i3_mega.def.json b/resources/definitions/anycubic_i3_mega.def.json
index cba868900c..7106038193 100644
--- a/resources/definitions/anycubic_i3_mega.def.json
+++ b/resources/definitions/anycubic_i3_mega.def.json
@@ -12,7 +12,7 @@
"platform": "anycubic_i3_mega_platform.stl",
"has_materials": false,
"has_machine_quality": true,
- "preferred_quality": "*normal*"
+ "preferred_quality_type": "normal"
},
"overrides":
diff --git a/resources/definitions/builder_premium_large.def.json b/resources/definitions/builder_premium_large.def.json
index b496dc524e..deb1539a9a 100644
--- a/resources/definitions/builder_premium_large.def.json
+++ b/resources/definitions/builder_premium_large.def.json
@@ -12,16 +12,14 @@
"platform": "builder_premium_platform.stl",
"platform_offset": [-126, -36, 117],
"has_machine_quality": true,
- "preferred_quality": "*Normal*",
+ "preferred_quality_type": "normal",
"machine_extruder_trains":
{
"0": "builder_premium_large_rear",
"1": "builder_premium_large_front"
}
},
-
-
-
+
"overrides": {
"machine_name": { "default_value": "Builder Premium Large" },
"machine_heated_bed": { "default_value": true },
@@ -36,7 +34,7 @@
"default_material_print_temperature": { "value": "215" },
"material_print_temperature_layer_0": { "value": "material_print_temperature + 5" },
"material_standby_temperature": { "value": "material_print_temperature" },
-
+
"switch_extruder_retraction_speeds": {"default_value": 15 },
"switch_extruder_retraction_speed": {"default_value": 15 },
"switch_extruder_prime_speed": {"default_value": 15 },
@@ -58,9 +56,9 @@
"prime_tower_wipe_enabled": { "default_value": false },
"prime_tower_min_volume": { "default_value": 50 },
"dual_pre_wipe": { "default_value": false },
-
+
"prime_blob_enable": { "enabled": true },
-
+
"acceleration_enabled": { "value": "True" },
"acceleration_layer_0": { "value": "acceleration_topbottom" },
"acceleration_prime_tower": { "value": "math.ceil(acceleration_print * 2000 / 4000)" },
@@ -71,7 +69,7 @@
"acceleration_travel": { "value": "acceleration_print" },
"acceleration_wall": { "value": "math.ceil(acceleration_print * 1000 / 3000)" },
"acceleration_wall_0": { "value": "math.ceil(acceleration_wall * 1000 / 1000)" },
-
+
"cool_fan_full_at_height": { "value": "layer_height_0 + 2 * layer_height" },
"cool_min_layer_time": { "default_value": 10 },
@@ -84,9 +82,9 @@
"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)" },
-
+
"wall_thickness": { "value": "1.2" },
-
+
"retraction_amount": { "default_value": 3 },
"retraction_speed": { "default_value": 15 },
"retraction_retract_speed": { "default_value": 15 },
@@ -113,4 +111,4 @@
},
"machine_extruder_count": { "default_value": 2 }
}
-}
\ No newline at end of file
+}
diff --git a/resources/definitions/builder_premium_medium.def.json b/resources/definitions/builder_premium_medium.def.json
index fe8a039fc4..c28c7c5de6 100644
--- a/resources/definitions/builder_premium_medium.def.json
+++ b/resources/definitions/builder_premium_medium.def.json
@@ -12,16 +12,14 @@
"platform": "builder_premium_platform.stl",
"platform_offset": [-126, -36, 117],
"has_machine_quality": true,
- "preferred_quality": "*Normal*",
+ "preferred_quality_type": "normal",
"machine_extruder_trains":
{
"0": "builder_premium_medium_rear",
"1": "builder_premium_medium_front"
}
},
-
-
-
+
"overrides": {
"machine_name": { "default_value": "Builder Premium Medium" },
"machine_heated_bed": { "default_value": true },
@@ -36,7 +34,7 @@
"default_material_print_temperature": { "value": "215" },
"material_print_temperature_layer_0": { "value": "material_print_temperature + 5" },
"material_standby_temperature": { "value": "material_print_temperature" },
-
+
"switch_extruder_retraction_speeds": {"default_value": 15 },
"switch_extruder_retraction_speed": {"default_value": 15 },
"switch_extruder_prime_speed": {"default_value": 15 },
@@ -58,9 +56,9 @@
"prime_tower_wipe_enabled": { "default_value": false },
"prime_tower_min_volume": { "default_value": 50 },
"dual_pre_wipe": { "default_value": false },
-
+
"prime_blob_enable": { "enabled": true },
-
+
"acceleration_enabled": { "value": "True" },
"acceleration_layer_0": { "value": "acceleration_topbottom" },
"acceleration_prime_tower": { "value": "math.ceil(acceleration_print * 2000 / 4000)" },
@@ -71,7 +69,7 @@
"acceleration_travel": { "value": "acceleration_print" },
"acceleration_wall": { "value": "math.ceil(acceleration_print * 1000 / 3000)" },
"acceleration_wall_0": { "value": "math.ceil(acceleration_wall * 1000 / 1000)" },
-
+
"cool_fan_full_at_height": { "value": "layer_height_0 + 2 * layer_height" },
"cool_min_layer_time": { "default_value": 10 },
@@ -84,9 +82,9 @@
"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)" },
-
+
"wall_thickness": { "value": "1.2" },
-
+
"retraction_amount": { "default_value": 3 },
"retraction_speed": { "default_value": 15 },
"retraction_retract_speed": { "default_value": 15 },
@@ -113,4 +111,4 @@
},
"machine_extruder_count": { "default_value": 2 }
}
-}
\ No newline at end of file
+}
diff --git a/resources/definitions/builder_premium_small.def.json b/resources/definitions/builder_premium_small.def.json
index a1660b63cf..8e2fe44631 100644
--- a/resources/definitions/builder_premium_small.def.json
+++ b/resources/definitions/builder_premium_small.def.json
@@ -11,16 +11,14 @@
"platform": "builder_premium_platform.stl",
"platform_offset": [-126, -36, 117],
"has_machine_quality": true,
- "preferred_quality": "*Normal*",
+ "preferred_quality_type": "normal",
"machine_extruder_trains":
{
"0": "builder_premium_small_rear",
"1": "builder_premium_small_front"
}
},
-
-
-
+
"overrides": {
"machine_name": { "default_value": "Builder Premium Small" },
"machine_heated_bed": { "default_value": true },
@@ -35,7 +33,7 @@
"default_material_print_temperature": { "value": "215" },
"material_print_temperature_layer_0": { "value": "material_print_temperature + 5" },
"material_standby_temperature": { "value": "material_print_temperature" },
-
+
"switch_extruder_retraction_speeds": {"default_value": 15 },
"switch_extruder_retraction_speed": {"default_value": 15 },
"switch_extruder_prime_speed": {"default_value": 15 },
@@ -57,9 +55,9 @@
"prime_tower_wipe_enabled": { "default_value": false },
"prime_tower_min_volume": { "default_value": 50 },
"dual_pre_wipe": { "default_value": false },
-
+
"prime_blob_enable": { "enabled": true },
-
+
"acceleration_enabled": { "value": "True" },
"acceleration_layer_0": { "value": "acceleration_topbottom" },
"acceleration_prime_tower": { "value": "math.ceil(acceleration_print * 2000 / 4000)" },
@@ -70,7 +68,7 @@
"acceleration_travel": { "value": "acceleration_print" },
"acceleration_wall": { "value": "math.ceil(acceleration_print * 1000 / 3000)" },
"acceleration_wall_0": { "value": "math.ceil(acceleration_wall * 1000 / 1000)" },
-
+
"cool_fan_full_at_height": { "value": "layer_height_0 + 2 * layer_height" },
"cool_min_layer_time": { "default_value": 10 },
@@ -83,9 +81,9 @@
"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)" },
-
+
"wall_thickness": { "value": "1.2" },
-
+
"retraction_amount": { "default_value": 3 },
"retraction_speed": { "default_value": 15 },
"retraction_retract_speed": { "default_value": 15 },
@@ -112,4 +110,4 @@
},
"machine_extruder_count": { "default_value": 2 }
}
-}
\ No newline at end of file
+}
diff --git a/resources/definitions/cartesio.def.json b/resources/definitions/cartesio.def.json
index 44f3153015..5ca891d6c5 100644
--- a/resources/definitions/cartesio.def.json
+++ b/resources/definitions/cartesio.def.json
@@ -5,7 +5,7 @@
"metadata": {
"visible": true,
"author": "Scheepers",
- "manufacturer": "Cartesio bv",
+ "manufacturer": "MaukCC",
"file_formats": "text/x-gcode",
"has_machine_quality": true,
@@ -14,10 +14,10 @@
"has_variant_materials": true,
"has_variants": true,
- "variants_name": "Nozzle size",
- "preferred_variant": "*0.8*",
- "preferred_material": "*pla*",
- "preferred_quality": "*normal*",
+ "variants_name": "Tool",
+ "preferred_variant_name": "0.8 mm",
+ "preferred_material": "generic_pla",
+ "preferred_quality_type": "normal",
"machine_extruder_trains":
{
@@ -44,7 +44,7 @@
"machine_gcode_flavor": { "default_value": "RepRap (Marlin/Sprinter)" },
"material_print_temp_wait": { "default_value": false },
"material_bed_temp_wait": { "default_value": false },
- "prime_tower_enable": { "default_value": true },
+ "prime_tower_enable": { "default_value": false },
"prime_tower_wall_thickness": { "resolve": 0.7 },
"prime_tower_size": { "value": 24.0 },
"prime_tower_position_x": { "value": 125 },
@@ -55,15 +55,16 @@
[[215, 135], [-215, 135], [-215, 75], [215, 75]]
]},
"machine_start_gcode": {
- "default_value": "\nM92 E159 ;2288 for V5 extruder\n\nM140 S{material_bed_temperature_layer_0}\nM104 S120 T1\nM104 S120 T2\nM104 S120 T3\n\nG21\nG90\nM42 S255 P13 ;chamber lights\nM42 S255 P12 ;fume extraction\nM204 S300 ;default acceleration\nM205 X10 ;default jerk\n\nM117 Homing Y ......\nG28 Y\nM117 Homing X ......\nG28 X\nM117 Homing Z ......\nG28 Z F100\nG1 Z10 F600\nG1 X70 Y20 F9000;go to wipe point\n\nM190 S{material_bed_temperature_layer_0}\n\nM117 Heating for 50 sec.\nG4 S20\nM117 Heating for 30 sec.\nG4 S20\nM117 Heating for 10 sec.\nM300 S1200 P1000\nG4 S9\n\nM117 purging nozzle....\nT0\nG92 E0;set E\nG1 E10 F100\nG92 E0\nG1 E-1 F600\n\nM117 wiping nozzle....\nG1 X1 Y24 F3000\nG1 X70 F9000\nG1 Z10 F900\n\nM104 S21 T1\nM104 S21 T2\nM104 S21 T3\n\nM117 Printing .....\n"
+ "default_value": "\nM92 E159 ;2288 for V5 extruder\n\nM140 S{material_bed_temperature_layer_0}\nM104 T1 S120\nM104 T2 S120\nM104 T3 S120\n\nG21\nG90\nM42 S255 P13 ;chamber lights\nM42 S255 P12 ;fume extraction\nM204 S300 ;default acceleration\nM205 X10 ;default jerk\n\nM117 Homing Y ......\nG28 Y\nM117 Homing X ......\nG28 X\nM117 Homing Z ......\nG28 Z F100\nG1 Z10 F600\nG1 X70 Y20 F9000;go to wipe point\n\nM190 S{material_bed_temperature_layer_0}\n\nM117 Heating for 50 sec.\nG4 S20\nM117 Heating for 30 sec.\nG4 S20\nM117 Heating for 10 sec.\nM300 S1200 P1000\nG4 S9\n\nM117 purging nozzle....\nT0\nG92 E0;set E\nG1 E10 F100\nG92 E0\nG1 E-1 F600\n\nM117 wiping nozzle....\nG1 X1 Y24 F3000\nG1 X70 F9000\nG1 Z10 F900\n\nM104 T1 S21\nM104 T2 S21\nM104 T3 S21\n\nM117 Printing .....\n"
},
"machine_end_gcode": {
- "default_value": "; -- END GCODE --\nM117 cooling down....\nM106 S255\nM140 S5\nM104 S5 T0\nM104 S5 T1\nM104 S5 T2\nM104 S5 T3\n\nG91\nG1 Z1 F900\nG90\n\nG1 X20.0 Y260.0 F6000\nG4 S7\nM84\nG4 S90\nM107\nM42 P12 S0\nM42 P13 S0\nM84\nT0\nM117 Finished.\n; -- end of GCODE --"
+ "default_value": "; -- END GCODE --\nM117 cooling down....\nM106 S255\nM140 S5\nM104 T0 S5\nM104 T1 S5\nM104 T2 S5\nM104 T3 S5\n\nG91\nG1 Z1 F900\nG90\n\nG1 X20.0 Y260.0 F6000\nG4 S7\nM84\nG4 S90\nM107\nM42 P12 S0\nM42 P13 S0\nM84\nT0\nM117 Finished.\n; -- end of GCODE --"
},
"layer_height": { "maximum_value": "(0.8 * min(extruderValues('machine_nozzle_size')))" },
"layer_height_0": { "maximum_value": "(0.8 * min(extruderValues('machine_nozzle_size')))" },
"retraction_extra_prime_amount": { "minimum_value_warning": "-2.0" },
"optimize_wall_printing_order": { "default_value": true },
+ "material_initial_print_temperature": {"maximum_value_warning": "material_print_temperature + 15" },
"machine_nozzle_heat_up_speed": {"default_value": 20},
"machine_nozzle_cool_down_speed": {"default_value": 20},
"machine_min_cool_heat_time_window": {"default_value": 5}
diff --git a/resources/definitions/creality_cr10.def.json b/resources/definitions/creality_cr10.def.json
index 7a58adcd4d..eb0b8c7306 100644
--- a/resources/definitions/creality_cr10.def.json
+++ b/resources/definitions/creality_cr10.def.json
@@ -7,7 +7,7 @@
"author": "Michael Wildermuth",
"manufacturer": "Creality3D",
"file_formats": "text/x-gcode",
- "preferred_quality": "*Draft*"
+ "preferred_quality_type": "draft"
},
"overrides": {
"machine_width": {
diff --git a/resources/definitions/dagoma_discoeasy200.def.json b/resources/definitions/dagoma_discoeasy200.def.json
index 9bcc2402f2..4f0fddc41d 100644
--- a/resources/definitions/dagoma_discoeasy200.def.json
+++ b/resources/definitions/dagoma_discoeasy200.def.json
@@ -7,7 +7,6 @@
"author": "Dagoma",
"manufacturer": "Dagoma",
"file_formats": "text/x-gcode",
- "icon": "icon_discoeasy200.png",
"platform": "discoeasy200.stl",
"platform_offset": [ 105, -59, 280]
},
@@ -39,13 +38,25 @@
"default_value": 10
},
"machine_start_gcode": {
- "default_value": ";Gcode by Cura\nG90 ;absolute positioning\nM106 S250 ;fan on for the palpeur\nG28 X Y\nG1 X50\nM109 S180\nG28\nM104 S{material_print_temperature_layer_0}\n;Activation palpeur\n;bloc palpeur\nG29 ;Auto level\nM107 ;start with the fan off\nG1 X100 Y20 F3000\nG1 Z0.5\nM109 S{material_print_temperature_layer_0}\nM82 ;set extruder to absolute mode\nG92 E0 ;zero the extruded length\nG1 F200 E10 ;extrude 10mm of feed stock\nG92 E0 ;zero the extruded length again\nG1 Z3\nG1 F6000"
+ "default_value": ";Gcode by Cura\nG90\nM106 S250\nG28 X Y\nG1 X50\nM109 S180\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"
},
"machine_end_gcode": {
- "default_value": "M104 S0\nM106 S255 ;start fan full power\nM140 S0 ;heated bed heater off (if you have it)\n;Home machine\nG91 ;relative positioning\nG1 E-1 F300 ;retract the filament a bit before lifting the nozzle, to release some of the pressure\nG1 Z+3 F3000 ;move Z up a bit and retract filament even more\nG90\nG28 X Y\n;Ventilation forcee\nM107 ;stop fan\n;Shut down motor\nM84 ;shut down motors"
+ "default_value": "\nM104 S0\nM106 S255\nM140 S0\nG91\nG1 E-1 F300\nG1 Z+3 F3000\nG90\nG28 X Y\nM107\nM84\n"
},
"material_diameter": {
"default_value": 1.75
+ },
+ "speed_print": {
+ "default_value": 60
+ },
+ "speed_travel": {
+ "value": "100"
+ },
+ "retraction_amount": {
+ "default_value": 3.5
+ },
+ "retraction_speed": {
+ "default_value": 50
}
}
}
diff --git a/resources/definitions/dagoma_neva.def.json b/resources/definitions/dagoma_neva.def.json
new file mode 100644
index 0000000000..21a557ac22
--- /dev/null
+++ b/resources/definitions/dagoma_neva.def.json
@@ -0,0 +1,69 @@
+{
+ "id": "Dagoma_neva",
+ "name": "Dagoma NEVA",
+ "version": 2,
+ "inherits": "fdmprinter",
+ "metadata": {
+ "visible": true,
+ "author": "Dagoma",
+ "manufacturer": "Dagoma",
+ "file_formats": "text/x-gcode",
+ "platform": "neva.stl",
+ "platform_offset": [ 0, 0, 0]
+ },
+ "overrides": {
+ "machine_width": {
+ "default_value": 195.55
+ },
+ "machine_height": {
+ "default_value": 205
+ },
+ "machine_depth": {
+ "default_value": 195.55
+ },
+ "machine_center_is_zero": {
+ "default_value": true
+ },
+ "machine_nozzle_size": {
+ "default_value": 0.4
+ },
+ "machine_head_with_fans_polygon": {
+ "default_value": [
+ [17, 40],
+ [17, -70],
+ [-17, -70],
+ [17, 40]
+ ]
+ },
+ "gantry_height": {
+ "default_value": 0
+ },
+ "machine_shape": {
+ "default_value": "elliptic"
+ },
+ "machine_gcode_flavor": {
+ "default_value": "RepRap (RepRap)"
+ },
+ "machine_start_gcode": {
+ "default_value": ";Gcode by Cura\nG90\nG28\nM109 S100\nG29\nM104 S{material_print_temperature_layer_0}\nG0 X0 Y-85\nG0 Z0.26\nM109 S{material_print_temperature_layer_0}\nM82\nG92 E0\nG1 F200 E6\nG92 E0\nG1 F200 E-3.5\nG0 Z0.15\nG0 X10\nG0 Z3\nG1 F6000\n"
+ },
+ "machine_end_gcode": {
+ "default_value": "\nM104 S0\nM106 S255\nM140 S0\nG91\nG1 E-1 F300\nG1 Z+3 E-2 F9000\nG90\nG28\n"
+ },
+ "material_diameter": {
+ "default_value": 1.75
+ },
+ "speed_print": {
+ "default_value": 40
+ },
+ "speed_travel": {
+ "default_value": 120
+ },
+ "retraction_amount": {
+ "default_value": 3.8
+ },
+ "retraction_speed": {
+ "default_value": 60
+ }
+ }
+}
diff --git a/resources/definitions/fabtotum.def.json b/resources/definitions/fabtotum.def.json
index 87ce11a35c..d66de07c4a 100644
--- a/resources/definitions/fabtotum.def.json
+++ b/resources/definitions/fabtotum.def.json
@@ -13,18 +13,18 @@
"has_machine_quality": true,
"has_variants": true,
"variants_name": "Head",
- "preferred_variant": "*lite04*",
- "preferred_material": "*fabtotum_pla*",
+ "preferred_variant_name": "Lite 0.4 mm",
+ "preferred_material": "fabtotum_pla",
"supports_usb_connection": false
},
"overrides": {
"machine_name": { "default_value": "FABtotum Personal Fabricator" },
"machine_start_gcode": {
- "default_value": ";Layer height: {layer_height}\n;Walls: {wall_thickness}\n;Fill: {infill_sparse_density}\n;Top\\Bottom Thickness: {top_bottom_thickness}\nG90 ;absolute positioning\nM82 ;set extruder to absolute mode\nG4 S1 ;1 millisecond pause to buffer the bep bep \nM728 ;FAB bep bep (start the print, go check the oozing and skirt lines adesion) \nG4 S1 ;1 second pause to reach the printer (run fast)\nG92 E0 ;zero the extruded length \nG1 F200 E35 ;slowly extrude 35mm of filament to clean the nozzle and build up extrusion pressure \nG92 E0 ;zero the extruded length again \nG1 F{speed_travel} ;Set travel speed \n;print"
+ "default_value": ";Layer height: {layer_height}\n;Walls: {wall_thickness}\n;Fill: {infill_sparse_density}\n;Top\\Bottom Thickness: {top_bottom_thickness}\nG90 ;absolute positioning\nM82 ;set extruder to absolute mode\nG4 S1 ;1 millisecond pause to buffer the bep bep \nM300 S2 ;FAB bep bep (start the print, go check the oozing and skirt lines adesion) \nG4 S1 ;1 second pause to reach the printer (run fast)\nG92 E0 ;zero the extruded length \nG1 F200 E35 ;slowly extrude 35mm of filament to clean the nozzle and build up extrusion pressure \nG92 E0 ;zero the extruded length again \n;print"
},
"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\nM728 ;FAB bep bep (end print)"
+ "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 },
"machine_width": { "default_value": 214 },
diff --git a/resources/definitions/fdmextruder.def.json b/resources/definitions/fdmextruder.def.json
index 2b314cd6a5..3f84ed69a4 100644
--- a/resources/definitions/fdmextruder.def.json
+++ b/resources/definitions/fdmextruder.def.json
@@ -216,6 +216,30 @@
"enabled": false
}
}
+ },
+ "material":
+ {
+ "label": "Material",
+ "icon": "category_material",
+ "description": "Material",
+ "type": "category",
+ "children":
+ {
+ "material_diameter":
+ {
+ "label": "Diameter",
+ "description": "Adjusts the diameter of the filament used. Match this value with the diameter of the used filament.",
+ "unit": "mm",
+ "type": "float",
+ "default_value": 2.85,
+ "minimum_value": "0.0001",
+ "minimum_value_warning": "0.4",
+ "maximum_value_warning": "3.5",
+ "enabled": "machine_gcode_flavor != \"UltiGCode\"",
+ "settable_per_mesh": false,
+ "settable_per_extruder": true
+ }
+ }
}
}
}
diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json
index 5c31c74178..21ee543333 100644
--- a/resources/definitions/fdmprinter.def.json
+++ b/resources/definitions/fdmprinter.def.json
@@ -11,8 +11,8 @@
"file_formats": "text/x-gcode;application/x-stl-ascii;application/x-stl-binary;application/x-wavefront-obj;application/x3g",
"visible": false,
"has_materials": true,
- "preferred_material": "*generic_pla*",
- "preferred_quality": "*normal*",
+ "preferred_material": "generic_pla",
+ "preferred_quality_type": "normal",
"machine_extruder_trains":
{
"0": "fdmextruder"
@@ -51,8 +51,8 @@
},
"machine_start_gcode":
{
- "label": "Start GCode",
- "description": "Gcode commands to be executed at the very start - separated by \\n.",
+ "label": "Start G-code",
+ "description": "G-code commands to be executed at the very start - separated by \\n.",
"default_value": "G28 ;Home\nG1 Z15.0 F6000 ;Move the platform down 15mm\n;Prime the extruder\nG92 E0\nG1 F200 E3\nG92 E0",
"type": "str",
"settable_per_mesh": false,
@@ -61,8 +61,8 @@
},
"machine_end_gcode":
{
- "label": "End GCode",
- "description": "Gcode commands to be executed at the very end - separated by \\n.",
+ "label": "End G-code",
+ "description": "G-code commands to be executed at the very end - separated by \\n.",
"default_value": "M104 S0\nM140 S0\n;Retract the filament\nG92 E1\nG1 E-1 F300\nG28 X0 Y0\nM84",
"type": "str",
"settable_per_mesh": false,
@@ -163,7 +163,7 @@
"options":
{
"glass": "Glass",
- "aluminium": "Aluminium"
+ "aluminum": "Aluminum"
},
"settable_per_mesh": false,
"settable_per_extruder": false,
@@ -211,6 +211,18 @@
"settable_per_extruder": false,
"settable_per_meshgroup": false
},
+ "extruders_enabled_count":
+ {
+ "label": "Number of Extruders that are enabled",
+ "description": "Number of extruder trains that are enabled; automatically set in software",
+ "value": "machine_extruder_count",
+ "minimum_value": "1",
+ "maximum_value": "16",
+ "type": "int",
+ "settable_per_mesh": false,
+ "settable_per_extruder": false,
+ "settable_per_meshgroup": false
+ },
"machine_nozzle_tip_outer_diameter":
{
"label": "Outer nozzle diameter",
@@ -312,8 +324,8 @@
},
"machine_gcode_flavor":
{
- "label": "Gcode flavour",
- "description": "The type of gcode to be generated.",
+ "label": "G-code flavour",
+ "description": "The type of g-code to be generated.",
"type": "enum",
"options":
{
@@ -620,6 +632,73 @@
"settable_per_extruder": false,
"settable_per_meshgroup": false
},
+ "machine_steps_per_mm_x":
+ {
+ "label": "Steps per Millimeter (X)",
+ "description": "How many steps of the stepper motor will result in one millimeter of movement in the X direction.",
+ "type": "int",
+ "default_value": 50,
+ "minimum_value": "0.0000001",
+ "settable_per_mesh": false,
+ "settable_per_extruder": true
+ },
+ "machine_steps_per_mm_y":
+ {
+ "label": "Steps per Millimeter (Y)",
+ "description": "How many steps of the stepper motor will result in one millimeter of movement in the Y direction.",
+ "type": "int",
+ "default_value": 50,
+ "minimum_value": "0.0000001",
+ "settable_per_mesh": false,
+ "settable_per_extruder": true
+ },
+ "machine_steps_per_mm_z":
+ {
+ "label": "Steps per Millimeter (Z)",
+ "description": "How many steps of the stepper motor will result in one millimeter of movement in the Z direction.",
+ "type": "int",
+ "default_value": 50,
+ "minimum_value": "0.0000001",
+ "settable_per_mesh": false,
+ "settable_per_extruder": true
+ },
+ "machine_steps_per_mm_e":
+ {
+ "label": "Steps per Millimeter (E)",
+ "description": "How many steps of the stepper motors will result in one millimeter of extrusion.",
+ "type": "int",
+ "default_value": 1600,
+ "minimum_value": "0.0000001",
+ "settable_per_mesh": false,
+ "settable_per_extruder": true
+ },
+ "machine_endstop_positive_direction_x":
+ {
+ "label": "X Endstop in Positive Direction",
+ "description": "Whether the endstop of the X axis is in the positive direction (high X coordinate) or negative (low X coordinate).",
+ "type": "bool",
+ "default_value": false,
+ "settable_per_mesh": false,
+ "settable_per_extruder": true
+ },
+ "machine_endstop_positive_direction_y":
+ {
+ "label": "Y Endstop in Positive Direction",
+ "description": "Whether the endstop of the Y axis is in the positive direction (high Y coordinate) or negative (low Y coordinate).",
+ "type": "bool",
+ "default_value": false,
+ "settable_per_mesh": false,
+ "settable_per_extruder": true
+ },
+ "machine_endstop_positive_direction_z":
+ {
+ "label": "Z Endstop in Positive Direction",
+ "description": "Whether the endstop of the Z axis is in the positive direction (high Z coordinate) or negative (low Z coordinate).",
+ "type": "bool",
+ "default_value": true,
+ "settable_per_mesh": false,
+ "settable_per_extruder": true
+ },
"machine_minimum_feedrate":
{
"label": "Minimum Feedrate",
@@ -630,6 +709,16 @@
"settable_per_mesh": false,
"settable_per_extruder": false,
"settable_per_meshgroup": false
+ },
+ "machine_feeder_wheel_diameter":
+ {
+ "label": "Feeder Wheel Diameter",
+ "description": "The diameter of the wheel that drives the material in the feeder.",
+ "unit": "mm",
+ "type": "float",
+ "default_value": 10.0,
+ "settable_per_mesh": false,
+ "settable_per_extruder": true
}
}
},
@@ -668,20 +757,6 @@
"settable_per_mesh": false,
"settable_per_extruder": false
},
- "slicing_tolerance":
- {
- "label": "Slicing Tolerance",
- "description": "How to slice layers with diagonal surfaces. The areas of a layer can be generated based on where the middle of the layer intersects the surface (Middle). Alternatively each layer can have the areas which fall inside of the volume throughout the height of the layer (Exclusive) or a layer has the areas which fall inside anywhere within the layer (Inclusive). Exclusive retains the most details, Inclusive makes for the best fit and Middle takes the least time to process.",
- "type": "enum",
- "options":
- {
- "middle": "Middle",
- "exclusive": "Exclusive",
- "inclusive": "Inclusive"
- },
- "default_value": "middle",
- "settable_per_mesh": true
- },
"line_width":
{
"label": "Line Width",
@@ -741,21 +816,6 @@
}
}
},
- "roofing_line_width":
- {
- "label": "Top Surface Skin Line Width",
- "description": "Width of a single line of the areas at the top of the print.",
- "unit": "mm",
- "minimum_value": "0.001",
- "minimum_value_warning": "0.1 + 0.4 * machine_nozzle_size",
- "maximum_value_warning": "2 * machine_nozzle_size",
- "default_value": 0.4,
- "type": "float",
- "value": "skin_line_width",
- "limit_to_extruder": "roofing_extruder_nr",
- "settable_per_mesh": true,
- "enabled": "roofing_layer_count > 0 and top_layers > 0"
- },
"skin_line_width":
{
"label": "Top/Bottom Line Width",
@@ -916,7 +976,7 @@
"settable_per_extruder": false,
"settable_per_meshgroup": true,
"settable_globally": true,
- "enabled": "machine_extruder_count > 1",
+ "enabled": "extruders_enabled_count > 1",
"children": {
"wall_0_extruder_nr":
{
@@ -929,7 +989,7 @@
"settable_per_extruder": false,
"settable_per_meshgroup": true,
"settable_globally": true,
- "enabled": "machine_extruder_count > 1"
+ "enabled": "extruders_enabled_count > 1"
},
"wall_x_extruder_nr":
{
@@ -942,7 +1002,7 @@
"settable_per_extruder": false,
"settable_per_meshgroup": true,
"settable_globally": true,
- "enabled": "machine_extruder_count > 1"
+ "enabled": "extruders_enabled_count > 1"
}
}
},
@@ -999,7 +1059,7 @@
"settable_per_extruder": false,
"settable_per_meshgroup": true,
"settable_globally": true,
- "enabled": "machine_extruder_count > 1 and max(extruderValues('roofing_layer_count')) > 0 and max(extruderValues('top_layers')) > 0"
+ "enabled": "extruders_enabled_count > 1 and max(extruderValues('roofing_layer_count')) > 0 and max(extruderValues('top_layers')) > 0"
},
"roofing_layer_count":
{
@@ -1014,34 +1074,6 @@
"settable_per_mesh": true,
"enabled": "top_layers > 0"
},
- "roofing_pattern":
- {
- "label": "Top Surface Skin Pattern",
- "description": "The pattern of the top most layers.",
- "type": "enum",
- "options":
- {
- "lines": "Lines",
- "concentric": "Concentric",
- "zigzag": "Zig Zag"
- },
- "default_value": "lines",
- "value": "top_bottom_pattern",
- "limit_to_extruder": "roofing_extruder_nr",
- "settable_per_mesh": true,
- "enabled": "roofing_layer_count > 0 and top_layers > 0"
- },
- "roofing_angles":
- {
- "label": "Top Surface Skin Line Directions",
- "description": "A list of integer line directions to use when the top surface skin layers use the lines or zig zag pattern. 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 traditional default angles (45 and 135 degrees).",
- "type": "[int]",
- "default_value": "[ ]",
- "value": "skin_angles",
- "enabled": "roofing_pattern != 'concentric' and roofing_layer_count > 0 and top_layers > 0",
- "limit_to_extruder": "roofing_extruder_nr",
- "settable_per_mesh": true
- },
"top_bottom_extruder_nr":
{
"label": "Top/Bottom Extruder",
@@ -1052,7 +1084,7 @@
"settable_per_extruder": false,
"settable_per_meshgroup": true,
"settable_globally": true,
- "enabled": "machine_extruder_count > 1"
+ "enabled": "extruders_enabled_count > 1"
},
"top_bottom_thickness":
{
@@ -1522,7 +1554,7 @@
"settable_per_extruder": false,
"settable_per_meshgroup": true,
"settable_globally": true,
- "enabled": "machine_extruder_count > 1"
+ "enabled": "extruders_enabled_count > 1"
},
"infill_sparse_density":
{
@@ -1584,8 +1616,10 @@
"label": "Connect Infill Lines",
"description": "Connect the ends where the infill pattern meets the inner wall using a line which follows the shape of the inner wall. Enabling this setting can make the infill adhere to the walls better and reduce the effects of infill on the quality of vertical surfaces. Disabling this setting reduces the amount of material used.",
"type": "bool",
- "default_value": true,
- "enabled": "infill_pattern == 'cross' or infill_pattern == 'cross_3d'",
+ "default_value": false,
+ "value": "infill_pattern == 'cross' or infill_pattern == 'cross_3d'",
+ "enabled": "infill_pattern == 'grid' or infill_pattern == 'triangles' or infill_pattern == 'trihexagon' or infill_pattern == 'cubic' or infill_pattern == 'tetrahedral' or infill_pattern == 'quarter_cubic' or infill_pattern == 'cross' or infill_pattern == 'cross_3d'",
+ "limit_to_extruder": "infill_extruder_nr",
"settable_per_mesh": true
},
"infill_angles":
@@ -1876,14 +1910,6 @@
"settable_per_mesh": true
}
}
- },
- "infill_enable_travel_optimization":
- {
- "label": "Enable Travel Optimization",
- "description": "When enabled, the order in which the infill lines are printed is optimized to reduce the distance travelled. The reduction in travel time achieved very much depends on the model being sliced, infill pattern, density, etc. Note that, for some models that have many small areas of infill, the time to slice the model may be greatly increased.",
- "type": "bool",
- "default_value": false,
- "settable_per_mesh": true
}
}
},
@@ -1895,16 +1921,6 @@
"type": "category",
"children":
{
- "material_flow_dependent_temperature":
- {
- "label": "Auto Temperature",
- "description": "Change the temperature for each layer automatically with the average flow speed of that layer.",
- "type": "bool",
- "default_value": false,
- "enabled": "machine_nozzle_temp_enabled and False",
- "settable_per_mesh": false,
- "settable_per_extruder": true
- },
"default_material_print_temperature":
{
"label": "Default Printing Temperature",
@@ -1979,17 +1995,6 @@
"settable_per_mesh": false,
"settable_per_extruder": true
},
- "material_flow_temp_graph":
- {
- "label": "Flow Temperature Graph",
- "description": "Data linking material flow (in mm3 per second) to temperature (degrees Celsius).",
- "unit": "[[mm³,°C]]",
- "type": "str",
- "default_value": "[[3.5,200],[7.0,240]]",
- "enabled": "False and machine_nozzle_temp_enabled and material_flow_dependent_temperature",
- "settable_per_mesh": false,
- "settable_per_extruder": true
- },
"material_extrusion_cool_down_speed":
{
"label": "Extrusion Cool Down Speed Modifier",
@@ -2000,7 +2005,7 @@
"minimum_value": "0",
"maximum_value_warning": "10.0",
"maximum_value": "machine_nozzle_heat_up_speed",
- "enabled": "material_flow_dependent_temperature or (machine_extruder_count > 1 and material_final_print_temperature != material_print_temperature)",
+ "enabled": "material_flow_dependent_temperature or (extruders_enabled_count > 1 and material_final_print_temperature != material_print_temperature)",
"settable_per_mesh": false,
"settable_per_extruder": true
},
@@ -2105,6 +2110,19 @@
"enabled": "machine_gcode_flavor != \"UltiGCode\"",
"settable_per_mesh": true
},
+ "material_flow_layer_0":
+ {
+ "label": "Initial Layer Flow",
+ "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",
+ "maximum_value_warning": "150",
+ "settable_per_mesh": true
+ },
"retraction_enable":
{
"label": "Enable Retraction",
@@ -2114,7 +2132,8 @@
"settable_per_mesh": false,
"settable_per_extruder": true
},
- "retract_at_layer_change":{
+ "retract_at_layer_change":
+ {
"label": "Retract at Layer Change",
"description": "Retract the filament when the nozzle is moving to the next layer.",
"type": "bool",
@@ -2144,7 +2163,7 @@
"default_value": 25,
"minimum_value": "0.0001",
"minimum_value_warning": "1",
- "maximum_value": "machine_max_feedrate_e",
+ "maximum_value": "machine_max_feedrate_e if retraction_enable else float('inf')",
"maximum_value_warning": "70",
"enabled": "retraction_enable and machine_gcode_flavor != \"UltiGCode\"",
"settable_per_mesh": false,
@@ -2159,7 +2178,7 @@
"type": "float",
"default_value": 25,
"minimum_value": "0.0001",
- "maximum_value": "machine_max_feedrate_e",
+ "maximum_value": "machine_max_feedrate_e if retraction_enable else float('inf')",
"minimum_value_warning": "1",
"maximum_value_warning": "70",
"enabled": "retraction_enable and machine_gcode_flavor != \"UltiGCode\"",
@@ -2175,7 +2194,7 @@
"type": "float",
"default_value": 25,
"minimum_value": "0.0001",
- "maximum_value": "machine_max_feedrate_e",
+ "maximum_value": "machine_max_feedrate_e if retraction_enable else float('inf')",
"minimum_value_warning": "1",
"maximum_value_warning": "70",
"enabled": "retraction_enable and machine_gcode_flavor != \"UltiGCode\"",
@@ -2207,6 +2226,7 @@
"default_value": 1.5,
"value": "line_width * 2",
"minimum_value": "0",
+ "minimum_value_warning": "line_width * 1.5",
"maximum_value_warning": "10",
"enabled": "retraction_enable",
"settable_per_mesh": false,
@@ -2248,7 +2268,7 @@
"minimum_value": "-273.15",
"minimum_value_warning": "0",
"maximum_value_warning": "260",
- "enabled": "machine_extruder_count > 1 and machine_nozzle_temp_enabled",
+ "enabled": "extruders_enabled_count > 1 and machine_nozzle_temp_enabled",
"settable_per_mesh": false,
"settable_per_extruder": true
},
@@ -2276,7 +2296,7 @@
"default_value": 20,
"minimum_value": "0.1",
"minimum_value_warning": "1",
- "maximum_value": "machine_max_feedrate_e",
+ "maximum_value": "machine_max_feedrate_e if retraction_enable else float('inf')",
"maximum_value_warning": "70",
"settable_per_mesh": false,
"settable_per_extruder": true,
@@ -2293,7 +2313,7 @@
"value": "switch_extruder_retraction_speeds",
"minimum_value": "0.1",
"minimum_value_warning": "1",
- "maximum_value": "machine_max_feedrate_e",
+ "maximum_value": "machine_max_feedrate_e if retraction_enable else float('inf')",
"maximum_value_warning": "70",
"settable_per_mesh": false,
"settable_per_extruder": true
@@ -2309,7 +2329,7 @@
"value": "switch_extruder_retraction_speeds",
"minimum_value": "0.1",
"minimum_value_warning": "1",
- "maximum_value": "machine_max_feedrate_e",
+ "maximum_value": "machine_max_feedrate_e if retraction_enable else float('inf')",
"maximum_value_warning": "70",
"settable_per_mesh": false,
"settable_per_extruder": true
@@ -3350,7 +3370,7 @@
"description": "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.",
"type": "bool",
"default_value": true,
- "enabled": "retraction_hop_enabled and machine_extruder_count > 1",
+ "enabled": "retraction_hop_enabled and extruders_enabled_count > 1",
"settable_per_mesh": false,
"settable_per_extruder": true
}
@@ -3522,22 +3542,14 @@
"settable_per_mesh": true,
"settable_per_extruder": false
},
- "support_tree_enable":
- {
- "label": "Tree Support",
- "description": "Generate a tree-like support with branches that support your print. This may reduce material usage and print time.",
- "type": "bool",
- "default_value": false,
- "settable_per_mesh": true,
- "settable_per_extruder": false
- },
"support_extruder_nr":
{
"label": "Support Extruder",
"description": "The extruder train to use for printing the support. This is used in multi-extrusion.",
"type": "extruder",
"default_value": "0",
- "enabled": "(support_enable or support_tree_enable) and machine_extruder_count > 1",
+ "value": "-1",
+ "enabled": "(support_enable or support_tree_enable) and extruders_enabled_count > 1",
"settable_per_mesh": false,
"settable_per_extruder": false,
"children": {
@@ -3548,7 +3560,7 @@
"type": "extruder",
"default_value": "0",
"value": "support_extruder_nr",
- "enabled": "(support_enable or support_tree_enable) and machine_extruder_count > 1",
+ "enabled": "(support_enable or support_tree_enable) and extruders_enabled_count > 1",
"settable_per_mesh": false,
"settable_per_extruder": false
},
@@ -3559,7 +3571,7 @@
"type": "extruder",
"default_value": "0",
"value": "support_extruder_nr",
- "enabled": "(support_enable or support_tree_enable) and machine_extruder_count > 1",
+ "enabled": "(support_enable or support_tree_enable) and extruders_enabled_count > 1",
"settable_per_mesh": false,
"settable_per_extruder": false
},
@@ -3570,7 +3582,7 @@
"type": "extruder",
"default_value": "0",
"value": "support_extruder_nr",
- "enabled": "(support_enable or support_tree_enable) and machine_extruder_count > 1",
+ "enabled": "(support_enable or support_tree_enable) and extruders_enabled_count > 1",
"settable_per_mesh": false,
"settable_per_extruder": false,
"children":
@@ -3582,7 +3594,7 @@
"type": "extruder",
"default_value": "0",
"value": "support_interface_extruder_nr",
- "enabled": "(support_enable or support_tree_enable) and machine_extruder_count > 1",
+ "enabled": "(support_enable or support_tree_enable) and extruders_enabled_count > 1",
"settable_per_mesh": false,
"settable_per_extruder": false
},
@@ -3593,7 +3605,7 @@
"type": "extruder",
"default_value": "0",
"value": "support_interface_extruder_nr",
- "enabled": "(support_enable or support_tree_enable) and machine_extruder_count > 1",
+ "enabled": "(support_enable or support_tree_enable) and extruders_enabled_count > 1",
"settable_per_mesh": false,
"settable_per_extruder": false
}
@@ -3652,6 +3664,18 @@
"settable_per_mesh": false,
"settable_per_extruder": true
},
+ "zig_zaggify_support":
+ {
+ "label": "Connect Support Lines",
+ "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'",
+ "limit_to_extruder": "support_infill_extruder_nr",
+ "settable_per_mesh": false,
+ "settable_per_extruder": true
+ },
"support_connect_zigzags":
{
"label": "Connect Support ZigZags",
@@ -3849,110 +3873,6 @@
"limit_to_extruder": "support_infill_extruder_nr",
"settable_per_mesh": false
},
- "support_tree_angle":
- {
- "label": "Tree Support Branch Angle",
- "description": "The angle of the branches. Use a lower angle to make them more vertical and more stable. Use a higher angle to be able to have more reach.",
- "unit": "°",
- "type": "float",
- "minimum_value": "0",
- "maximum_value": "90",
- "maximum_value_warning": "60",
- "default_value": 40,
- "limit_to_extruder": "support_infill_extruder_nr",
- "enabled": "support_tree_enable",
- "settable_per_mesh": false,
- "settable_per_extruder": true
- },
- "support_tree_branch_distance":
- {
- "label": "Tree Support Branch Distance",
- "description": "How far apart the branches need to be when they touch the model. Making this distance small will cause the tree support to touch the model at more points, causing better overhang but making support harder to remove.",
- "unit": "mm",
- "type": "float",
- "minimum_value": "0.001",
- "default_value": 4,
- "limit_to_extruder": "support_infill_extruder_nr",
- "enabled": "support_tree_enable",
- "settable_per_mesh": true
- },
- "support_tree_branch_diameter":
- {
- "label": "Tree Support Branch Diameter",
- "description": "The diameter of the thinnest branches of tree support. Thicker branches are more sturdy. Branches towards the base will be thicker than this.",
- "unit": "mm",
- "type": "float",
- "minimum_value": "0.001",
- "minimum_value_warning": "support_line_width * 2",
- "default_value": 2,
- "limit_to_extruder": "support_infill_extruder_nr",
- "enabled": "support_tree_enable",
- "settable_per_mesh": false,
- "settable_per_extruder": true
- },
- "support_tree_branch_diameter_angle":
- {
- "label": "Tree Support Branch Diameter Angle",
- "description": "The angle of the branches' diameter as they gradually become thicker towards the bottom. An angle of 0 will cause the branches to have uniform thickness over their length. A bit of an angle can increase stability of the tree support.",
- "unit": "°",
- "type": "float",
- "minimum_value": "0",
- "maximum_value": "89.9999",
- "maximum_value_warning": "15",
- "default_value": 5,
- "limit_to_extruder": "support_infill_extruder_nr",
- "enabled": "support_tree_enable",
- "settable_per_mesh": false,
- "settable_per_extruder": true
- },
- "support_tree_collision_resolution":
- {
- "label": "Tree Support Collision Resolution",
- "description": "Resolution to compute collisions with to avoid hitting the model. Setting this lower will produce more accurate trees that fail less often, but increases slicing time dramatically.",
- "unit": "mm",
- "type": "float",
- "minimum_value": "0.001",
- "minimum_value_warning": "support_line_width / 4",
- "maximum_value_warning": "support_line_width * 2",
- "default_value": 0.4,
- "value": "support_line_width / 2",
- "limit_to_extruder": "support_infill_extruder_nr",
- "enabled": "support_tree_enable and support_tree_branch_diameter_angle > 0",
- "settable_per_mesh": false,
- "settable_per_extruder": true
- },
- "support_tree_wall_thickness":
- {
- "label": "Tree Support Wall Thickness",
- "description": "The thickness of the walls of the branches of tree support. Thicker walls take longer to print but don't fall over as easily.",
- "unit": "mm",
- "type": "float",
- "minimum_value": "0",
- "minimum_value_warning": "wall_line_width",
- "default_value": 0.8,
- "value": "support_line_width",
- "limit_to_extruder": "support_infill_extruder_nr",
- "enabled": "support_tree_enable",
- "settable_per_mesh": false,
- "settable_per_extruder": true,
- "children":
- {
- "support_tree_wall_count":
- {
- "label": "Tree Support Wall Line Count",
- "description": "The number of walls of the branches of tree support. Thicker walls take longer to print but don't fall over as easily.",
- "type": "int",
- "minimum_value": "0",
- "minimum_value_warning": "1",
- "default_value": 1,
- "value": "round(support_tree_wall_thickness / support_line_width)",
- "limit_to_extruder": "support_infill_extruder_nr",
- "enabled": "support_tree_enable",
- "settable_per_mesh": false,
- "settable_per_extruder": true
- }
- }
- },
"gradual_support_infill_steps":
{
"label": "Gradual Support Infill Steps",
@@ -4355,7 +4275,8 @@
"description": "The extruder train to use for printing the skirt/brim/raft. This is used in multi-extrusion.",
"type": "extruder",
"default_value": "0",
- "enabled": "machine_extruder_count > 1 and resolveOrValue('adhesion_type') != 'none'",
+ "value": "-1",
+ "enabled": "extruders_enabled_count > 1 and resolveOrValue('adhesion_type') != 'none'",
"settable_per_mesh": false,
"settable_per_extruder": false
},
@@ -4926,12 +4847,23 @@
"label": "Enable Prime Tower",
"description": "Print a tower next to the print which serves to prime the material after each nozzle switch.",
"type": "bool",
- "enabled": "machine_extruder_count > 1",
+ "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'))",
+ "settable_per_mesh": false,
+ "settable_per_extruder": false
+ },
"prime_tower_size":
{
"label": "Prime Tower Size",
@@ -4955,8 +4887,9 @@
"unit": "mm³",
"type": "float",
"default_value": 10,
+ "value": "8.48 if prime_tower_circular else 10",
"minimum_value": "0",
- "maximum_value_warning": "resolveOrValue('prime_tower_size') ** 2 * resolveOrValue('layer_height')",
+ "maximum_value_warning": "round((resolveOrValue('prime_tower_size') * 0.5) ** 2 * 3.14159 * resolveOrValue('layer_height'), 2) if prime_tower_circular else resolveOrValue('prime_tower_size') ** 2 * resolveOrValue('layer_height')",
"enabled": "resolveOrValue('prime_tower_enable')",
"settable_per_mesh": false,
"settable_per_extruder": true,
@@ -4969,7 +4902,7 @@
"unit": "mm",
"type": "float",
"default_value": 2,
- "value": "round(max(2 * prime_tower_line_width, 0.5 * (prime_tower_size - math.sqrt(max(0, prime_tower_size ** 2 - prime_tower_min_volume / layer_height)))), 3)",
+ "value": "round(max(2 * prime_tower_line_width, (0.5 * (prime_tower_size - math.sqrt(max(0, prime_tower_size ** 2 - 4 * prime_tower_min_volume / (3.14159 * layer_height))))) if prime_tower_circular else (0.5 * (prime_tower_size - math.sqrt(max(0, prime_tower_size ** 2 - prime_tower_min_volume / layer_height))))), 3)",
"resolve": "max(extruderValues('prime_tower_wall_thickness'))",
"minimum_value": "0.001",
"minimum_value_warning": "2 * min(extruderValues('prime_tower_line_width')) - 0.0001",
@@ -5062,7 +4995,7 @@
"description": "Enable exterior ooze shield. This will create a shell around the model which is likely to wipe a second nozzle if it's at the same height as the first nozzle.",
"type": "bool",
"resolve": "any(extruderValues('ooze_shield_enabled'))",
- "enabled": "machine_extruder_count > 1",
+ "enabled": "extruders_enabled_count > 1",
"default_value": false,
"settable_per_mesh": false,
"settable_per_extruder": false
@@ -5132,23 +5065,11 @@
"meshfix_keep_open_polygons":
{
"label": "Keep Disconnected Faces",
- "description": "Normally Cura tries to stitch up small holes in the mesh and remove parts of a layer with big holes. Enabling this option keeps those parts which cannot be stitched. This option should be used as a last resort option when everything else fails to produce proper GCode.",
+ "description": "Normally Cura tries to stitch up small holes in the mesh and remove parts of a layer with big holes. Enabling this option keeps those parts which cannot be stitched. This option should be used as a last resort option when everything else fails to produce proper g-code.",
"type": "bool",
"default_value": false,
"settable_per_mesh": true
},
- "meshfix_maximum_resolution":
- {
- "label": "Maximum Resolution",
- "description": "The minimum size of a line segment after slicing. If you increase this, the mesh will have a lower resolution. This may allow the printer to keep up with the speed it has to process g-code and will increase slice speed by removing details of the mesh that it can't process anyway.",
- "type": "float",
- "unit": "mm",
- "default_value": 0.01,
- "minimum_value": "0.001",
- "minimum_value_warning": "0.005",
- "maximum_value_warning": "0.1",
- "settable_per_mesh": true
- },
"multiple_mesh_overlap":
{
"label": "Merged Meshes Overlap",
@@ -5167,7 +5088,7 @@
"description": "Remove areas where multiple meshes are overlapping with each other. This may be used if merged dual material objects overlap with each other.",
"type": "bool",
"default_value": true,
- "value": "machine_extruder_count > 1",
+ "value": "extruders_enabled_count > 1",
"settable_per_mesh": false,
"settable_per_extruder": false,
"settable_per_meshgroup": true
@@ -5214,7 +5135,7 @@
"one_at_a_time": "One at a Time"
},
"default_value": "all_at_once",
- "enabled": "machine_extruder_count == 1",
+ "enabled": "extruders_enabled_count == 1",
"settable_per_mesh": false,
"settable_per_extruder": false,
"settable_per_meshgroup": false
@@ -5359,7 +5280,7 @@
"relative_extrusion":
{
"label": "Relative Extrusion",
- "description": "Use relative extrusion rather than absolute extrusion. Using relative E-steps makes for easier post-processing of the Gcode. However, it's not supported by all printers and it may produce very slight deviations in the amount of deposited material compared to absolute E-steps. Irrespective of this setting, the extrusion mode will always be set to absolute before any Gcode script is output.",
+ "description": "Use relative extrusion rather than absolute extrusion. Using relative E-steps makes for easier post-processing of the g-code. However, it's not supported by all printers and it may produce very slight deviations in the amount of deposited material compared to absolute E-steps. Irrespective of this setting, the extrusion mode will always be set to absolute before any g-code script is output.",
"type": "bool",
"default_value": false,
"value": "machine_gcode_flavor==\"RepRap (RepRap)\"",
@@ -5377,6 +5298,217 @@
"description": "experimental!",
"children":
{
+ "support_tree_enable":
+ {
+ "label": "Tree Support",
+ "description": "Generate a tree-like support with branches that support your print. This may reduce material usage and print time, but greatly increases slicing time.",
+ "type": "bool",
+ "default_value": false,
+ "settable_per_mesh": true,
+ "settable_per_extruder": false
+ },
+ "support_tree_angle":
+ {
+ "label": "Tree Support Branch Angle",
+ "description": "The angle of the branches. Use a lower angle to make them more vertical and more stable. Use a higher angle to be able to have more reach.",
+ "unit": "°",
+ "type": "float",
+ "minimum_value": "0",
+ "maximum_value": "90",
+ "maximum_value_warning": "60",
+ "default_value": 40,
+ "limit_to_extruder": "support_infill_extruder_nr",
+ "enabled": "support_tree_enable",
+ "settable_per_mesh": false,
+ "settable_per_extruder": true
+ },
+ "support_tree_branch_distance":
+ {
+ "label": "Tree Support Branch Distance",
+ "description": "How far apart the branches need to be when they touch the model. Making this distance small will cause the tree support to touch the model at more points, causing better overhang but making support harder to remove.",
+ "unit": "mm",
+ "type": "float",
+ "minimum_value": "0.001",
+ "default_value": 4,
+ "limit_to_extruder": "support_infill_extruder_nr",
+ "enabled": "support_tree_enable",
+ "settable_per_mesh": true
+ },
+ "support_tree_branch_diameter":
+ {
+ "label": "Tree Support Branch Diameter",
+ "description": "The diameter of the thinnest branches of tree support. Thicker branches are more sturdy. Branches towards the base will be thicker than this.",
+ "unit": "mm",
+ "type": "float",
+ "minimum_value": "0.001",
+ "minimum_value_warning": "support_line_width * 2",
+ "default_value": 2,
+ "limit_to_extruder": "support_infill_extruder_nr",
+ "enabled": "support_tree_enable",
+ "settable_per_mesh": false,
+ "settable_per_extruder": true
+ },
+ "support_tree_branch_diameter_angle":
+ {
+ "label": "Tree Support Branch Diameter Angle",
+ "description": "The angle of the branches' diameter as they gradually become thicker towards the bottom. An angle of 0 will cause the branches to have uniform thickness over their length. A bit of an angle can increase stability of the tree support.",
+ "unit": "°",
+ "type": "float",
+ "minimum_value": "0",
+ "maximum_value": "89.9999",
+ "maximum_value_warning": "15",
+ "default_value": 5,
+ "limit_to_extruder": "support_infill_extruder_nr",
+ "enabled": "support_tree_enable",
+ "settable_per_mesh": false,
+ "settable_per_extruder": true
+ },
+ "support_tree_collision_resolution":
+ {
+ "label": "Tree Support Collision Resolution",
+ "description": "Resolution to compute collisions with to avoid hitting the model. Setting this lower will produce more accurate trees that fail less often, but increases slicing time dramatically.",
+ "unit": "mm",
+ "type": "float",
+ "minimum_value": "0.001",
+ "minimum_value_warning": "support_line_width / 4",
+ "maximum_value_warning": "support_line_width * 2",
+ "default_value": 0.4,
+ "value": "support_line_width / 2",
+ "limit_to_extruder": "support_infill_extruder_nr",
+ "enabled": "support_tree_enable and support_tree_branch_diameter_angle > 0",
+ "settable_per_mesh": false,
+ "settable_per_extruder": true
+ },
+ "support_tree_wall_thickness":
+ {
+ "label": "Tree Support Wall Thickness",
+ "description": "The thickness of the walls of the branches of tree support. Thicker walls take longer to print but don't fall over as easily.",
+ "unit": "mm",
+ "type": "float",
+ "minimum_value": "0",
+ "minimum_value_warning": "wall_line_width",
+ "default_value": 0.8,
+ "value": "support_line_width",
+ "limit_to_extruder": "support_infill_extruder_nr",
+ "enabled": "support_tree_enable",
+ "settable_per_mesh": false,
+ "settable_per_extruder": true,
+ "children":
+ {
+ "support_tree_wall_count":
+ {
+ "label": "Tree Support Wall Line Count",
+ "description": "The number of walls of the branches of tree support. Thicker walls take longer to print but don't fall over as easily.",
+ "type": "int",
+ "minimum_value": "0",
+ "minimum_value_warning": "1",
+ "default_value": 1,
+ "value": "round(support_tree_wall_thickness / support_line_width)",
+ "limit_to_extruder": "support_infill_extruder_nr",
+ "enabled": "support_tree_enable",
+ "settable_per_mesh": false,
+ "settable_per_extruder": true
+ }
+ }
+ },
+ "slicing_tolerance":
+ {
+ "label": "Slicing Tolerance",
+ "description": "How to slice layers with diagonal surfaces. The areas of a layer can be generated based on where the middle of the layer intersects the surface (Middle). Alternatively each layer can have the areas which fall inside of the volume throughout the height of the layer (Exclusive) or a layer has the areas which fall inside anywhere within the layer (Inclusive). Exclusive retains the most details, Inclusive makes for the best fit and Middle takes the least time to process.",
+ "type": "enum",
+ "options":
+ {
+ "middle": "Middle",
+ "exclusive": "Exclusive",
+ "inclusive": "Inclusive"
+ },
+ "default_value": "middle",
+ "settable_per_mesh": true
+ },
+ "roofing_line_width":
+ {
+ "label": "Top Surface Skin Line Width",
+ "description": "Width of a single line of the areas at the top of the print.",
+ "unit": "mm",
+ "minimum_value": "0.001",
+ "minimum_value_warning": "0.1 + 0.4 * machine_nozzle_size",
+ "maximum_value_warning": "2 * machine_nozzle_size",
+ "default_value": 0.4,
+ "type": "float",
+ "value": "skin_line_width",
+ "limit_to_extruder": "roofing_extruder_nr",
+ "settable_per_mesh": true,
+ "enabled": "roofing_layer_count > 0 and top_layers > 0"
+ },
+ "roofing_pattern":
+ {
+ "label": "Top Surface Skin Pattern",
+ "description": "The pattern of the top most layers.",
+ "type": "enum",
+ "options":
+ {
+ "lines": "Lines",
+ "concentric": "Concentric",
+ "zigzag": "Zig Zag"
+ },
+ "default_value": "lines",
+ "value": "top_bottom_pattern",
+ "limit_to_extruder": "roofing_extruder_nr",
+ "settable_per_mesh": true,
+ "enabled": "roofing_layer_count > 0 and top_layers > 0"
+ },
+ "roofing_angles":
+ {
+ "label": "Top Surface Skin Line Directions",
+ "description": "A list of integer line directions to use when the top surface skin layers use the lines or zig zag pattern. 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 traditional default angles (45 and 135 degrees).",
+ "type": "[int]",
+ "default_value": "[ ]",
+ "value": "skin_angles",
+ "enabled": "roofing_pattern != 'concentric' and roofing_layer_count > 0 and top_layers > 0",
+ "limit_to_extruder": "roofing_extruder_nr",
+ "settable_per_mesh": true
+ },
+ "infill_enable_travel_optimization":
+ {
+ "label": "Infill Travel Optimization",
+ "description": "When enabled, the order in which the infill lines are printed is optimized to reduce the distance travelled. The reduction in travel time achieved very much depends on the model being sliced, infill pattern, density, etc. Note that, for some models that have many small areas of infill, the time to slice the model may be greatly increased.",
+ "type": "bool",
+ "default_value": false,
+ "settable_per_mesh": true
+ },
+ "material_flow_dependent_temperature":
+ {
+ "label": "Auto Temperature",
+ "description": "Change the temperature for each layer automatically with the average flow speed of that layer.",
+ "type": "bool",
+ "default_value": false,
+ "enabled": "machine_nozzle_temp_enabled and False",
+ "settable_per_mesh": false,
+ "settable_per_extruder": true
+ },
+ "material_flow_temp_graph":
+ {
+ "label": "Flow Temperature Graph",
+ "description": "Data linking material flow (in mm3 per second) to temperature (degrees Celsius).",
+ "unit": "[[mm³,°C]]",
+ "type": "str",
+ "default_value": "[[3.5,200],[7.0,240]]",
+ "enabled": "False and machine_nozzle_temp_enabled and material_flow_dependent_temperature",
+ "settable_per_mesh": false,
+ "settable_per_extruder": true
+ },
+ "meshfix_maximum_resolution":
+ {
+ "label": "Maximum Resolution",
+ "description": "The minimum size of a line segment after slicing. If you increase this, the mesh will have a lower resolution. This may allow the printer to keep up with the speed it has to process g-code and will increase slice speed by removing details of the mesh that it can't process anyway.",
+ "type": "float",
+ "unit": "mm",
+ "default_value": 0.01,
+ "minimum_value": "0.001",
+ "minimum_value_warning": "0.005",
+ "maximum_value_warning": "0.1",
+ "settable_per_mesh": true
+ },
"support_skip_some_zags":
{
"label": "Break Up Support In Chunks",
@@ -6188,6 +6320,258 @@
"settable_per_mesh": false,
"settable_per_extruder": false,
"settable_per_meshgroup": false
+ },
+ "bridge_settings_enabled":
+ {
+ "label": "Enable Bridge Settings",
+ "description": "Detect bridges and modify print speed, flow and fan settings while bridges are printed.",
+ "type": "bool",
+ "default_value": false,
+ "settable_per_mesh": true,
+ "settable_per_extruder": false,
+ "settable_per_meshgroup": false
+ },
+ "bridge_wall_min_length":
+ {
+ "label": "Minimum Bridge Wall Length",
+ "description": "Unsupported walls shorter than this will be printed using the normal wall settings. Longer unsupported walls will be printed using the bridge wall settings.",
+ "unit": "mm",
+ "type": "float",
+ "minimum_value": "0",
+ "default_value": 5,
+ "enabled": "bridge_settings_enabled",
+ "settable_per_mesh": false,
+ "settable_per_extruder": true
+ },
+ "bridge_skin_support_threshold":
+ {
+ "label": "Bridge Skin Support Threshold",
+ "description": "If a skin region is supported for less than this percentage of its area, print it using the bridge settings. Otherwise it is printed using the normal skin settings.",
+ "unit": "%",
+ "default_value": 50,
+ "type": "float",
+ "minimum_value": "0",
+ "maximum_value": "100",
+ "enabled": "bridge_settings_enabled",
+ "settable_per_mesh": true
+ },
+ "bridge_wall_max_overhang":
+ {
+ "label": "Bridge Wall Max Overhang",
+ "description": "The maximum allowed width of the region of air below a wall line before the wall is printed using bridge settings. Expressed as a percentage of the wall line width. When the air gap is wider than this, the wall line is printed using the bridge settings. Otherwise, the wall line is printed using the normal settings. The lower the value, the more likely it is that overhung wall lines will be printed using bridge settings.",
+ "unit": "%",
+ "default_value": 100,
+ "type": "float",
+ "minimum_value": "0",
+ "maximum_value": "100",
+ "enabled": "bridge_settings_enabled",
+ "settable_per_mesh": true
+ },
+ "bridge_wall_coast":
+ {
+ "label": "Bridge Wall Coasting",
+ "description": "This controls the distance the extruder should coast immediately before a bridge wall begins. Coasting before the bridge starts can reduce the pressure in the nozzle and may produce a flatter bridge.",
+ "unit": "%",
+ "default_value": 100,
+ "type": "float",
+ "minimum_value": "0",
+ "maximum_value": "500",
+ "enabled": "bridge_settings_enabled",
+ "settable_per_mesh": false
+ },
+ "bridge_wall_speed":
+ {
+ "label": "Bridge Wall Speed",
+ "description": "The speed at which the bridge walls are printed.",
+ "unit": "mm/s",
+ "type": "float",
+ "minimum_value": "cool_min_speed",
+ "maximum_value": "math.sqrt(machine_max_feedrate_x ** 2 + machine_max_feedrate_y ** 2)",
+ "maximum_value_warning": "300",
+ "default_value": 15,
+ "value": "max(cool_min_speed, speed_wall_0 / 2)",
+ "enabled": "bridge_settings_enabled",
+ "settable_per_mesh": true
+ },
+ "bridge_wall_material_flow":
+ {
+ "label": "Bridge Wall Flow",
+ "description": "When printing bridge walls, the amount of material extruded is multiplied by this value.",
+ "unit": "%",
+ "default_value": 50,
+ "type": "float",
+ "minimum_value": "5",
+ "minimum_value_warning": "50",
+ "maximum_value_warning": "150",
+ "enabled": "bridge_settings_enabled",
+ "settable_per_mesh": true
+ },
+ "bridge_skin_speed":
+ {
+ "label": "Bridge Skin Speed",
+ "description": "The speed at which bridge skin regions are printed.",
+ "unit": "mm/s",
+ "type": "float",
+ "minimum_value": "cool_min_speed",
+ "maximum_value": "math.sqrt(machine_max_feedrate_x ** 2 + machine_max_feedrate_y ** 2)",
+ "maximum_value_warning": "300",
+ "default_value": 15,
+ "value": "max(cool_min_speed, speed_topbottom / 2)",
+ "enabled": "bridge_settings_enabled",
+ "settable_per_mesh": true
+ },
+ "bridge_skin_material_flow":
+ {
+ "label": "Bridge Skin Flow",
+ "description": "When printing bridge skin regions, the amount of material extruded is multiplied by this value.",
+ "unit": "%",
+ "default_value": 60,
+ "type": "float",
+ "minimum_value": "5",
+ "minimum_value_warning": "50",
+ "maximum_value_warning": "150",
+ "enabled": "bridge_settings_enabled",
+ "settable_per_mesh": true
+ },
+ "bridge_skin_density":
+ {
+ "label": "Bridge Skin Density",
+ "description": "The density of the bridge skin layer. Values less than 100 will increase the gaps between the skin lines.",
+ "unit": "%",
+ "default_value": 100,
+ "type": "float",
+ "minimum_value": "5",
+ "maximum_value": "100",
+ "minimum_value_warning": "20",
+ "enabled": "bridge_settings_enabled",
+ "settable_per_mesh": true
+ },
+ "bridge_fan_speed":
+ {
+ "label": "Bridge Fan Speed",
+ "description": "Percentage fan speed to use when printing bridge walls and skin.",
+ "unit": "%",
+ "minimum_value": "0",
+ "maximum_value": "100",
+ "default_value": 100,
+ "type": "float",
+ "enabled": "bridge_settings_enabled",
+ "settable_per_mesh": true
+ },
+ "bridge_enable_more_layers":
+ {
+ "label": "Bridge Has Multiple Layers",
+ "description": "If enabled, the second and third layers above the air are printed using the following settings. Otherwise, those layers are printed using the normal settings.",
+ "type": "bool",
+ "default_value": true,
+ "enabled": "bridge_settings_enabled",
+ "settable_per_mesh": true
+ },
+ "bridge_skin_speed_2":
+ {
+ "label": "Bridge Second Skin Speed",
+ "description": "Print speed to use when printing the second bridge skin layer.",
+ "unit": "mm/s",
+ "type": "float",
+ "minimum_value": "cool_min_speed",
+ "maximum_value": "math.sqrt(machine_max_feedrate_x ** 2 + machine_max_feedrate_y ** 2)",
+ "maximum_value_warning": "300",
+ "default_value": 25,
+ "value": "bridge_skin_speed",
+ "enabled": "bridge_settings_enabled and bridge_enable_more_layers",
+ "settable_per_mesh": true
+ },
+ "bridge_skin_material_flow_2":
+ {
+ "label": "Bridge Second Skin Flow",
+ "description": "When printing the second bridge skin layer, the amount of material extruded is multiplied by this value.",
+ "unit": "%",
+ "default_value": 100,
+ "type": "float",
+ "minimum_value": "5",
+ "maximum_value": "500",
+ "minimum_value_warning": "50",
+ "maximum_value_warning": "150",
+ "enabled": "bridge_settings_enabled and bridge_enable_more_layers",
+ "settable_per_mesh": true
+ },
+ "bridge_skin_density_2":
+ {
+ "label": "Bridge Second Skin Density",
+ "description": "The density of the second bridge skin layer. Values less than 100 will increase the gaps between the skin lines.",
+ "unit": "%",
+ "default_value": 75,
+ "type": "float",
+ "minimum_value": "5",
+ "maximum_value": "100",
+ "minimum_value_warning": "20",
+ "enabled": "bridge_settings_enabled and bridge_enable_more_layers",
+ "settable_per_mesh": true
+ },
+ "bridge_fan_speed_2":
+ {
+ "label": "Bridge Second Skin Fan Speed",
+ "description": "Percentage fan speed to use when printing the second bridge skin layer.",
+ "unit": "%",
+ "minimum_value": "0",
+ "maximum_value": "100",
+ "default_value": 0,
+ "type": "float",
+ "enabled": "bridge_settings_enabled and bridge_enable_more_layers",
+ "settable_per_mesh": true
+ },
+ "bridge_skin_speed_3":
+ {
+ "label": "Bridge Third Skin Speed",
+ "description": "Print speed to use when printing the third bridge skin layer.",
+ "unit": "mm/s",
+ "type": "float",
+ "minimum_value": "cool_min_speed",
+ "maximum_value": "math.sqrt(machine_max_feedrate_x ** 2 + machine_max_feedrate_y ** 2)",
+ "maximum_value_warning": "300",
+ "default_value": 15,
+ "value": "bridge_skin_speed",
+ "enabled": "bridge_settings_enabled and bridge_enable_more_layers",
+ "settable_per_mesh": true
+ },
+ "bridge_skin_material_flow_3":
+ {
+ "label": "Bridge Third Skin Flow",
+ "description": "When printing the third bridge skin layer, the amount of material extruded is multiplied by this value.",
+ "unit": "%",
+ "default_value": 110,
+ "type": "float",
+ "minimum_value": "5",
+ "maximum_value": "500",
+ "minimum_value_warning": "50",
+ "maximum_value_warning": "150",
+ "enabled": "bridge_settings_enabled and bridge_enable_more_layers",
+ "settable_per_mesh": true
+ },
+ "bridge_skin_density_3":
+ {
+ "label": "Bridge Third Skin Density",
+ "description": "The density of the third bridge skin layer. Values less than 100 will increase the gaps between the skin lines.",
+ "unit": "%",
+ "default_value": 80,
+ "type": "float",
+ "minimum_value": "5",
+ "maximum_value": "100",
+ "minimum_value_warning": "20",
+ "enabled": "bridge_settings_enabled and bridge_enable_more_layers",
+ "settable_per_mesh": true
+ },
+ "bridge_fan_speed_3":
+ {
+ "label": "Bridge Third Skin Fan Speed",
+ "description": "Percentage fan speed to use when printing the third bridge skin layer.",
+ "unit": "%",
+ "minimum_value": "0",
+ "maximum_value": "100",
+ "default_value": 0,
+ "type": "float",
+ "enabled": "bridge_settings_enabled and bridge_enable_more_layers",
+ "settable_per_mesh": true
}
}
},
diff --git a/resources/definitions/gmax15plus.def.json b/resources/definitions/gmax15plus.def.json
new file mode 100644
index 0000000000..897d492bb2
--- /dev/null
+++ b/resources/definitions/gmax15plus.def.json
@@ -0,0 +1,52 @@
+{
+ "id": "gmax15plus",
+ "version": 2,
+ "name": "gMax 1.5 Plus",
+ "inherits": "fdmprinter",
+ "metadata": {
+ "visible": true,
+ "author": "gcreate",
+ "manufacturer": "gcreate",
+ "category": "Other",
+ "file_formats": "text/x-gcode",
+ "platform": "gmax_1-5_xt-plus_s3d_full model_150707.stl",
+ "has_machine_quality": true,
+ "has_variants": true,
+ "variants_name": "Hotend",
+ "preferred_variant_name": "0.5mm E3D (Default)"
+ },
+
+ "overrides": {
+ "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 },
+ "speed_print": { "default_value": 50 },
+ "speed_travel": { "default_value": 70 },
+ "machine_max_acceleration_x": { "default_value": 600 },
+ "machine_max_acceleration_y": { "default_value": 600 },
+ "machine_max_acceleration_z": { "default_value": 30 },
+ "machine_max_acceleration_e": { "default_value": 10000 },
+ "machine_max_jerk_xy": { "default_value": 8 },
+ "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_end_gcode": { "default_value": "M104 S0 ;extruder heater off\nM140 S0 ;heated bed heater off (if you have it)\nG91 ;relative positioning\nG1 E-1 F300 ;retract the filament a bit before lifting the nozzle, to release some of the pressure\nG1 Z+0.5 E-5 X-20 Y-20 F9000 ;move Z up a bit and retract filament even more\nG28 X0 Y0 ;move X/Y to min endstops, so the head is out of the way\nM84 ;steppers off\nG90 ;absolute positioning" },
+ "material_print_temperature": { "default_value": 202 },
+ "wall_thickness": { "default_value": 1 },
+ "top_bottom_thickness": { "default_value": 1 },
+ "bottom_thickness": { "default_value": 1 }
+ }
+}
diff --git a/resources/definitions/gmax15plus_dual.def.json b/resources/definitions/gmax15plus_dual.def.json
new file mode 100644
index 0000000000..8c57c8af63
--- /dev/null
+++ b/resources/definitions/gmax15plus_dual.def.json
@@ -0,0 +1,56 @@
+{
+ "id": "gmax15plus_dual",
+ "version": 2,
+ "name": "gMax 1.5 Plus Dual Extruder",
+ "inherits": "fdmprinter",
+ "metadata": {
+ "visible": true,
+ "author": "GTL_180109",
+ "manufacturer": "gCreate",
+ "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"
+ }
+ },
+
+ "overrides": {
+ "machine_name": { "default_value": "gMax 1.5 Plus Dual Extruder" },
+ "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 },
+ "speed_print": { "default_value": 50 },
+ "speed_travel": { "default_value": 70 },
+ "machine_max_acceleration_x": { "default_value": 600 },
+ "machine_max_acceleration_y": { "default_value": 600 },
+ "machine_max_acceleration_z": { "default_value": 30 },
+ "machine_max_acceleration_e": { "default_value": 10000 },
+ "machine_max_jerk_xy": { "default_value": 8 },
+ "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_end_gcode": { "default_value": "M104 S0 T0;Left extruder off\nM104 S0 T1; Right extruder off\nM140 S0 ;heated bed heater off (if you have it)\nG91 ;relative positioning\nG1 E-1 F300 ;retract the filament a bit before lifting the nozzle, to release some of the pressure\nG1 Z+0.5 E-5 X-20 Y-20 F9000 ;move Z up a bit and retract filament even more\nG28 X0 Y0 ;move X/Y to min endstops, so the head is out of the way\nM84 ;steppers off\nG90 ;absolute positioning" },
+ "material_print_temperature": { "default_value": 202 },
+ "wall_thickness": { "default_value": 1 },
+ "top_bottom_thickness": { "default_value": 1 },
+ "bottom_thickness": { "default_value": 1 }
+ }
+}
diff --git a/resources/definitions/imade3d_jellybox.def.json b/resources/definitions/imade3d_jellybox.def.json
index 11df730408..b234e4b2cd 100644
--- a/resources/definitions/imade3d_jellybox.def.json
+++ b/resources/definitions/imade3d_jellybox.def.json
@@ -9,9 +9,8 @@
"platform": "imade3d_jellybox_platform.stl",
"platform_offset": [ 0, -0.3, 0],
"file_formats": "text/x-gcode",
- "preferred_variant": "*0.4*",
- "preferred_material": "*generic_pla*",
- "preferred_quality": "*fast*",
+ "preferred_variant_name": "0.4 mm",
+ "preferred_quality_type": "fast",
"has_materials": true,
"has_variants": true,
"has_machine_materials": true,
diff --git a/resources/definitions/malyan_m180.def.json b/resources/definitions/malyan_m180.def.json
index 5e0a6038dd..c1a424f0c9 100644
--- a/resources/definitions/malyan_m180.def.json
+++ b/resources/definitions/malyan_m180.def.json
@@ -25,8 +25,7 @@
"default_value": true
},
"machine_nozzle_size": {
- "default_value": 0.4,
- "minimum_value": "0.001"
+ "default_value": 0.4
},
"machine_head_with_fans_polygon": {
"default_value": [
@@ -36,6 +35,21 @@
[ 18, 35 ]
]
},
+ "machine_max_feedrate_z": {
+ "default_value": 400
+ },
+ "steps_per_mm_x": {
+ "default_value": 93
+ },
+ "steps_per_mm_y": {
+ "default_value": 93
+ },
+ "steps_per_mm_z": {
+ "default_value": 1600
+ },
+ "steps_per_mm_e": {
+ "default_value": 92
+ },
"gantry_height": {
"default_value": 55
},
diff --git a/resources/definitions/malyan_m200.def.json b/resources/definitions/malyan_m200.def.json
index 9aae3a5244..a3f4f81ecf 100644
--- a/resources/definitions/malyan_m200.def.json
+++ b/resources/definitions/malyan_m200.def.json
@@ -11,7 +11,7 @@
"platform": "malyan_m200_platform.stl",
"has_machine_quality": true,
"has_materials": true,
- "preferred_quality": "*normal*",
+ "preferred_quality_type": "normal",
"supports_usb_connection": true,
"visible": true,
"first_start_actions": ["MachineSettingsAction"],
@@ -51,7 +51,7 @@
"machine_height": { "default_value": 120 },
"machine_heated_bed": { "default_value": true },
"machine_center_is_zero": { "default_value": false },
- "material_diameter": { "value": 1.75 },
+ "material_diameter": { "default_value": 1.75 },
"machine_nozzle_size": {
"default_value": 0.4,
"minimum_value": 0.15
diff --git a/resources/definitions/monoprice_select_mini_v2.def.json b/resources/definitions/monoprice_select_mini_v2.def.json
index 87014c136b..99bb7ef50a 100644
--- a/resources/definitions/monoprice_select_mini_v2.def.json
+++ b/resources/definitions/monoprice_select_mini_v2.def.json
@@ -10,7 +10,7 @@
"file_formats": "text/x-gcode",
"has_machine_quality": true,
"has_materials": true,
- "preferred_quality": "*normal*",
+ "preferred_quality_type": "normal",
"visible": true
},
diff --git a/resources/definitions/peopoly_moai.def.json b/resources/definitions/peopoly_moai.def.json
index 78aca31dae..5a3cbddd14 100644
--- a/resources/definitions/peopoly_moai.def.json
+++ b/resources/definitions/peopoly_moai.def.json
@@ -136,7 +136,7 @@
},
"material_diameter": {
"enabled": false,
- "value": "1.75"
+ "default_value": 1.75
},
"cool_fan_enabled": {
"enabled": false,
diff --git a/resources/definitions/printrbot_simple_makers_kit.def.json b/resources/definitions/printrbot_simple_makers_kit.def.json
new file mode 100644
index 0000000000..e2afd57826
--- /dev/null
+++ b/resources/definitions/printrbot_simple_makers_kit.def.json
@@ -0,0 +1,38 @@
+{
+ "version": 2,
+ "name": "Printrbot Simple Maker's Kit (1405)",
+ "inherits": "fdmprinter",
+ "metadata": {
+ "visible": true,
+ "author": "Timur Tabi",
+ "manufacturer": "Printrbot",
+ "file_formats": "text/x-gcode"
+ },
+
+ "overrides": {
+ "machine_name": { "default_value": "Printrbot Simple Maker's Kit (1405)" },
+ "machine_heated_bed": { "default_value": false },
+ "machine_width": { "default_value": 100 },
+ "machine_depth": { "default_value": 100 },
+ "machine_height": { "default_value": 115 },
+ "material_diameter": { "default_value": 1.75 },
+ "machine_nozzle_size": { "default_value": 0.4 },
+ "machine_head_with_fans_polygon": {
+ "default_value": [
+ [-40, 1000],
+ [-40, -10],
+ [60, 1000],
+ [60, -10]
+ ]
+ },
+ "gantry_height": { "default_value": 1000 },
+ "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 ;home X/Y\nG28 Z0 ;home Z\nG92 E0 ;zero the extruded length\nG29 ;initiate auto bed leveling sequence"
+ },
+ "machine_end_gcode": {
+ "default_value": "M104 S0 ;extruder heater off\nM140 S0 ;heated bed heater off (if you have it)\nM106 S0 ;fan off\nG91 ;relative positioning\nG1 E-1 F300 ;retract the filament a bit\nG1 Z+1 E-5 F9000 ;move Z up a bit and retract even more\nG28 X0 Y0 ;home X/Y, so the head is out of the way\nM84 ;steppers off\nG90 ;absolute positioning"
+ }
+ }
+}
diff --git a/resources/definitions/seemecnc_artemis.def.json b/resources/definitions/seemecnc_artemis.def.json
new file mode 100644
index 0000000000..88a1b28de6
--- /dev/null
+++ b/resources/definitions/seemecnc_artemis.def.json
@@ -0,0 +1,43 @@
+{
+ "version": 2,
+ "name": "SeeMeCNC Artemis",
+ "inherits": "fdmprinter",
+ "metadata": {
+ "visible": true,
+ "author": "PouncingIguana, JJ",
+ "manufacturer": "SeeMeCNC",
+ "file_formats": "text/x-gcode",
+ "icon": "icon_ultimaker2",
+ "platform": "artemis_platform.stl",
+ "has_materials": true
+ },
+
+ "overrides": {
+ "layer_height": { "default_value": 0.1618 },
+ "layer_height_0": { "default_value": 0.2 },
+ "machine_center_is_zero": { "default_value": true },
+ "machine_depth": { "default_value": 290 },
+ "machine_gcode_flavor": { "default_value": "RepRap (RepRap)" },
+ "machine_heated_bed": { "default_value": true },
+ "machine_height": { "default_value": 530 },
+ "machine_max_feedrate_z": { "default_value": 400 },
+ "machine_name": { "default_value": "Artemis" },
+ "machine_nozzle_size": { "default_value": 0.5 },
+ "machine_shape": { "default_value": "elliptic" },
+ "machine_width": { "default_value": 290 },
+ "relative_extrusion": { "default_value": false },
+ "retraction_amount": { "default_value": 3.2 },
+ "retraction_combing": { "default_value": "off" },
+ "retraction_hop_enabled": { "default_value": true },
+ "retraction_hop_only_when_collides": { "default_value": false },
+ "retraction_prime_speed": { "default_value": 45 },
+ "retraction_retract_speed": { "default_value": 45 },
+ "retraction_speed": { "default_value": 45 },
+ "machine_start_gcode": {
+ "default_value": "G28\nG1 Z15.0 F10000\nG92 E0"
+ },
+ "machine_end_gcode": {
+ "default_value": "M203 Z24000\nM104 S0\nM140 S0\nM107\nG28\nM84"
+ }
+ }
+}
diff --git a/resources/definitions/seemecnc_v32.def.json b/resources/definitions/seemecnc_v32.def.json
new file mode 100644
index 0000000000..5932403bc5
--- /dev/null
+++ b/resources/definitions/seemecnc_v32.def.json
@@ -0,0 +1,43 @@
+{
+ "version": 2,
+ "name": "SeeMeCNC Rostock Max V3.2",
+ "inherits": "fdmprinter",
+ "metadata": {
+ "visible": true,
+ "author": "PouncingIguana, JJ",
+ "manufacturer": "SeeMeCNC",
+ "file_formats": "text/x-gcode",
+ "icon": "icon_ultimaker2",
+ "platform": "rostock_platform.stl",
+ "has_materials": true
+ },
+
+ "overrides": {
+ "layer_height": { "default_value": 0.1618 },
+ "layer_height_0": { "default_value": 0.2 },
+ "machine_center_is_zero": { "default_value": true },
+ "machine_depth": { "default_value": 265 },
+ "machine_gcode_flavor": { "default_value": "RepRap (RepRap)" },
+ "machine_heated_bed": { "default_value": true },
+ "machine_height": { "default_value": 395 },
+ "machine_max_feedrate_z": { "default_value": 300 },
+ "machine_name": { "default_value": "Rostock Max V3.2" },
+ "machine_nozzle_size": { "default_value": 0.5 },
+ "machine_shape": { "default_value": "elliptic" },
+ "machine_width": { "default_value": 265 },
+ "relative_extrusion": { "default_value": false },
+ "retraction_amount": { "default_value": 3.2 },
+ "retraction_combing": { "default_value": "off" },
+ "retraction_hop_enabled": { "default_value": true },
+ "retraction_hop_only_when_collides": { "default_value": false },
+ "retraction_prime_speed": { "default_value": 45 },
+ "retraction_retract_speed": { "default_value": 45 },
+ "retraction_speed": { "default_value": 45 },
+ "machine_start_gcode": {
+ "default_value": "G28\nG1 Z15.0 F10000\nG92 E0"
+ },
+ "machine_end_gcode": {
+ "default_value": "M203 Z24000\nM104 S0\nM140 S0\nM107\nG28\nM84"
+ }
+ }
+}
diff --git a/resources/definitions/tevo_blackwidow.def.json b/resources/definitions/tevo_blackwidow.def.json
index 04cadfb160..22f7095e17 100644
--- a/resources/definitions/tevo_blackwidow.def.json
+++ b/resources/definitions/tevo_blackwidow.def.json
@@ -11,7 +11,7 @@
"has_materials": false,
"has_machine_quality": true,
"platform": "tevo_blackwidow.stl",
- "preferred_quality": "*normal*"
+ "preferred_quality_type": "normal"
},
"overrides":
{
diff --git a/resources/definitions/tevo_tarantula.def.json b/resources/definitions/tevo_tarantula.def.json
index a9f9cefff2..c3bfb38192 100644
--- a/resources/definitions/tevo_tarantula.def.json
+++ b/resources/definitions/tevo_tarantula.def.json
@@ -2,7 +2,8 @@
"version": 2,
"name": "Tevo Tarantula",
"inherits": "fdmprinter",
- "metadata": {
+ "metadata":
+ {
"visible": true,
"author": "TheAssassin",
"manufacturer": "Tevo",
@@ -11,62 +12,39 @@
"platform": "prusai3_platform.stl"
},
- "overrides": {
- "machine_name": {
- "default_value": "Tevo Tarantula"
- },
- "machine_heated_bed": {
- "default_value": true
- },
- "machine_width": {
- "default_value": 200
- },
- "machine_height": {
- "default_value": 200
- },
- "machine_depth": {
- "default_value": 200
- },
- "machine_center_is_zero": {
- "default_value": false
- },
- "machine_nozzle_size": {
- "default_value": 0.4
- },
- "material_diameter": {
- "default_value": 1.75
- },
- "machine_head_polygon": {
- "default_value": [
+ "overrides":
+ {
+ "machine_name": { "default_value": "Tevo Tarantula" },
+ "machine_heated_bed": { "default_value": true },
+ "machine_width": { "default_value": 200 },
+ "machine_height": { "default_value": 200 },
+ "machine_depth": { "default_value": 200 },
+ "machine_center_is_zero": { "default_value": false },
+ "machine_nozzle_size": { "default_value": 0.4 },
+ "material_diameter": { "default_value": 1.75 },
+ "machine_head_polygon":
+ {
+ "default_value":
+ [
[-75, -18],
[-75, 35],
[18, 35],
[18, -18]
]
},
- "gantry_height": {
- "default_value": 55
- },
- "machine_gcode_flavor": {
- "default_value": "RepRap (Marlin/Sprinter)"
- },
- "machine_acceleration": {
- "default_value": 500
- },
- "machine_max_jerk_xy": {
- "default_value": 4.0
- },
- "machine_max_jerk_z": {
- "default_value": 0.2
- },
- "machine_max_jerk_e": {
- "default_value": 2.5
- },
- "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..."
- },
- "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\nG90 ;absolute positioning\nG1 X0 Y200 F3600 ;move extruder out of the way by moving the baseplate to the front for easier access to printed object\nM84 ;steppers off"
- }
+ "gantry_height": { "default_value": 55 },
+ "machine_gcode_flavor": { "default_value": "RepRap (Marlin/Sprinter)" },
+ "machine_acceleration": { "default_value": 2650 },
+ "machine_max_jerk_xy": { "default_value": 15.0 },
+ "machine_max_jerk_z": { "default_value": 0.4 },
+ "machine_max_jerk_e": { "default_value": 5 },
+ "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_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..." },
+ "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\nG90 ;absolute positioning\nG1 X0 Y200 F3600 ;move extruder out of the way by moving the baseplate to the front for easier access to printed object\nM84 ;steppers off" }
}
}
diff --git a/resources/definitions/ubuild-3d_mr_bot_280.def.json b/resources/definitions/ubuild-3d_mr_bot_280.def.json
new file mode 100644
index 0000000000..4febdcd350
--- /dev/null
+++ b/resources/definitions/ubuild-3d_mr_bot_280.def.json
@@ -0,0 +1,49 @@
+{
+ "id": "ubuild-3d_mr_bot_280",
+ "version": 2,
+ "name": "uBuild-3D Mr Bot 280",
+ "inherits": "fdmprinter",
+ "metadata": {
+ "visible": true,
+ "author": "uBuild-3D",
+ "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"
+ },
+
+ "overrides": {
+ "machine_name": { "default_value": "Mr Bot 280" },
+ "machine_heated_bed": { "default_value": true },
+ "machine_width": { "default_value": 275 },
+ "machine_height": { "default_value": 275 },
+ "machine_depth": { "default_value": 275 },
+ "machine_center_is_zero": { "default_value": false },
+ "material_diameter": { "default_value": 1.75 },
+ "material_bed_temperature": { "default_value": 70 },
+ "machine_nozzle_size": { "default_value": 0.4 },
+ "layer_height_0": { "default_value": 0.1 },
+ "retraction_amount": { "default_value": 2 },
+ "retraction_speed": { "default_value": 50 },
+ "retraction_retract_speed": { "default_value": 50 },
+ "retraction_prime_speed": { "default_value": 30 },
+ "adhesion_type": { "default_value": "skirt" },
+ "machine_nozzle_heat_up_speed": { "default_value": 2 },
+ "machine_nozzle_cool_down_speed": { "default_value": 2 },
+ "machine_head_with_fans_polygon": { "default_value": [[-20,20],[10,10],[10,10],[10,10]] },
+ "gantry_height": { "default_value": 275 },
+ "machine_max_feedrate_z": { "default_value": 15 },
+ "machine_max_feedrate_e": { "default_value": 60 },
+ "machine_max_acceleration_z": { "default_value": 1000 },
+ "machine_acceleration": { "default_value": 2000 },
+ "machine_max_jerk_xy": { "default_value": 20 },
+ "machine_max_jerk_z": { "default_value": 0.4 },
+ "machine_max_jerk_e": { "default_value": 5 },
+ "machine_gcode_flavor": { "default_value": "RepRap (Marlin/Sprinter)" },
+ "machine_start_gcode": { "default_value": "G21 ; set units to millimeters\nG90 ; use absolute positioning\nM82 ; absolute extrusion mode\nM140 S{material_bed_temperature} ; set bed temp\nM104 S{material_print_temperature} ; set extruder temp\nG28 ; home X, Y and Z\nG29 ; probe sequence (for auto-leveling)\nG1 Z15 F600 ; go to Z15 position\nG1 X0 Y-20 F10000 ; go to X0 Y-20 position\nM190 S{material_bed_temperature} ; wait for bed temp\nM109 S{material_print_temperature} ; wait for extruder temp\nG92 E0 ; reset extruder distance position\nG1 E25 F100 ; extrude 25mm of material\nG92 E0 ; reset extruder distance position\nM117 Printing..." },
+ "machine_end_gcode": { "default_value": "M400 ; wait for moves to finish\nG92 Z0 E0 ; reset Z position\nG1 E-2 F9000 ; retract material\nG1 Z2 ; get extruder out of the way\nM104 S0 ; turn off extruder\nG1 Y285 F3000 ; present finished print\nM140 S0 ; turn off bed\nM84 ; disable motors\nM117 Print complete" }
+ }
+}
diff --git a/resources/definitions/ultimaker2.def.json b/resources/definitions/ultimaker2.def.json
index 038071574f..33b48116be 100644
--- a/resources/definitions/ultimaker2.def.json
+++ b/resources/definitions/ultimaker2.def.json
@@ -20,12 +20,10 @@
"overrides": {
"machine_name": { "default_value": "Ultimaker 2" },
"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\\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": "",
- "value": "\"\" if machine_gcode_flavor == \"UltiGCode\" else \"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\""
+ "value": "\";Version _2.6 of the firmware can abort the print too early if the file ends\\n;too soon. However if the file hasn't ended yet because there are comments at\\n;the end of the file, it won't abort yet. Therefore we have to put at least 512\\n;bytes at the end of the g-code so that the file is not yet finished by the\\n;time that the motion planner gets flushed. With firmware version _3.3 this\\n;should be fixed, so this comment wouldn't be necessary any more. Now we have\\n;to pad this text to make precisely 512 bytes.\" if machine_gcode_flavor == \"UltiGCode\" else \"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\\n;Version _2.6 of the firmware can abort the print too early if the file ends\\n;too soon. However if the file hasn't ended yet because there are comments at\\n;the end of the file, it won't abort yet. Therefore we have to put at least 512\\n;bytes at the end of the g-code so that the file is not yet finished by the\\n;time that the motion planner gets flushed. With firmware version _3.3 this\\n;should be fixed, so this comment wouldn't be necessary any more. Now we have\\n;to pad this text to make precisely 512 bytes.\""
},
"machine_width": {
"default_value": 223
diff --git a/resources/definitions/ultimaker2_plus.def.json b/resources/definitions/ultimaker2_plus.def.json
index 58833904d2..935bf5b6c0 100644
--- a/resources/definitions/ultimaker2_plus.def.json
+++ b/resources/definitions/ultimaker2_plus.def.json
@@ -9,7 +9,7 @@
"file_formats": "text/x-gcode",
"platform": "ultimaker2_platform.obj",
"platform_texture": "Ultimaker2Plusbackplate.png",
- "preferred_variant": "*0.4*",
+ "preferred_variant_name": "0.4 mm",
"has_variants": true,
"has_materials": true,
"has_machine_materials": true,
diff --git a/resources/definitions/ultimaker3.def.json b/resources/definitions/ultimaker3.def.json
index e7b9b6255e..57cfbe960f 100644
--- a/resources/definitions/ultimaker3.def.json
+++ b/resources/definitions/ultimaker3.def.json
@@ -15,8 +15,8 @@
"has_machine_materials": true,
"has_variant_materials": true,
"has_variants": true,
- "preferred_variant": "*aa04*",
- "preferred_quality": "*Normal*",
+ "preferred_variant_name": "AA 0.4",
+ "preferred_quality_type": "normal",
"variants_name": "Print core",
"machine_extruder_trains":
{
@@ -43,10 +43,10 @@
{
"default_value":
[
- [ -29, 6.1 ],
- [ -29, -33.9 ],
- [ 71, 6.1 ],
- [ 71, -33.9 ]
+ [ -41.9, -45.8 ],
+ [ -41.9, 33.9 ],
+ [ 59.9, 33.9 ],
+ [ 59.9, -45.8 ]
]
},
"machine_gcode_flavor": { "default_value": "Griffin" },
@@ -90,6 +90,7 @@
"infill_overlap": { "value": "0" },
"infill_pattern": { "value": "'triangles'" },
"infill_wipe_dist": { "value": "0" },
+ "initial_layer_line_width_factor": { "value": "120" },
"jerk_enabled": { "value": "True" },
"jerk_layer_0": { "value": "jerk_topbottom" },
"jerk_prime_tower": { "value": "math.ceil(jerk_print * 15 / 25)" },
@@ -109,7 +110,9 @@
"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 },
"raft_airgap": { "value": "0" },
"raft_base_thickness": { "value": "0.3" },
@@ -123,7 +126,7 @@
"retraction_count_max": { "value": "10" },
"retraction_extrusion_window": { "value": "1" },
"retraction_hop": { "value": "2" },
- "retraction_hop_enabled": { "value": "True" },
+ "retraction_hop_enabled": { "value": "extruders_enabled_count > 1" },
"retraction_hop_only_when_collides": { "value": "True" },
"retraction_min_travel": { "value": "5" },
"retraction_prime_speed": { "value": "15" },
@@ -147,9 +150,10 @@
"switch_extruder_prime_speed": { "value": "15" },
"switch_extruder_retraction_amount": { "value": "8" },
"top_bottom_thickness": { "value": "1" },
- "travel_avoid_distance": { "value": "3" },
+ "travel_avoid_distance": { "value": "3 if extruders_enabled_count > 1 else machine_nozzle_tip_outer_diameter / 2 * 1.5" },
"wall_0_inset": { "value": "0" },
"wall_line_width_x": { "value": "round(wall_line_width * 0.3 / 0.35, 2)" },
- "wall_thickness": { "value": "1" }
+ "wall_thickness": { "value": "1" },
+ "zig_zaggify_infill": { "value": "True" }
}
}
diff --git a/resources/definitions/ultimaker3_extended.def.json b/resources/definitions/ultimaker3_extended.def.json
index 385199f4f1..3a1be3a303 100644
--- a/resources/definitions/ultimaker3_extended.def.json
+++ b/resources/definitions/ultimaker3_extended.def.json
@@ -16,7 +16,7 @@
"has_variant_materials": true,
"has_materials": true,
"has_variants": true,
- "preferred_variant": "*aa04*",
+ "preferred_variant_name": "AA 0.4",
"variants_name": "Print core",
"machine_extruder_trains":
{
diff --git a/resources/definitions/vertex_delta_k8800.def.json b/resources/definitions/vertex_delta_k8800.def.json
index 736d17e17a..495fd5a5bc 100644
--- a/resources/definitions/vertex_delta_k8800.def.json
+++ b/resources/definitions/vertex_delta_k8800.def.json
@@ -6,7 +6,9 @@
"manufacturer": "Velleman nv",
"file_formats": "text/x-gcode",
"visible": true,
- "author": "Velleman"
+ "author": "Velleman",
+ "has_machine_quality": true,
+ "has_materials": true
},
"overrides": {
"material_diameter": {
@@ -59,6 +61,99 @@
},
"machine_end_gcode": {
"default_value": "; Vertex Delta end code\nM107 ; Turn off fan\nG91 ; Relative positioning\nT0\nG1 E-1 F1500; Reduce filament pressure\nM104 T0 S0\nG90 ; Absolute positioning\nG92 E0 ; Reset extruder position\nM300 S4000 P500\nM300 S3000 P500\nM300 S2000 P800\nG28\nM84 ; 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
+ },
+ "speed_print": {
+ "value": 35
+ },
+ "speed_infill": {
+ "value": 40
+ },
+ "speed_wall": {
+ "value": 35
+ },
+ "speed_wall_x": {
+ "value": 35
+ },
+ "speed_topbottom": {
+ "value": 35
+ },
+ "speed_travel": {
+ "value": 190
+ },
+ "speed_layer_0": {
+ "value": 20
+ },
+ "speed_print_layer_0": {
+ "value": 20
+ },
+ "skirt_brim_speed": {
+ "value": 20
+ },
+ "travel_retract_before_outer_wall": {
+ "value": false
+ },
+ "retraction_hop_enabled": {
+ "value": true
+ },
+ "retraction_hop": {
+ "value": 0.1
+ },
+ "cool_fan_full_at_height": {
+ "value": 2
+ },
+ "cool_fan_full_layer": {
+ "value": 11
+ },
+ "cool_min_layer_time": {
+ "value": 8
+ },
+ "support_z_distance": {
+ "value": 0.4
+ },
+ "support_xy_distance": {
+ "value": 1
+ },
+ "brim_width": {
+ "value": 6
+ },
+ "skirt_line_count": {
+ "value": 2
+ },
+ "skirt_brim_minimal_length": {
+ "value": 50
}
}
}
\ No newline at end of file
diff --git a/resources/extruders/cartesio_extruder_0.def.json b/resources/extruders/cartesio_extruder_0.def.json
index 5558d9325e..47b5b5abf5 100644
--- a/resources/extruders/cartesio_extruder_0.def.json
+++ b/resources/extruders/cartesio_extruder_0.def.json
@@ -16,17 +16,10 @@
"machine_nozzle_offset_x": { "default_value": 0.0 },
"machine_nozzle_offset_y": { "default_value": 0.0 },
"machine_extruder_start_code": {
- "default_value": "\n;start extruder_0\n\nM117 printing...\n"
+ "default_value": "\n;start T0\n\nM104 T0 S{material_print_temperature_layer_0}\nG1 X65 Y35 F9000 ; go to wipe position\nM109 T0 S{material_print_temperature_layer_0}; wait for temp\nG1 E10 F300; prime\nG92 E0\nG1 X45 Y15 F3000; wipe\nG1 X55 F9000\nG1 Y35 F6000; wipe again\n\nM117 printing...\n"
},
"machine_extruder_end_code": {
- "default_value": "\nM104 T0 S120\n;end extruder_0\nM117 temp is {material_print_temp}\n"
- },
-
- "machine_extruder_start_pos_abs": { "default_value": true },
- "machine_extruder_start_pos_x": { "default_value": 24 },
- "machine_extruder_start_pos_y": { "default_value": 16 },
- "machine_extruder_end_pos_abs": { "default_value": true },
- "machine_extruder_end_pos_x": { "default_value": 48 },
- "machine_extruder_end_pos_y": { "default_value": 16 }
+ "default_value": "\nM104 T0 S{material_standby_temperature}\nG1 X65 Y35 F9000 ; go to wipe position\nM109 T0 R{material_standby_temperature}; wait for temp\nG1 X45 Y15 F3000; wipe\nG1 X55 F9000\nG1 Y35 F6000; wipe again\n\n;end T0\n\n"
+ }
}
}
diff --git a/resources/extruders/cartesio_extruder_1.def.json b/resources/extruders/cartesio_extruder_1.def.json
index f8350f8091..78bcccd12a 100644
--- a/resources/extruders/cartesio_extruder_1.def.json
+++ b/resources/extruders/cartesio_extruder_1.def.json
@@ -16,17 +16,10 @@
"machine_nozzle_offset_x": { "default_value": 24.0 },
"machine_nozzle_offset_y": { "default_value": 0.0 },
"machine_extruder_start_code": {
- "default_value": "\n;start extruder_1\n\nM117 printing...\n"
+ "default_value": "\n;start T1\n\nM104 T1 S{material_print_temperature_layer_0}\nG1 X41 Y35 F9000 ; go to wipe position\nM109 T1 S{material_print_temperature_layer_0}; wait for temp\nG1 E10 F300; prime\nG92 E0\nG1 X21 Y15 F3000; wipe\nG1 X34 F9000\nG1 Y35 F6000; wipe again\n\nM117 printing...\n"
},
"machine_extruder_end_code": {
- "default_value": "\nM104 T1 S120\n;end extruder_1\n"
- },
-
- "machine_extruder_start_pos_abs": { "default_value": true },
- "machine_extruder_start_pos_x": { "default_value": 48 },
- "machine_extruder_start_pos_y": { "default_value": 16 },
- "machine_extruder_end_pos_abs": { "default_value": true },
- "machine_extruder_end_pos_x": { "default_value": 24 },
- "machine_extruder_end_pos_y": { "default_value": 16 }
+ "default_value": "\nM104 T1 S{material_standby_temperature}\nG1 X41 Y35 F9000 ; go to wipe position\nM109 T1 R{material_standby_temperature}; wait for temp\nG1 X21 Y15 F3000; wipe\nG1 X31 F9000\nG1 Y35 F6000; wipe again\n\n;end T1\n\n"
+ }
}
}
diff --git a/resources/extruders/cartesio_extruder_2.def.json b/resources/extruders/cartesio_extruder_2.def.json
index bfc10e75c3..dbd6643bfe 100644
--- a/resources/extruders/cartesio_extruder_2.def.json
+++ b/resources/extruders/cartesio_extruder_2.def.json
@@ -13,20 +13,13 @@
"default_value": 2,
"maximum_value": "3"
},
- "machine_nozzle_offset_x": { "default_value": 0.0 },
- "machine_nozzle_offset_y": { "default_value": 0.0 },
+ "machine_nozzle_offset_x": { "default_value": 24.0 },
+ "machine_nozzle_offset_y": { "default_value": -100.0 },
"machine_extruder_start_code": {
- "default_value": "\n;start extruder_2\n\nM117 printing...\n"
+ "default_value": "\n;start T2\n\nM104 T2 S{material_print_temperature_layer_0}\nG1 X41 Y215 F9000 ; go to wipe position\nM109 T2 S{material_print_temperature_layer_0}; wait for temp\nG1 E10 F300; prime\nG92 E0\nG1 X21 Y235 F3000; wipe\nG1 X31 F9000\nG1 Y215 F6000; wipe again\n\nM117 printing...\n"
},
"machine_extruder_end_code": {
- "default_value": "\nM104 T2 S120\n;end extruder_2\n"
- },
-
- "machine_extruder_start_pos_abs": { "default_value": true },
- "machine_extruder_start_pos_x": { "default_value": 24 },
- "machine_extruder_start_pos_y": { "default_value": 309 },
- "machine_extruder_end_pos_abs": { "default_value": true },
- "machine_extruder_end_pos_x": { "default_value": 48 },
- "machine_extruder_end_pos_y": { "default_value": 309 }
+ "default_value": "\nM104 T2 S{material_standby_temperature}\nG1 X41 Y215 F9000 ; go to wipe position\nM109 T2 R{material_standby_temperature}; wait for temp\nG1 X21 Y235 F3000; wipe\nG1 X31 F9000\nG1 Y215 F6000; wipe again\n\n;end T2\n\n"
+ }
}
}
diff --git a/resources/extruders/cartesio_extruder_3.def.json b/resources/extruders/cartesio_extruder_3.def.json
index f0be53e564..beed117abe 100644
--- a/resources/extruders/cartesio_extruder_3.def.json
+++ b/resources/extruders/cartesio_extruder_3.def.json
@@ -14,19 +14,12 @@
"maximum_value": "3"
},
"machine_nozzle_offset_x": { "default_value": 0.0 },
- "machine_nozzle_offset_y": { "default_value": 0.0 },
+ "machine_nozzle_offset_y": { "default_value": -100.0 },
"machine_extruder_start_code": {
- "default_value": "\n;start extruder_3\n\nM117 printing...\n"
+ "default_value": "\n;start T3\n\nM104 T3 S{material_print_temperature_layer_0}\nG1 X65 Y215 F9000 ; go to wipe position\nM109 T3 S{material_print_temperature_layer_0}; wait for temp\nG1 E10 F300; prime\nG92 E0\nG1 X45 Y235 F3000; wipe\nG1 X55 F9000\nG1 Y215 F6000; wipe again\n\nM117 printing...\n"
},
"machine_extruder_end_code": {
- "default_value": "\nM104 T3 S120\n;end extruder_3\n"
- },
-
- "machine_extruder_start_pos_abs": { "default_value": true },
- "machine_extruder_start_pos_x": { "default_value": 48 },
- "machine_extruder_start_pos_y": { "default_value": 309 },
- "machine_extruder_end_pos_abs": { "default_value": true },
- "machine_extruder_end_pos_x": { "default_value": 24 },
- "machine_extruder_end_pos_y": { "default_value": 309}
+ "default_value": "\nM104 T3 S{material_standby_temperature}\nG1 X65 Y215 F9000 ; go to wipe position\nM109 T3 R{material_standby_temperature}; wait for temp\nG1 X45 Y235 F3000; wipe\nG1 X55 F9000\nG1 Y215 F6000; wipe again\n\n;end T3\n\n"
+ }
}
}
diff --git a/resources/extruders/gmax15plus_dual_extruder_0.def.json b/resources/extruders/gmax15plus_dual_extruder_0.def.json
new file mode 100644
index 0000000000..0037b75a1c
--- /dev/null
+++ b/resources/extruders/gmax15plus_dual_extruder_0.def.json
@@ -0,0 +1,28 @@
+{
+ "id": "gmax15plus_dual_extruder_0",
+ "version": 2,
+ "name": "Left Extruder",
+ "inherits": "fdmextruder",
+ "metadata": {
+ "machine": "gmax15plus_dual",
+ "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.5 },
+
+ "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 },
+ "machine_extruder_end_pos_x": { "value": 40 },
+ "machine_extruder_end_pos_y": { "value": 210 }
+
+ }
+}
diff --git a/resources/extruders/gmax15plus_dual_extruder_1.def.json b/resources/extruders/gmax15plus_dual_extruder_1.def.json
new file mode 100644
index 0000000000..2db9aef3ee
--- /dev/null
+++ b/resources/extruders/gmax15plus_dual_extruder_1.def.json
@@ -0,0 +1,30 @@
+{
+ "id": "gmax15plus_dual_extruder_1",
+ "version": 2,
+ "name": "Right Extruder",
+ "inherits": "fdmextruder",
+ "metadata": {
+ "machine": "gmax15plus_dual",
+ "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 },
+ "machine_nozzle_size": { "default_value": 0.5 },
+
+ "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 },
+ "machine_extruder_end_pos_x": { "value": 40 },
+ "machine_extruder_end_pos_y": { "value": 210 }
+
+ }
+}
+
+
diff --git a/resources/extruders/punchtec_connect_xl_extruder_left.def.json b/resources/extruders/punchtec_connect_xl_extruder_0.def.json
similarity index 100%
rename from resources/extruders/punchtec_connect_xl_extruder_left.def.json
rename to resources/extruders/punchtec_connect_xl_extruder_0.def.json
diff --git a/resources/extruders/punchtec_connect_xl_extruder_right.def.json b/resources/extruders/punchtec_connect_xl_extruder_1.def.json
similarity index 100%
rename from resources/extruders/punchtec_connect_xl_extruder_right.def.json
rename to resources/extruders/punchtec_connect_xl_extruder_1.def.json
diff --git a/resources/i18n/cura.pot b/resources/i18n/cura.pot
index be6613ebf5..1620e11d81 100644
--- a/resources/i18n/cura.pot
+++ b/resources/i18n/cura.pot
@@ -1,14 +1,14 @@
# Cura
-# Copyright (C) 2017 Ultimaker
+# Copyright (C) 2018 Ultimaker
# This file is distributed under the same license as the Cura package.
-# Ruben Dulek , 2017.
+# Ruben Dulek , 2018.
#
#, fuzzy
msgid ""
msgstr ""
-"Project-Id-Version: Cura 3.1\n"
+"Project-Id-Version: Cura 3.2\n"
"Report-Msgid-Bugs-To: r.dulek@ultimaker.com\n"
-"POT-Creation-Date: 2017-08-02 16:53+0000\n"
+"POT-Creation-Date: 2018-01-29 09:48+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME \n"
"Language-Team: TEAM\n"
@@ -18,7 +18,7 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.py:29
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.py:26
msgctxt "@action"
msgid "Machine Settings"
msgstr ""
@@ -55,12 +55,11 @@ msgstr ""
#: /home/ruben/Projects/Cura/plugins/Doodle3D-cura-plugin/Doodle3D/D3DCloudPrintOutputDevicePlugin.py:87
#: /home/ruben/Projects/Cura/plugins/Doodle3D-cura-plugin/Doodle3D/D3DCloudPrintOutputDevicePlugin.py:155
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:874
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:646
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:875
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:659
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/DiscoverUM3Action.qml:370
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/PrintWindow.qml:78
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/ConfigDialog.qml:104
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/ExportSTLUI.qml:99
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:355
#: /home/ruben/Projects/Cura/plugins/ImageReader/ConfigUI.qml:188
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:376
#: /home/ruben/Projects/Cura/plugins/PluginBrowser/PluginBrowser.qml:139
@@ -100,7 +99,7 @@ msgctxt "@info:tooltip"
msgid "Open the Doodle3D Connect web interface"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/ChangeLogPlugin/ChangeLog.py:34
+#: /home/ruben/Projects/Cura/plugins/ChangeLogPlugin/ChangeLog.py:33
msgctxt "@item:inmenu"
msgid "Show Changelog"
msgstr ""
@@ -115,80 +114,85 @@ msgctxt "@info:status"
msgid "Profile has been flattened & activated."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:26
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:27
msgctxt "@item:inmenu"
msgid "USB printing"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:27
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:28
msgctxt "@action:button Preceded by 'Ready to'."
msgid "Print via USB"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:28
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:29
msgctxt "@info:tooltip"
msgid "Print via USB"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:30
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:31
msgctxt "@info:status"
msgid "Connected via USB"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:154
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:183
msgctxt "@info:status"
msgid "Unable to start a new job because the printer is busy or not connected."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:154
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:183
msgctxt "@info:title"
msgid "Printer Unavailable"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:457
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:485
msgctxt "@info:status"
msgid ""
"This printer does not support USB printing because it uses UltiGCode flavor."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:457
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:485
msgctxt "@info:title"
msgid "USB Printing"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:461
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:489
msgctxt "@info:status"
msgid ""
"Unable to start a new job because the printer does not support usb printing."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:461
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDeviceManager.py:108
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:489
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDeviceManager.py:103
#: /home/ruben/Projects/Cura/plugins/RemovableDriveOutputDevice/RemovableDriveOutputDevice.py:146
#: /home/ruben/Projects/Cura/plugins/RemovableDriveOutputDevice/RemovableDriveOutputDevice.py:158
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:945
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1349
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1417
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:946
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1418
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1496
msgctxt "@info:title"
msgid "Warning"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDeviceManager.py:108
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDeviceManager.py:103
msgctxt "@info"
msgid "Unable to update firmware because there are no printers connected."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDeviceManager.py:122
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDeviceManager.py:117
#, python-format
msgctxt "@info"
msgid "Could not find firmware required for the printer at %s."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDeviceManager.py:122
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDeviceManager.py:117
msgctxt "@info:title"
msgid "Printer Firmware"
msgstr ""
+#: /home/ruben/Projects/Cura/plugins/PrepareStage/__init__.py:12
+msgctxt "@item:inmenu"
+msgid "Prepare"
+msgstr ""
+
#: /home/ruben/Projects/Cura/plugins/RemovableDriveOutputDevice/RemovableDriveOutputDevice.py:23
msgctxt "@action:button Preceded by 'Ready to'."
msgid "Save to Removable Drive"
@@ -232,11 +236,11 @@ msgid "Could not save to removable drive {0}: {1}"
msgstr ""
#: /home/ruben/Projects/Cura/plugins/RemovableDriveOutputDevice/RemovableDriveOutputDevice.py:132
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:692
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:700
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:146
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:693
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:701
#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:153
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1358
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:160
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1427
msgctxt "@info:title"
msgid "Error"
msgstr ""
@@ -286,7 +290,7 @@ msgid "Removable Drive"
msgstr ""
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:109
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:53
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:51
msgctxt "@action:button Preceded by 'Ready to'."
msgid "Print over network"
msgstr ""
@@ -406,37 +410,37 @@ msgctxt "@info:title"
msgid "Printer Status"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:691
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:692
#, python-brace-format
msgctxt "@info:status"
msgid "Unable to start a new print job. No Printcore loaded in slot {0}"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:699
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:700
#, python-brace-format
msgctxt "@info:status"
msgid "Unable to start a new print job. No material loaded in slot {0}"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:709
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:710
#, python-brace-format
msgctxt "@label"
msgid "Not enough material for spool {0}."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:719
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:720
#, python-brace-format
msgctxt "@label"
msgid "Different PrintCore (Cura: {0}, Printer: {1}) selected for extruder {2}"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:733
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:734
#, python-brace-format
msgctxt "@label"
msgid "Different material (Cura: {0}, Printer: {1}) selected for extruder {2}"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:741
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:742
#, python-brace-format
msgctxt "@label"
msgid ""
@@ -444,12 +448,12 @@ msgid ""
"performed on the printer."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:746
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:747
msgctxt "@label"
msgid "Are you sure you wish to print with the selected configuration?"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:747
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:748
msgctxt "@label"
msgid ""
"There is a mismatch between the configuration or calibration of the printer "
@@ -457,65 +461,65 @@ msgid ""
"that are inserted in your printer."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:753
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:754
msgctxt "@window:title"
msgid "Mismatched configuration"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:864
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:262
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:865
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:258
msgctxt "@info:status"
msgid ""
"Sending new jobs (temporarily) blocked, still sending the previous print job."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:873
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:874
msgctxt "@info:status"
msgid "Sending data to printer"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:873
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:874
msgctxt "@info:title"
msgid "Sending Data"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:944
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:945
msgctxt "@info:status"
msgid "Unable to send data to printer. Is another job still active?"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:1085
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:1087
#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:196
msgctxt "@label:MonitorStatus"
msgid "Aborting print..."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:1091
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:1093
msgctxt "@label:MonitorStatus"
msgid "Print aborted. Please check the printer"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:1097
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:1099
msgctxt "@label:MonitorStatus"
msgid "Pausing print..."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:1099
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:1101
msgctxt "@label:MonitorStatus"
msgid "Resuming print..."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:1289
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:1291
msgctxt "@window:title"
msgid "Sync with your printer"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:1291
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:1293
msgctxt "@label"
msgid "Would you like to use your current printer configuration in Cura?"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:1293
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:1295
msgctxt "@label"
msgid ""
"The PrintCores and/or materials on your printer differ from those within "
@@ -544,80 +548,84 @@ msgid ""
msgstr ""
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:115
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:520
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:533
#, python-brace-format
msgid ""
"{printer_name} is reserved to print '{job_name}'. Please change the "
"printer's configuration to match the job, for it to start printing."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:278
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:277
msgctxt "@info:status"
msgid ""
"Unable to send new print job: this 3D printer is not (yet) set up to host a "
"group of connected Ultimaker 3 printers."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:410
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:423
#, python-brace-format
msgctxt "@info:status"
msgid "Unable to send print job to group {cluster_name}."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:418
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:431
#, python-brace-format
msgctxt "@info:status"
msgid "Sent {file_name} to group {cluster_name}."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:423
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:436
msgctxt "@action:button"
msgid "Show print jobs"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:424
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:437
msgctxt "@info:tooltip"
msgid "Opens the print jobs interface in your browser."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:489
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:502
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/DiscoverUM3Action.qml:239
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/PrinterInfoBlock.qml:47
-msgctxt "@label"
+msgctxt "@label Printer name"
msgid "Unknown"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:492
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:505
#, python-brace-format
msgctxt "@info:status"
msgid "Printer '{printer_name}' has finished printing '{job_name}'."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:494
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:497
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:507
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:510
msgctxt "@info:status"
msgid "Print finished"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:522
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:525
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:535
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:538
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/PrinterInfoBlock.qml:282
msgctxt "@label:status"
msgid "Action required"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:643
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:656
#, python-brace-format
msgctxt "@info:progress"
msgid "Sending {file_name} to group {cluster_name}"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/DiscoverUM3Action.py:19
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/DiscoverUM3Action.py:17
msgctxt "@action"
msgid "Connect via Network"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py:64
+#: /home/ruben/Projects/Cura/plugins/MonitorStage/__init__.py:12
+msgctxt "@item:inmenu"
+msgid "Monitor"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py:66
#, python-brace-format
msgctxt ""
"@info Don't translate {machine_name}, since it gets replaced by a printer "
@@ -627,74 +635,118 @@ msgid ""
"update the firmware on your printer."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py:65
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py:67
#, 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:66
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py:68
msgctxt "@action:button"
msgid "How to update"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py:77
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py:79
msgctxt "@info"
msgid "Could not access update information."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksReader.py:199
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksReader.py:579
msgctxt "@info:status"
msgid ""
-"Errors appeared while opening your SolidWorks file! Please "
-"check, whether it is possible to open your file in SolidWorks itself without "
-"any problems as well!"
+"SolidWorks reported errors, while opening your file. We recommend to solve "
+"these issues inside SolidWorks itself."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/__init__.py:31
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksReader.py:591
+msgctxt "@info:status"
+msgid ""
+"Found no models inside your drawing. Could you please check it's content "
+"again and make sure one part or assembly is inside?\n"
+"\n"
+" Thanks!."
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksReader.py:595
+msgctxt "@info:status"
+msgid ""
+"Found more then one part or assembly inside your drawing. We currently only "
+"support drawings with exactly one part or assembly inside.\n"
+"\n"
+"Sorry!"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/__init__.py:25
msgctxt "@item:inlistbox"
msgid "SolidWorks part file"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/__init__.py:35
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/__init__.py:29
msgctxt "@item:inlistbox"
msgid "SolidWorks assembly file"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/ConfigDialog.py:21
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/__init__.py:33
+msgctxt "@item:inlistbox"
+msgid "SolidWorks drawing file"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/__init__.py:48
+msgctxt "@info:status"
+msgid ""
+"Dear customer,\n"
+"We could not find a valid installation of SolidWorks on your system. That "
+"means that either SolidWorks is not installed or you don't own an valid "
+"license. Please make sure that running SolidWorks itself works without "
+"issues and/or contact your ICT.\n"
+"\n"
+"With kind regards\n"
+" - Thomas Karl Pietrowski"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/__init__.py:57
+msgctxt "@info:status"
+msgid ""
+"Dear customer,\n"
+"You are currently running this plugin on an operating system other than "
+"Windows. This plugin will only work on Windows with SolidWorks installed, "
+"including an valid license. Please install this plugin on a Windows machine "
+"with SolidWorks installed.\n"
+"\n"
+"With kind regards\n"
+" - Thomas Karl Pietrowski"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksDialogHandler.py:70
msgid "Configure"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/CommonComReader.py:135
-#, python-format
-msgctxt "@info:status"
-msgid "Error while starting %s!"
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksDialogHandler.py:71
+msgid "Installation guide for SolidWorks macro"
msgstr ""
#: /home/ruben/Projects/Cura/plugins/SimulationView/__init__.py:14
msgctxt "@item:inlistbox"
-msgid "Simulation view"
+msgid "Layer view"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.py:100
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.py:103
msgctxt "@info:status"
msgid "Cura does not accurately display layers when Wire Printing is enabled"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.py:101
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.py:104
msgctxt "@info:title"
msgid "Simulation View"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.py:26
+#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.py:25
msgid "Modify G-Code"
msgstr ""
#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/SliceInfo.py:43
msgctxt "@info"
-msgid ""
-"Cura collects anonymised slicing statistics. You can disable this in the "
-"preferences."
+msgid "Cura collects anonymized usage statistics."
msgstr ""
#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/SliceInfo.py:46
@@ -704,7 +756,27 @@ msgstr ""
#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/SliceInfo.py:48
msgctxt "@action:button"
-msgid "Dismiss"
+msgid "Allow"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/SliceInfo.py:49
+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/SliceInfoPlugin/SliceInfo.py:50
+msgctxt "@action:button"
+msgid "Disable"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/SliceInfo.py:51
+msgctxt "@action:tooltip"
+msgid ""
+"Don't allow Cura to send anonymized usage statistics. You can enable it "
+"again in the preferences."
msgstr ""
#: /home/ruben/Projects/Cura/plugins/LegacyProfileReader/__init__.py:14
@@ -712,6 +784,18 @@ msgctxt "@item:inlistbox"
msgid "Cura 15.04 profiles"
msgstr ""
+#: /home/ruben/Projects/Cura/plugins/CuraBlenderPlugin/__init__.py:15
+msgctxt "@item:inlistbox"
+msgid "Blender file"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/CuraBlenderPlugin/CadIntegrationUtils/CommonReader.py:199
+msgctxt "@info:status"
+msgid ""
+"Could not export using \"{}\" quality!\n"
+"Felt back to \"{}\"."
+msgstr ""
+
#: /home/ruben/Projects/Cura/plugins/GCodeProfileReader/__init__.py:14
#: /home/ruben/Projects/Cura/plugins/GCodeReader/__init__.py:14
msgctxt "@item:inlistbox"
@@ -743,23 +827,23 @@ msgctxt "@item:inlistbox"
msgid "GIF Image"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:269
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:299
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:269
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:297
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:319
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:299
#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:327
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:336
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:349
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:357
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:366
msgctxt "@info:title"
msgid "Unable to slice"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:296
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:326
#, python-brace-format
msgctxt "@info:status"
msgid ""
@@ -767,7 +851,7 @@ msgid ""
"errors: {0}"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:318
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:348
#, python-brace-format
msgctxt "@info:status"
msgid ""
@@ -775,13 +859,13 @@ msgid ""
"errors on one or more models: {error_labels}"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:326
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:356
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:335
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:365
msgctxt "@info:status"
msgid ""
"Nothing to slice because none of the models fit the build volume. Please "
@@ -789,12 +873,12 @@ msgid ""
msgstr ""
#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py:50
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py:239
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py:242
msgctxt "@info:status"
msgid "Processing Layers"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py:239
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py:242
msgctxt "@info:title"
msgid "Information"
msgstr ""
@@ -836,14 +920,14 @@ msgid ""
"UGII_USER_DIR for Siemens NX."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.py:167
-#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:585
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.py:165
+#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:590
msgctxt "@title:tab"
msgid "Recommended"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.py:169
-#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:590
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.py:167
+#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:595
msgctxt "@title:tab"
msgid "Custom"
msgstr ""
@@ -854,24 +938,24 @@ msgctxt "@item:inlistbox"
msgid "3MF File"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/3MFReader/ThreeMFWorkspaceReader.py:126
-#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:1142
+#: /home/ruben/Projects/Cura/plugins/3MFReader/ThreeMFWorkspaceReader.py:159
+#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:1185
msgctxt "@label"
msgid "Nozzle"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/PluginBrowser/PluginBrowser.py:164
+#: /home/ruben/Projects/Cura/plugins/PluginBrowser/PluginBrowser.py:152
#, python-brace-format
msgctxt "@info:status"
msgid "Failed to get plugin ID from {0}"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/PluginBrowser/PluginBrowser.py:165
+#: /home/ruben/Projects/Cura/plugins/PluginBrowser/PluginBrowser.py:153
msgctxt "@info:tile"
msgid "Warning"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/PluginBrowser/PluginBrowser.py:203
+#: /home/ruben/Projects/Cura/plugins/PluginBrowser/PluginBrowser.py:191
msgctxt "@window:title"
msgid "Plugin browser"
msgstr ""
@@ -886,18 +970,18 @@ msgctxt "@item:inlistbox"
msgid "G File"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/GCodeReader/GCodeReader.py:314
+#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:321
msgctxt "@info:status"
msgid "Parsing G-code"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/GCodeReader/GCodeReader.py:316
-#: /home/ruben/Projects/Cura/plugins/GCodeReader/GCodeReader.py:426
+#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:323
+#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:464
msgctxt "@info:title"
msgid "G-code Details"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/GCodeReader/GCodeReader.py:424
+#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:462
msgctxt "@info:generic"
msgid ""
"Make sure the g-code is suitable for your printer and printer configuration "
@@ -910,6 +994,16 @@ msgctxt "@item:inlistbox"
msgid "Cura Profile"
msgstr ""
+#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/__init__.py:12
+msgctxt "@item:inmenu"
+msgid "Profile Assistant"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/__init__.py:17
+msgctxt "@item:inlistbox"
+msgid "Profile Assistant"
+msgstr ""
+
#: /home/ruben/Projects/Cura/plugins/3MFWriter/__init__.py:30
msgctxt "@item:inlistbox"
msgid "3MF file"
@@ -941,111 +1035,90 @@ msgctxt "@action"
msgid "Level build plate"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:89
+#: /home/ruben/Projects/Cura/cura/PrintInformation.py:98
msgctxt "@tooltip"
msgid "Outer Wall"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:90
+#: /home/ruben/Projects/Cura/cura/PrintInformation.py:99
msgctxt "@tooltip"
msgid "Inner Walls"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:91
+#: /home/ruben/Projects/Cura/cura/PrintInformation.py:100
msgctxt "@tooltip"
msgid "Skin"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:92
+#: /home/ruben/Projects/Cura/cura/PrintInformation.py:101
msgctxt "@tooltip"
msgid "Infill"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:93
+#: /home/ruben/Projects/Cura/cura/PrintInformation.py:102
msgctxt "@tooltip"
msgid "Support Infill"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:94
+#: /home/ruben/Projects/Cura/cura/PrintInformation.py:103
msgctxt "@tooltip"
msgid "Support Interface"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:95
+#: /home/ruben/Projects/Cura/cura/PrintInformation.py:104
msgctxt "@tooltip"
msgid "Support"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:96
+#: /home/ruben/Projects/Cura/cura/PrintInformation.py:105
msgctxt "@tooltip"
msgid "Skirt"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:97
+#: /home/ruben/Projects/Cura/cura/PrintInformation.py:106
msgctxt "@tooltip"
msgid "Travel"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:98
+#: /home/ruben/Projects/Cura/cura/PrintInformation.py:107
msgctxt "@tooltip"
msgid "Retractions"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:99
+#: /home/ruben/Projects/Cura/cura/PrintInformation.py:108
msgctxt "@tooltip"
msgid "Other"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:199
+#: /home/ruben/Projects/Cura/cura/PrintInformation.py:231
msgctxt "@label unknown material"
msgid "Unknown"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:284
+#: /home/ruben/Projects/Cura/cura/PrintInformation.py:318
#, python-brace-format
msgctxt "@label"
msgid "Pre-sliced file {0}"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/PrinterOutputDevice.py:469
+#: /home/ruben/Projects/Cura/cura/PrinterOutputDevice.py:440
msgctxt "@item:material"
msgid "No material loaded"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/PrinterOutputDevice.py:476
+#: /home/ruben/Projects/Cura/cura/PrinterOutputDevice.py:447
msgctxt "@item:material"
msgid "Unknown material"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/ArrangeObjectsJob.py:30
-msgctxt "@info:status"
-msgid "Finding new location for objects"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/cura/ArrangeObjectsJob.py:34
-msgctxt "@info:title"
-msgid "Finding Location"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/cura/ArrangeObjectsJob.py:89
-#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:83
-msgctxt "@info:status"
-msgid "Unable to find a location within the build volume for all objects"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/cura/ArrangeObjectsJob.py:90
-msgctxt "@info:title"
-msgid "Can't Find Location"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:431
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:113
+#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:437
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:120
msgctxt "@title:window"
msgid "File Already Exists"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:432
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:114
+#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:438
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:121
#, python-brace-format
msgctxt "@label Don't translate the XML tag !"
msgid ""
@@ -1053,34 +1126,29 @@ msgid ""
"overwrite it?"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:815
+#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:872
msgctxt "@label"
msgid "Custom"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:819
+#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:876
msgctxt "@label"
msgid "Custom Material"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/Settings/ExtrudersModel.py:182
-msgctxt "@menuitem"
-msgid "Global"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/cura/Settings/ExtrudersModel.py:229
+#: /home/ruben/Projects/Cura/cura/Settings/ExtrudersModel.py:205
msgctxt "@menuitem"
msgid "Not overridden"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:117
+#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:124
msgctxt "@info:status"
msgid ""
"The selected material is incompatible with the selected machine or "
"configuration."
msgstr ""
-#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:118
+#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:125
#: /home/ruben/Projects/Cura/cura/Settings/MaterialManager.py:24
msgctxt "@info:title"
msgid "Incompatible Material"
@@ -1103,14 +1171,14 @@ msgctxt "@action"
msgid "Undo changing the material diameter."
msgstr ""
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:144
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:151
#, 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:151
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:158
#, python-brace-format
msgctxt "@info:status Don't translate the XML tag !"
msgid ""
@@ -1118,21 +1186,20 @@ msgid ""
"failure."
msgstr ""
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:156
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:163
#, 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:157
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:164
msgctxt "@info:title"
msgid "Export succeeded"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:183
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:205
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:214
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:248
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:190
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:211
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:271
#, python-brace-format
msgctxt "@info:status Don't translate the XML tags or !"
msgid ""
@@ -1140,35 +1207,62 @@ msgid ""
"message>"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:216
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:252
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:230
+#, python-brace-format
+msgctxt "@info:status Don't translate the XML tags or !"
+msgid ""
+"This profile {0} contains incorrect data, could not "
+"import it."
+msgstr ""
+
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:240
+#, python-brace-format
+msgctxt "@info:status Don't translate the XML tags or !"
+msgid ""
+"The machine defined in profile {0} doesn't match with "
+"your current machine, could not import it."
+msgstr ""
+
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:274
#, python-brace-format
msgctxt "@info:status"
msgid "Successfully imported profile {0}"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:255
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:277
+#, python-brace-format
+msgctxt "@info:status"
+msgid "File {0} does not contain any valid profile."
+msgstr ""
+
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:280
#, 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:274
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:298
msgctxt "@label"
msgid "Custom profile"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:285
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:313
msgctxt "@info:status"
msgid "Profile is missing a quality type."
msgstr ""
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:321
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:349
#, 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:46
+#, python-brace-format
+msgctxt "@label"
+msgid "Group #{group_nr}"
+msgstr ""
+
#: /home/ruben/Projects/Cura/cura/BuildVolume.py:100
msgctxt "@info:status"
msgid ""
@@ -1181,126 +1275,151 @@ msgctxt "@info:title"
msgid "Build Volume"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:34
+#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:25
msgctxt "@info:status"
msgid "Multiplying and placing objects"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:35
-#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:83
+#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:26
+#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:78
msgctxt "@info:title"
msgid "Placing Object"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/CrashHandler.py:80
+#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:78
+#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsJob.py:88
+#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsAllBuildPlatesJob.py:152
+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:29
+#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsAllBuildPlatesJob.py:64
+msgctxt "@info:status"
+msgid "Finding new location for objects"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsJob.py:33
+#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsAllBuildPlatesJob.py:68
+msgctxt "@info:title"
+msgid "Finding Location"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsJob.py:89
+#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsAllBuildPlatesJob.py:153
+msgctxt "@info:title"
+msgid "Can't Find Location"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/cura/CrashHandler.py:81
msgctxt "@title:window"
msgid "Crash Report"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/CrashHandler.py:93
+#: /home/ruben/Projects/Cura/cura/CrashHandler.py:94
msgctxt "@label crash message"
msgid ""
-"
A fatal exception has occurred. Please send us this Crash Report to "
-"fix the problem
\n"
+"
A fatal error has occurred. Please send us this Crash Report to fix "
+"the problem
\n"
"
Please use the \"Send report\" button to post a bug report "
"automatically to our servers
"
-#: /home/ruben/Projects/Cura/cura/CrashHandler.py:141
+#: /home/ruben/Projects/Cura/cura/CrashHandler.py:147
msgctxt "@title:groupbox"
-msgid "Exception traceback"
-msgstr "Ausnahme-Rückverfolgung"
+msgid "Error traceback"
+msgstr "Fehler-Rückverfolgung"
-#: /home/ruben/Projects/Cura/cura/CrashHandler.py:208
+#: /home/ruben/Projects/Cura/cura/CrashHandler.py:214
msgctxt "@title:groupbox"
msgid "Logs"
msgstr "Protokolle"
-#: /home/ruben/Projects/Cura/cura/CrashHandler.py:231
+#: /home/ruben/Projects/Cura/cura/CrashHandler.py:237
msgctxt "@title:groupbox"
msgid "User description"
msgstr "Benutzerbeschreibung"
-#: /home/ruben/Projects/Cura/cura/CrashHandler.py:246
+#: /home/ruben/Projects/Cura/cura/CrashHandler.py:252
msgctxt "@action:button"
msgid "Send report"
msgstr "Bericht senden"
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:256
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:274
msgctxt "@info:progress"
msgid "Loading machines..."
msgstr "Geräte werden geladen..."
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:661
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:660
msgctxt "@info:progress"
msgid "Setting up scene..."
msgstr "Die Szene wird eingerichtet..."
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:703
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:702
msgctxt "@info:progress"
msgid "Loading interface..."
msgstr "Die Benutzeroberfläche wird geladen..."
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:874
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:899
#, 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:1348
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1417
#, 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:1357
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1426
#, 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:1416
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1495
msgctxt "@info:status"
msgid "The selected model was too small to load."
msgstr "Das gewählte Modell war zu klein zum Laden."
@@ -1279,12 +1407,11 @@ msgstr "X (Breite)"
#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:119
#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:129
#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:235
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:288
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:300
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:391
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:401
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:413
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:840
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:383
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:394
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:412
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:424
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:849
msgctxt "@label"
msgid "mm"
msgstr "mm"
@@ -1374,68 +1501,67 @@ 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:255
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:254
msgctxt "@label"
msgid "Number of Extruders"
msgstr "Anzahl Extruder"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:289
-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:291
-msgctxt "@label"
-msgid "Material diameter"
-msgstr "Materialdurchmesser"
-
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:299
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:390
-msgctxt "@label"
-msgid "Nozzle size"
-msgstr "Düsengröße"
-
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:317
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:310
msgctxt "@label"
msgid "Start Gcode"
msgstr "G-Code starten"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:327
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:320
msgctxt "@tooltip"
msgid "Gcode 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:336
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:329
msgctxt "@label"
msgid "End Gcode"
msgstr "G-Code beenden"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:346
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:339
msgctxt "@tooltip"
msgid "Gcode 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:378
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:370
msgctxt "@label"
msgid "Nozzle Settings"
msgstr "Düseneinstellungen"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:400
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:382
+msgctxt "@label"
+msgid "Nozzle size"
+msgstr "Düsengröße"
+
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:393
+msgctxt "@label"
+msgid "Compatible material diameter"
+msgstr "Kompatibler Materialdurchmesser"
+
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:395
+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:411
msgctxt "@label"
msgid "Nozzle offset X"
msgstr "X-Versatz Düse"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:412
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:423
msgctxt "@label"
msgid "Nozzle offset Y"
msgstr "Y-Versatz Düse"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:433
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:444
msgctxt "@label"
msgid "Extruder Start Gcode"
msgstr "G-Code Extruder-Start"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:451
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:462
msgctxt "@label"
msgid "Extruder End Gcode"
msgstr "G-Code Extruder-Ende"
@@ -1448,8 +1574,9 @@ msgstr "Änderungsprotokoll"
#: /home/ruben/Projects/Cura/plugins/ChangeLogPlugin/ChangeLog.qml:37
#: /home/ruben/Projects/Cura/plugins/USBPrinting/FirmwareUpdateWindow.qml:107
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/UM3InfoComponents.qml:55
-#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.qml:445
-#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:357
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksMacroTutorial.qml:306
+#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.qml:456
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:492
#: /home/ruben/Projects/Cura/plugins/PluginBrowser/PluginBrowser.qml:80
#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:123
#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:147
@@ -1506,7 +1633,7 @@ msgstr "Unbekannter Fehlercode: %1"
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/DiscoverUM3Action.qml:55
msgctxt "@title:window"
msgid "Connect to Networked Printer"
-msgstr "Anschluss an vernetzten Drucker"
+msgstr "Anschluss an Netzwerk Drucker"
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/DiscoverUM3Action.qml:65
msgctxt "@label"
@@ -1514,7 +1641,10 @@ 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\nWählen Sie Ihren Drucker aus der folgenden Liste:"
+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:"
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/DiscoverUM3Action.qml:75
#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:44
@@ -1530,7 +1660,7 @@ msgstr "Bearbeiten"
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/DiscoverUM3Action.qml:96
#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:50
#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:95
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:190
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:171
msgctxt "@action:button"
msgid "Remove"
msgstr "Entfernen"
@@ -1552,12 +1682,12 @@ msgid "Type"
msgstr "Typ"
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/DiscoverUM3Action.qml:233
-msgctxt "@label"
+msgctxt "@label Printer name"
msgid "Ultimaker 3"
msgstr "Ultimaker 3"
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/DiscoverUM3Action.qml:236
-msgctxt "@label"
+msgctxt "@label Printer name"
msgid "Ultimaker 3 Extended"
msgstr "Ultimaker 3 Extended"
@@ -1603,8 +1733,6 @@ 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/DiscoverUM3Action.qml:379
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/ConfigDialog.qml:92
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/ExportSTLUI.qml:88
#: /home/ruben/Projects/Cura/plugins/ImageReader/ConfigUI.qml:181
msgctxt "@action:button"
msgid "OK"
@@ -1625,6 +1753,11 @@ msgctxt "@label: arg 1 is group name"
msgid "%1 is not set up to host a group of connected Ultimaker 3 printers"
msgstr "%1 ist nicht für das Hosten einer Gruppe verbundener Ultimaker 3-Drucker eingerichtet"
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/ClusterMonitorItem.qml:55
+msgctxt "@label link to connect manager"
+msgid "Add/Remove printers"
+msgstr "Drucker hinzufügen/entfernen"
+
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/OpenPanelButton.qml:14
msgctxt "@info:tooltip"
msgid "Opens the print jobs page with your default web browser."
@@ -1655,11 +1788,16 @@ msgid "Available"
msgstr "Verfügbar"
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/PrinterInfoBlock.qml:43
-#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:101
+#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:100
msgctxt "@label:MonitorStatus"
msgid "Lost connection with the printer"
msgstr "Verbindung zum Drucker wurde unterbrochen"
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/PrinterInfoBlock.qml:47
+msgctxt "@label Printer status"
+msgid "Unknown"
+msgstr "Unbekannt"
+
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/PrinterInfoBlock.qml:257
msgctxt "@label:status"
msgid "Disabled"
@@ -1751,138 +1889,252 @@ msgctxt "@action:button"
msgid "Activate Configuration"
msgstr "Konfiguration aktivieren"
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/ConfigDialog.qml:20
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksWizard.qml:21
msgctxt "@title:window"
-msgid "Cura SolidWorks Plugin Configuration"
-msgstr "Cura SolidWorks Plugin-Konfiguration"
+msgid "SolidWorks: Export wizard"
+msgstr "SolidWorks: Exportassistent"
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/ConfigDialog.qml:44
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksWizard.qml:45
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:140
msgctxt "@action:label"
-msgid "Default quality of the exported STL:"
-msgstr "Standardqualität des exportierten STL:"
+msgid "Quality:"
+msgstr "Qualität:"
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/ConfigDialog.qml:79
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksWizard.qml:78
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:179
msgctxt "@option:curaSolidworksStlQuality"
-msgid "Always ask"
-msgstr "Immer nachfragen"
+msgid "Fine (3D-printing)"
+msgstr "Fein (3D-Druck)"
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/ConfigDialog.qml:80
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksWizard.qml:79
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:180
msgctxt "@option:curaSolidworksStlQuality"
-msgid "Always use Fine quality"
-msgstr "Immer Qualität „Fein“ verwenden"
+msgid "Coarse (3D-printing)"
+msgstr "Grob (3D-Druck)"
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/ConfigDialog.qml:81
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksWizard.qml:80
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:181
msgctxt "@option:curaSolidworksStlQuality"
-msgid "Always use Coarse quality"
-msgstr "Immer Qualität „Grob“ verwenden"
+msgid "Fine (SolidWorks)"
+msgstr "Fein (SolidWorks)"
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/ExportSTLUI.qml:20
-msgctxt "@title:window"
-msgid "Import SolidWorks File as STL..."
-msgstr "SolidWorks-Datei importieren als STL ..."
-
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/ExportSTLUI.qml:43
-msgctxt "@info:tooltip"
-msgid "Quality of the Exported STL"
-msgstr "Qualität des exportierten STL"
-
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/ExportSTLUI.qml:48
-msgctxt "@action:label"
-msgid "Quality"
-msgstr "Qualität"
-
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/ExportSTLUI.qml:62
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksWizard.qml:81
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:182
msgctxt "@option:curaSolidworksStlQuality"
-msgid "Coarse"
-msgstr "Grob"
+msgid "Coarse (SolidWorks)"
+msgstr "Grob (SolidWorks)"
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/ExportSTLUI.qml:63
-msgctxt "@option:curaSolidworksStlQuality"
-msgid "Fine"
-msgstr "Fein"
-
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/ExportSTLUI.qml:78
-#: /home/ruben/Projects/Cura/resources/qml/AskOpenAsProjectOrModelsDialog.qml:82
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksWizard.qml:94
msgctxt "@text:window"
-msgid "Remember my choice"
-msgstr "Meine Auswahl merken"
+msgid "Show this dialog again"
+msgstr "Diesen Dialog erneut anzeigen"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:81
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksWizard.qml:104
+msgctxt "@action:button"
+msgid "Continue"
+msgstr "Weiter"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksWizard.qml:116
+msgctxt "@action:button"
+msgid "Abort"
+msgstr "Abbrechen"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksMacroTutorial.qml:21
+msgctxt "@title:window"
+msgid "How to install Cura SolidWorks macro"
+msgstr "Installieren von Cura SolidWorks Makro"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksMacroTutorial.qml:62
+msgctxt "@description:label"
+msgid "Steps:"
+msgstr "Schritte:"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksMacroTutorial.qml:140
+msgctxt "@action:button"
+msgid ""
+"Open the directory\n"
+"with macro and icon"
+msgstr ""
+"Verzeichnis\n"
+"mit Makro und Symbol öffnen"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksMacroTutorial.qml:160
+msgctxt "@description:label"
+msgid "Instructions:"
+msgstr "Anweisungen:"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksMacroTutorial.qml:202
+msgctxt "@action:playpause"
+msgid "Play"
+msgstr "Wiedergeben"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksMacroTutorial.qml:206
+msgctxt "@action:playpause"
+msgid "Pause"
+msgstr "Pausieren"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksMacroTutorial.qml:268
+msgctxt "@action:button"
+msgid "Previous Step"
+msgstr "Vorheriger Schritt"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksMacroTutorial.qml:283
+msgctxt "@action:button"
+msgid "Done"
+msgstr "Fertig"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksMacroTutorial.qml:287
+msgctxt "@action:button"
+msgid "Next Step"
+msgstr "Nächster Schritt"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:21
+msgctxt "@title:window"
+msgid "SolidWorks plugin: Configuration"
+msgstr "SolidWorks Plugin: Konfiguration"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:39
+msgctxt "@title:tab"
+msgid "Conversion settings"
+msgstr "Konvertierungseinstellungen"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:66
+msgctxt "@label"
+msgid "First choice:"
+msgstr "Erste Wahl:"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:86
+msgctxt "@text:menu"
+msgid "Latest installed version (Recommended)"
+msgstr "Aktuelle installierte Version (Empfohlen)"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:95
+msgctxt "@text:menu"
+msgid "Default version"
+msgstr "Standardversion"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:193
+msgctxt "@label"
+msgid "Show wizard before opening SolidWorks files"
+msgstr "Assistent vor dem Öffnen von SolidWorks-Dateien anzeigen"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:203
+msgctxt "@label"
+msgid "Automatically rotate opened file into normed orientation"
+msgstr "Geöffnete Datei automatisch in normale Ausrichtung drehen"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:210
+msgctxt "@title:tab"
+msgid "Installation(s)"
+msgstr "Installation(en)"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:284
+msgctxt "@label"
+msgid "COM service found"
+msgstr "COM-Service gefunden"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:295
+msgctxt "@label"
+msgid "Executable found"
+msgstr "Ausführbare Datei gefunden"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:306
+msgctxt "@label"
+msgid "COM starting"
+msgstr "COM wird gestartet"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:317
+msgctxt "@label"
+msgid "Revision number"
+msgstr "Revisionsnummer"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:328
+msgctxt "@label"
+msgid "Functions available"
+msgstr "Verfügbare Funktionen"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:341
+#: /home/ruben/Projects/Cura/resources/qml/WorkspaceSummaryDialog.qml:264
+msgctxt "@action:button"
+msgid "Save"
+msgstr "Speichern"
+
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:117
msgctxt "@label"
msgid "Color scheme"
msgstr "Farbschema"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:96
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:132
msgctxt "@label:listbox"
msgid "Material Color"
msgstr "Materialfarbe"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:100
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:136
msgctxt "@label:listbox"
msgid "Line Type"
msgstr "Linientyp"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:104
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:140
msgctxt "@label:listbox"
msgid "Feedrate"
msgstr "Vorschub"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:108
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:144
msgctxt "@label:listbox"
msgid "Layer thickness"
msgstr "Schichtdicke"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:148
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:185
msgctxt "@label"
msgid "Compatibility Mode"
msgstr "Kompatibilitätsmodus"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:230
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:264
msgctxt "@label"
msgid "Show Travels"
msgstr "Bewegungen anzeigen"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:236
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:270
msgctxt "@label"
msgid "Show Helpers"
msgstr "Helfer anzeigen"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:242
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:276
msgctxt "@label"
msgid "Show Shell"
msgstr "Gehäuse anzeigen"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:248
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:282
msgctxt "@label"
msgid "Show Infill"
msgstr "Füllung anzeigen"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:297
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:330
msgctxt "@label"
msgid "Only Show Top Layers"
msgstr "Nur obere Schichten anzeigen"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:306
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:339
msgctxt "@label"
msgid "Show 5 Detailed Layers On Top"
msgstr "5 detaillierte Schichten oben anzeigen"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:317
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:350
msgctxt "@label"
msgid "Top / Bottom"
msgstr "Oben/Unten"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:321
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:354
msgctxt "@label"
msgid "Inner Wall"
msgstr "Innenwand"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:378
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:410
msgctxt "@label"
msgid "min"
msgstr "min."
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:420
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:452
msgctxt "@label"
msgid "max"
msgstr "max."
@@ -1907,7 +2159,7 @@ msgctxt "@label"
msgid "Settings"
msgstr "Einstellungen"
-#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.qml:455
+#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.qml:466
msgctxt "@info:tooltip"
msgid "Change active post-processing scripts"
msgstr "Aktive Skripts Nachbearbeitung ändern"
@@ -1982,23 +2234,53 @@ msgctxt "@action:label"
msgid "Smoothing"
msgstr "Glättung"
-#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:208
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:38
+msgctxt "@label"
+msgid "Mesh Type"
+msgstr "Mesh-Typ"
+
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:69
+msgctxt "@label"
+msgid "Normal model"
+msgstr "Normales Modell"
+
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:76
+msgctxt "@label"
+msgid "Print as support"
+msgstr "Als Stützstruktur drucken"
+
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:84
+msgctxt "@label"
+msgid "Don't support overlap with other models"
+msgstr "Keine Überlappung mit anderen Modellen unterstützen"
+
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:92
+msgctxt "@label"
+msgid "Modify settings for overlap with other models"
+msgstr "Einstellungen für Überlappung mit anderen Modellen bearbeiten"
+
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:100
+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:333
msgctxt "@action:button"
msgid "Select settings"
msgstr "Einstellungen wählen"
-#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:248
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:375
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:272
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:402
#: /home/ruben/Projects/Cura/resources/qml/Preferences/SettingVisibilityPage.qml:91
msgctxt "@label:textbox"
msgid "Filter..."
msgstr "Filtern..."
-#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:296
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:426
msgctxt "@label:checkbox"
msgid "Show all"
msgstr "Alle anzeigen"
@@ -2166,7 +2448,10 @@ msgid ""
"This plugin contains a license.\n"
"You need to accept this license to install this plugin.\n"
"Do you agree with the terms below?"
-msgstr "Dieses Plugin enthält eine Lizenz.\nSie müssen diese Lizenz akzeptieren, um das Plugin zu installieren.\nStimmen Sie den nachfolgenden Bedingungen zu?"
+msgstr ""
+"Dieses Plugin enthält eine Lizenz.\n"
+"Sie müssen diese Lizenz akzeptieren, um das Plugin zu installieren.\n"
+"Stimmen Sie den nachfolgenden Bedingungen zu?"
#: /home/ruben/Projects/Cura/plugins/PluginBrowser/PluginBrowser.qml:242
msgctxt "@action:button"
@@ -2357,66 +2642,66 @@ 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:88
+#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:87
msgctxt "@label:MonitorStatus"
msgid "Not connected to a printer"
msgstr "Nicht mit einem Drucker verbunden"
-#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:90
+#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:89
msgctxt "@label:MonitorStatus"
msgid "Printer does not accept commands"
msgstr "Drucker nimmt keine Befehle an"
-#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:96
+#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:95
#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:194
msgctxt "@label:MonitorStatus"
msgid "In maintenance. Please check the printer"
msgstr "In Wartung. Den Drucker überprüfen"
-#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:103
+#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:102
#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:184
msgctxt "@label:MonitorStatus"
msgid "Printing..."
msgstr "Es wird gedruckt..."
-#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:106
+#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:105
#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:186
msgctxt "@label:MonitorStatus"
msgid "Paused"
msgstr "Pausiert"
-#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:109
+#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:108
#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:188
msgctxt "@label:MonitorStatus"
msgid "Preparing..."
msgstr "Vorbereitung läuft..."
-#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:111
+#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:110
msgctxt "@label:MonitorStatus"
msgid "Please remove the print"
msgstr "Bitte den Ausdruck entfernen"
-#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:237
+#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:241
msgctxt "@label:"
msgid "Resume"
msgstr "Zurückkehren"
-#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:241
+#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:245
msgctxt "@label:"
msgid "Pause"
msgstr "Pausieren"
-#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:270
+#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:274
msgctxt "@label:"
msgid "Abort Print"
msgstr "Drucken abbrechen"
-#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:280
+#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:284
msgctxt "@window:title"
msgid "Abort print"
msgstr "Drucken abbrechen"
-#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:282
+#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:286
msgctxt "@label"
msgid "Are you sure you want to abort the print?"
msgstr "Soll das Drucken wirklich abgebrochen werden?"
@@ -2431,7 +2716,9 @@ 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.\nMöchten Sie diese Einstellungen übernehmen oder verwerfen?"
+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"
@@ -2449,19 +2736,19 @@ msgid "Customized"
msgstr "Angepasst"
#: /home/ruben/Projects/Cura/resources/qml/DiscardOrKeepProfileChangesDialog.qml:157
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:593
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:595
msgctxt "@option:discardOrKeep"
msgid "Always ask me this"
msgstr "Stets nachfragen"
#: /home/ruben/Projects/Cura/resources/qml/DiscardOrKeepProfileChangesDialog.qml:158
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:594
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:596
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
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:595
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:597
msgctxt "@option:discardOrKeep"
msgid "Keep and never ask again"
msgstr "Übernehmen und zukünftig nicht mehr nachfragen"
@@ -2474,7 +2761,7 @@ msgstr "Verwerfen"
#: /home/ruben/Projects/Cura/resources/qml/DiscardOrKeepProfileChangesDialog.qml:209
msgctxt "@action:button"
msgid "Keep"
-msgstr "Übernehmen"
+msgstr "Beibehalten"
#: /home/ruben/Projects/Cura/resources/qml/DiscardOrKeepProfileChangesDialog.qml:222
msgctxt "@action:button"
@@ -2496,72 +2783,72 @@ msgctxt "@label"
msgid "Brand"
msgstr "Marke"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:92
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:88
msgctxt "@label"
msgid "Material Type"
msgstr "Materialtyp"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:105
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:97
msgctxt "@label"
msgid "Color"
msgstr "Farbe"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:139
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:141
msgctxt "@label"
msgid "Properties"
msgstr "Eigenschaften"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:141
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:143
msgctxt "@label"
msgid "Density"
msgstr "Dichte"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:156
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:158
msgctxt "@label"
msgid "Diameter"
msgstr "Durchmesser"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:185
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:187
msgctxt "@label"
msgid "Filament Cost"
msgstr "Filamentkosten"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:201
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:203
msgctxt "@label"
msgid "Filament weight"
msgstr "Filamentgewicht"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:218
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:220
msgctxt "@label"
msgid "Filament length"
msgstr "Filamentlänge"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:227
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:229
msgctxt "@label"
msgid "Cost per Meter"
msgstr "Kosten pro Meter"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:241
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:243
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/MaterialView.qml:248
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:250
msgctxt "@label"
msgid "Unlink Material"
msgstr "Material trennen"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:259
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:261
msgctxt "@label"
msgid "Description"
msgstr "Beschreibung"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:272
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:274
msgctxt "@label"
msgid "Adhesion Information"
msgstr "Haftungsinformationen"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:298
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:300
msgctxt "@label"
msgid "Print settings"
msgstr "Druckeinstellungen"
@@ -2602,7 +2889,7 @@ msgid "Unit"
msgstr "Einheit"
#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:14
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:439
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:509
msgctxt "@title:tab"
msgid "General"
msgstr "Allgemein"
@@ -2617,230 +2904,255 @@ msgctxt "@label"
msgid "Language:"
msgstr "Sprache:"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:205
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:207
msgctxt "@label"
msgid "Currency:"
msgstr "Währung:"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:219
+#: /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:279
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:281
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:296
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:298
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:304
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:306
msgctxt "@option:check"
msgid "Slice automatically"
msgstr "Automatisch schneiden"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:318
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:320
msgctxt "@label"
msgid "Viewport behavior"
msgstr "Viewport-Verhalten"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:326
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:328
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:335
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:337
msgctxt "@option:check"
msgid "Display overhang"
msgstr "Überhang anzeigen"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:342
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:344
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:347
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:349
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:356
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:358
msgctxt "@info:tooltip"
msgid "Should the default zoom behavior of cura be inverted?"
msgstr "Soll das standardmäßige Zoom-Verhalten von Cura umgekehrt werden?"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:361
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:363
msgctxt "@action:button"
msgid "Invert the direction of camera zoom."
msgstr "Kehren Sie die Richtung des Kamera-Zooms um."
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:370
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:372
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:375
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:377
msgctxt "@action:button"
msgid "Zoom toward mouse direction"
msgstr "In Mausrichtung zoomen"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:384
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:386
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:389
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:391
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:397
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:399
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:402
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:404
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:414
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:416
msgctxt "@info:tooltip"
msgid "Show caution message in gcode reader."
msgstr "Warnmeldung im G-Code-Reader anzeigen."
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:423
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:425
msgctxt "@option:check"
msgid "Caution message in gcode reader"
msgstr "Warnmeldung in G-Code-Reader"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:430
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:432
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:435
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:437
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:451
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:453
msgctxt "@label"
msgid "Opening and saving files"
msgstr "Dateien öffnen und speichern"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:457
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:459
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:462
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:464
msgctxt "@option:check"
msgid "Scale large models"
msgstr "Große Modelle anpassen"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:471
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:473
msgctxt "@info:tooltip"
msgid "An model may appear extremely small if its unit is for example in meters rather than millimeters. Should these models be scaled up?"
msgstr "Ein Modell kann extrem klein erscheinen, wenn seine Maßeinheit z. B. in Metern anstelle von Millimetern angegeben ist. Sollen diese Modelle hoch skaliert werden?"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:476
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:478
msgctxt "@option:check"
msgid "Scale extremely small models"
msgstr "Extrem kleine Modelle skalieren"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:485
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:487
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:490
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:492
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:499
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:501
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:503
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:505
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:512
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:514
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:520
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:522
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:533
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:535
msgctxt "@option:openProject"
msgid "Always ask"
msgstr "Immer nachfragen"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:534
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:536
msgctxt "@option:openProject"
msgid "Always open as a project"
msgstr "Immer als Projekt öffnen"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:535
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:537
msgctxt "@option:openProject"
msgid "Always import models"
msgstr "Modelle immer importieren"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:571
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:573
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:580
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:582
msgctxt "@label"
msgid "Override Profile"
msgstr "Profil überschreiben"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:629
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:631
msgctxt "@label"
msgid "Privacy"
msgstr "Privatsphäre"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:636
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:638
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:641
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:643
msgctxt "@option:check"
msgid "Check for updates on start"
msgstr "Bei Start nach Updates suchen"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:651
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:653
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:656
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:658
msgctxt "@option:check"
msgid "Send (anonymous) print information"
msgstr "(Anonyme) Druckinformationen senden"
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:674
+msgctxt "@label"
+msgid "Experimental"
+msgstr "Experimentell"
+
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:680
+msgctxt "@info:tooltip"
+msgid "Use multi build plate functionality"
+msgstr "Mehrfach-Druckplattenfunktion verwenden"
+
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:685
+msgctxt "@option:check"
+msgid "Use multi build plate functionality (restart required)"
+msgstr "Mehrfach-Druckplattenfunktion verwenden (Neustart erforderlich)"
+
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:694
+msgctxt "@info:tooltip"
+msgid "Should newly loaded models be arranged on the build plate? Used in conjunction with multi build plate (EXPERIMENTAL)"
+msgstr "Sollen neu geladene Modelle auf der Druckplatte angeordnet werden? In Verbindung mit Mehrfach-Druckplatte verwenden (EXPERIMENTELL)"
+
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:699
+msgctxt "@option:check"
+msgid "Do not arrange objects on load"
+msgstr "Keine Objekte beim Laden anordnen"
+
#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:15
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:444
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:514
msgctxt "@title:tab"
msgid "Printers"
msgstr "Drucker"
#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:37
#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:51
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:137
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:138
msgctxt "@action:button"
msgid "Activate"
msgstr "Aktivieren"
@@ -2883,7 +3195,7 @@ msgid "Waiting for a printjob"
msgstr "Warten auf einen Druckauftrag"
#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:15
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:448
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:518
msgctxt "@title:tab"
msgid "Profiles"
msgstr "Profile"
@@ -2909,13 +3221,13 @@ msgid "Duplicate"
msgstr "Duplizieren"
#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:113
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:201
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:182
msgctxt "@action:button"
msgid "Import"
msgstr "Import"
#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:119
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:212
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:193
msgctxt "@action:button"
msgid "Export"
msgstr "Export"
@@ -2981,7 +3293,7 @@ msgid "Export Profile"
msgstr "Profil exportieren"
#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:15
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:446
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:516
msgctxt "@title:tab"
msgid "Materials"
msgstr "Materialien"
@@ -2996,60 +3308,60 @@ msgctxt "@action:label %1 is printer name"
msgid "Printer: %1"
msgstr "Drucker: %1"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:149
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:150
msgctxt "@action:button"
msgid "Create"
msgstr "Erstellen"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:168
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:160
msgctxt "@action:button"
msgid "Duplicate"
msgstr "Duplizieren"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:311
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:319
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:298
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:306
msgctxt "@title:window"
msgid "Import Material"
msgstr "Material importieren"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:320
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:307
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/MaterialsPage.qml:324
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:311
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/MaterialsPage.qml:343
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:358
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:329
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:344
msgctxt "@title:window"
msgid "Export Material"
msgstr "Material exportieren"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:362
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:348
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/MaterialsPage.qml:368
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:354
msgctxt "@info:status Don't translate the XML tag !"
msgid "Successfully exported material to %1"
msgstr "Material erfolgreich nach %1 exportiert"
#: /home/ruben/Projects/Cura/resources/qml/AddMachineDialog.qml:18
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:793
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:869
msgctxt "@title:window"
msgid "Add Printer"
msgstr "Drucker hinzufügen"
-#: /home/ruben/Projects/Cura/resources/qml/AddMachineDialog.qml:185
+#: /home/ruben/Projects/Cura/resources/qml/AddMachineDialog.qml:194
msgctxt "@label"
msgid "Printer Name:"
msgstr "Druckername:"
-#: /home/ruben/Projects/Cura/resources/qml/AddMachineDialog.qml:208
+#: /home/ruben/Projects/Cura/resources/qml/AddMachineDialog.qml:217
msgctxt "@action:button"
msgid "Add Printer"
msgstr "Drucker hinzufügen"
@@ -3074,7 +3386,9 @@ 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.\nCura verwendet mit Stolz die folgenden Open Source-Projekte:"
+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"
@@ -3171,163 +3485,177 @@ 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:41
msgctxt "@label"
msgid "Profile:"
msgstr "Profil:"
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:66
-msgctxt "@"
-msgid "No Profile Available"
-msgstr "Kein Profil verfügbar"
-
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:104
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:102
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\nKlicken Sie, um den Profilmanager zu öffnen."
+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:152
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:150
msgctxt "@label:textbox"
msgid "Search..."
msgstr "Suchen..."
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:483
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:482
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:498
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:497
msgctxt "@action:menu"
msgid "Hide this setting"
msgstr "Diese Einstellung ausblenden"
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:508
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:507
msgctxt "@action:menu"
msgid "Don't show this setting"
msgstr "Diese Einstellung ausblenden"
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:512
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:511
msgctxt "@action:menu"
msgid "Keep this setting visible"
msgstr "Diese Einstellung weiterhin anzeigen"
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:531
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:530
msgctxt "@action:menu"
msgid "Configure setting visiblity..."
msgstr "Sichtbarkeit der Einstellung wird konfiguriert..."
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingCategory.qml:123
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingCategory.qml:250
msgctxt "@label"
msgid ""
"Some hidden settings use values different from their normal calculated value.\n"
"\n"
"Click to make these settings visible."
-msgstr "Einige ausgeblendete Einstellungen verwenden Werte, die von ihren normalen, berechneten Werten abweichen.\n\nKlicken Sie, um diese Einstellungen sichtbar zu machen."
+msgstr ""
+"Einige ausgeblendete Einstellungen verwenden Werte, die von ihren normalen, berechneten Werten abweichen.\n"
+"\n"
+"Klicken Sie, um diese Einstellungen sichtbar zu machen."
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:62
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:61
msgctxt "@label Header for list of settings."
msgid "Affects"
msgstr "Hat Einfluss auf"
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:67
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:66
msgctxt "@label Header for list of settings."
msgid "Affected By"
msgstr "Wird beeinflusst von"
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:157
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:156
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"
+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:160
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:159
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:186
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:190
msgctxt "@label"
msgid ""
"This setting has a value that is different from the profile.\n"
"\n"
"Click to restore the value of the profile."
-msgstr "Diese Einstellung hat einen vom Profil abweichenden Wert.\n\nKlicken Sie, um den Wert des Profils wiederherzustellen."
+msgstr ""
+"Diese Einstellung hat einen vom Profil abweichenden Wert.\n"
+"\n"
+"Klicken Sie, um den Wert des Profils wiederherzustellen."
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:284
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:288
msgctxt "@label"
msgid ""
"This setting is normally calculated, but it currently has an absolute value set.\n"
"\n"
"Click to restore the calculated value."
-msgstr "Diese Einstellung wird normalerweise berechnet; aktuell ist jedoch ein Absolutwert eingestellt.\n\nKlicken Sie, um den berechneten Wert wiederherzustellen."
+msgstr ""
+"Diese Einstellung wird normalerweise berechnet; aktuell ist jedoch ein Absolutwert eingestellt.\n"
+"\n"
+"Klicken Sie, um den berechneten Wert wiederherzustellen."
-#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:120
+#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:128
msgctxt "@label:listbox"
msgid "Print Setup"
msgstr "Druckeinrichtung"
-#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:120
+#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:128
msgctxt "@label:listbox"
msgid ""
"Print Setup disabled\n"
"G-code files cannot be modified"
-msgstr "Druckeinrichtung deaktiviert\nG-Code-Dateien können nicht geändert werden"
+msgstr ""
+"Druckeinrichtung deaktiviert\n"
+"G-Code-Dateien können nicht geändert werden"
-#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:336
+#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:342
msgctxt "@label Hours and minutes"
msgid "00h 00min"
msgstr "00 Stunden 00 Minuten"
-#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:354
+#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:359
msgctxt "@tooltip"
-msgid "Time specification
"
-msgstr "Zeitangabe
"
+msgid "Time specification"
+msgstr "Zeitangabe"
-#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:429
+#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:441
msgctxt "@label"
msgid "Cost specification"
msgstr "Kostenangabe"
-#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:434
-#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:445
+#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:446
+#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:455
msgctxt "@label m for meter"
msgid "%1m"
msgstr "%1 m"
-#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:435
-#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:446
+#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:447
+#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:456
msgctxt "@label g for grams"
msgid "%1g"
msgstr "%1 g"
-#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:444
+#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:454
msgctxt "@label"
msgid "Total:"
msgstr "Insgesamt:"
-#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:498
+#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:504
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/resources/qml/Sidebar.qml:503
+#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:509
msgctxt "@label Print estimates: m for meters, g for grams"
msgid "%1m / ~ %2g"
msgstr "%1m / ~ %2g"
-#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:586
+#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:591
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/Sidebar.qml:591
+#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:596
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/Menus/MaterialMenu.qml:49
+#: /home/ruben/Projects/Cura/resources/qml/Menus/MaterialMenu.qml:50
msgctxt "@title:menuitem %1 is the automatically selected material"
msgid "Automatic: %1"
msgstr "Automatisch: %1"
@@ -3337,6 +3665,16 @@ msgctxt "@title:menu menubar:toplevel"
msgid "&View"
msgstr "&Ansicht"
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ViewMenu.qml:37
+msgctxt "@action:inmenu menubar:view"
+msgid "&Camera position"
+msgstr "&Kameraposition"
+
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ViewMenu.qml:52
+msgctxt "@action:inmenu menubar:view"
+msgid "&Build plate"
+msgstr "&Druckplatte"
+
#: /home/ruben/Projects/Cura/resources/qml/Menus/NozzleMenu.qml:40
msgctxt "@title:menuitem %1 is the nozzle currently loaded in the printer"
msgid "Automatic: %1"
@@ -3349,14 +3687,14 @@ msgid_plural "Print Selected Models With:"
msgstr[0] "Ausgewähltes Modell drucken mit:"
msgstr[1] "Ausgewählte Modelle drucken mit:"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/ContextMenu.qml:83
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ContextMenu.qml:114
msgctxt "@title:window"
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/Menus/ContextMenu.qml:108
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ContextMenu.qml:139
msgctxt "@label"
msgid "Number of Copies"
msgstr "Anzahl Kopien"
@@ -3372,7 +3710,7 @@ msgid "No printer connected"
msgstr "Es ist kein Drucker verbunden"
#: /home/ruben/Projects/Cura/resources/qml/PrintMonitor.qml:90
-#: /home/ruben/Projects/Cura/resources/qml/SidebarHeader.qml:138
+#: /home/ruben/Projects/Cura/resources/qml/SidebarHeader.qml:139
msgctxt "@label"
msgid "Extruder"
msgstr "Extruder"
@@ -3482,254 +3820,294 @@ msgctxt "@label"
msgid "Estimated time left"
msgstr "Geschätzte verbleibende Zeit"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:72
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:79
msgctxt "@action:inmenu"
msgid "Toggle Fu&ll Screen"
msgstr "Umschalten auf Vo&llbild-Modus"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:79
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:86
msgctxt "@action:inmenu menubar:edit"
msgid "&Undo"
msgstr "&Rückgängig machen"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:89
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:96
msgctxt "@action:inmenu menubar:edit"
msgid "&Redo"
msgstr "&Wiederholen"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:99
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:106
msgctxt "@action:inmenu menubar:file"
msgid "&Quit"
msgstr "&Beenden"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:107
-msgctxt "@action:inmenu menubar:view"
-msgid "&Reset camera position"
-msgstr "&Kameraposition zurücksetzen"
-
#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:114
+msgctxt "@action:inmenu menubar:view"
+msgid "&3D View"
+msgstr "&3D-Ansicht"
+
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:121
+msgctxt "@action:inmenu menubar:view"
+msgid "&Front View"
+msgstr "&Vorderansicht"
+
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:128
+msgctxt "@action:inmenu menubar:view"
+msgid "&Top View"
+msgstr "&Draufsicht"
+
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:135
+msgctxt "@action:inmenu menubar:view"
+msgid "&Left Side View"
+msgstr "&Ansicht von links"
+
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:142
+msgctxt "@action:inmenu menubar:view"
+msgid "&Right Side View"
+msgstr "&Ansicht von rechts"
+
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:149
msgctxt "@action:inmenu"
msgid "Configure Cura..."
msgstr "Cura konfigurieren..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:121
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:156
msgctxt "@action:inmenu menubar:printer"
msgid "&Add Printer..."
msgstr "&Drucker hinzufügen..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:127
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:162
msgctxt "@action:inmenu menubar:printer"
msgid "Manage Pr&inters..."
msgstr "Dr&ucker verwalten..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:134
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:169
msgctxt "@action:inmenu"
msgid "Manage Materials..."
msgstr "Materialien werden verwaltet..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:142
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:177
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:150
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:185
msgctxt "@action:inmenu menubar:profile"
msgid "&Discard current changes"
msgstr "&Aktuelle Änderungen verwerfen"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:162
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:197
msgctxt "@action:inmenu menubar:profile"
msgid "&Create profile from current settings/overrides..."
msgstr "&Profil von aktuellen Einstellungen/Überschreibungen erstellen..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:168
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:203
msgctxt "@action:inmenu menubar:profile"
msgid "Manage Profiles..."
msgstr "Profile verwalten..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:175
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:210
msgctxt "@action:inmenu menubar:help"
msgid "Show Online &Documentation"
msgstr "Online-&Dokumentation anzeigen"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:183
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:218
msgctxt "@action:inmenu menubar:help"
msgid "Report a &Bug"
msgstr "&Fehler melden"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:191
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:226
msgctxt "@action:inmenu menubar:help"
msgid "&About..."
msgstr "&Über..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:198
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:233
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:208
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:243
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:217
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:252
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:226
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:261
msgctxt "@action:inmenu"
msgid "Delete Model"
msgstr "Modell löschen"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:234
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:269
msgctxt "@action:inmenu"
msgid "Ce&nter Model on Platform"
msgstr "Modell auf Druckplatte ze&ntrieren"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:240
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:275
msgctxt "@action:inmenu menubar:edit"
msgid "&Group Models"
msgstr "Modelle &gruppieren"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:250
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:295
msgctxt "@action:inmenu menubar:edit"
msgid "Ungroup Models"
msgstr "Gruppierung für Modelle aufheben"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:260
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:305
msgctxt "@action:inmenu menubar:edit"
msgid "&Merge Models"
msgstr "Modelle &zusammenführen"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:270
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:315
msgctxt "@action:inmenu"
msgid "&Multiply Model..."
msgstr "Modell &multiplizieren"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:277
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:322
msgctxt "@action:inmenu menubar:edit"
msgid "&Select All Models"
msgstr "Alle Modelle &wählen"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:287
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:332
msgctxt "@action:inmenu menubar:edit"
msgid "&Clear Build Plate"
msgstr "Druckplatte &reinigen"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:297
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:342
msgctxt "@action:inmenu menubar:file"
msgid "Re&load All Models"
msgstr "Alle Modelle neu &laden"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:306
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:351
+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:358
msgctxt "@action:inmenu menubar:edit"
msgid "Arrange All Models"
msgstr "Alle Modelle anordnen"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:314
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:366
msgctxt "@action:inmenu menubar:edit"
msgid "Arrange Selection"
msgstr "Anordnung auswählen"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:321
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:373
msgctxt "@action:inmenu menubar:edit"
msgid "Reset All Model Positions"
msgstr "Alle Modellpositionen zurücksetzen"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:328
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:380
msgctxt "@action:inmenu menubar:edit"
msgid "Reset All Model &Transformations"
msgstr "Alle Modell&transformationen zurücksetzen"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:335
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:387
msgctxt "@action:inmenu menubar:file"
msgid "&Open File(s)..."
msgstr "&Datei(en) öffnen..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:343
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:395
msgctxt "@action:inmenu menubar:file"
msgid "&New Project..."
msgstr "&Neues Projekt..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:350
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:402
msgctxt "@action:inmenu menubar:help"
msgid "Show Engine &Log..."
msgstr "Engine-&Protokoll anzeigen..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:358
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:410
msgctxt "@action:inmenu menubar:help"
msgid "Show Configuration Folder"
msgstr "Konfigurationsordner anzeigen"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:365
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:417
msgctxt "@action:menu"
msgid "Configure setting visibility..."
msgstr "Sichtbarkeit einstellen wird konfiguriert..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:372
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:424
msgctxt "@action:menu"
msgid "Browse plugins..."
msgstr "Plugins durchsuchen..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:379
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:431
msgctxt "@action:menu"
msgid "Installed plugins..."
msgstr "Installierte plugins..."
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:28
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:438
+msgctxt "@action:inmenu menubar:view"
+msgid "Expand/Collapse Sidebar"
+msgstr "Seitenleiste vergrößern/verkleinern"
+
+#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:26
msgctxt "@label:PrintjobStatus"
msgid "Please load a 3D model"
msgstr "Bitte laden Sie ein 3D-Modell"
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:34
+#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:36
msgctxt "@label:PrintjobStatus"
msgid "Ready to slice"
msgstr "Bereit zum Slicen (Schneiden)"
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:36
+#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:38
msgctxt "@label:PrintjobStatus"
msgid "Slicing..."
msgstr "Das Slicing läuft..."
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:38
+#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:40
msgctxt "@label:PrintjobStatus %1 is target operation"
msgid "Ready to %1"
msgstr "Bereit zum %1"
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:40
+#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:42
msgctxt "@label:PrintjobStatus"
msgid "Unable to Slice"
msgstr "Slicing nicht möglich"
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:42
+#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:44
msgctxt "@label:PrintjobStatus"
msgid "Slicing unavailable"
msgstr "Slicing ist nicht verfügbar"
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:162
+#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:171
+msgctxt "@info:tooltip"
+msgid "Slice current printjob"
+msgstr "Aktuellen Druckauftrag slicen"
+
+#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:171
+msgctxt "@info:tooltip"
+msgid "Cancel slicing process"
+msgstr "Slicing-Vorgang abbrechen"
+
+#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:183
msgctxt "@label:Printjob"
msgid "Prepare"
msgstr "Vorbereiten"
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:162
+#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:183
msgctxt "@label:Printjob"
msgid "Cancel"
msgstr "Abbrechen"
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:302
+#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:317
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:620
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:696
msgctxt "@title:window"
msgid "Open file(s)"
msgstr "Datei(en) öffnen"
@@ -3749,114 +4127,114 @@ msgctxt "@title:window"
msgid "Ultimaker Cura"
msgstr "Ultimaker Cura"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:81
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:102
msgctxt "@title:menu menubar:toplevel"
msgid "&File"
msgstr "&Datei"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:98
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:119
msgctxt "@action:inmenu menubar:file"
msgid "&Save Selection to File"
msgstr "Auswahl als Datei &speichern"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:107
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:128
msgctxt "@title:menu menubar:file"
msgid "Save &As..."
msgstr "Speichern &Als"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:118
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:139
msgctxt "@title:menu menubar:file"
-msgid "Save project"
-msgstr "Projekt speichern"
+msgid "Save &Project..."
+msgstr "&Projekt speichern..."
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:141
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:162
msgctxt "@title:menu menubar:toplevel"
msgid "&Edit"
msgstr "&Bearbeiten"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:158
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:179
msgctxt "@title:menu"
msgid "&View"
msgstr "&Ansicht"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:163
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:184
msgctxt "@title:menu"
msgid "&Settings"
msgstr "&Einstellungen"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:165
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:186
msgctxt "@title:menu menubar:toplevel"
msgid "&Printer"
msgstr "Dr&ucker"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:175
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:187
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:196
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:208
msgctxt "@title:menu"
msgid "&Material"
msgstr "&Material"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:176
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:188
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:197
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:209
msgctxt "@title:menu"
msgid "&Profile"
msgstr "&Profil"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:180
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:201
msgctxt "@action:inmenu"
msgid "Set as Active Extruder"
msgstr "Als aktiven Extruder festlegen"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:198
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:219
msgctxt "@title:menu menubar:toplevel"
msgid "E&xtensions"
msgstr "Er&weiterungen"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:232
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:253
msgctxt "@title:menu menubar:toplevel"
msgid "P&lugins"
msgstr "&Plugins"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:240
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:261
msgctxt "@title:menu menubar:toplevel"
msgid "P&references"
msgstr "E&instellungen"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:248
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:269
msgctxt "@title:menu menubar:toplevel"
msgid "&Help"
msgstr "&Hilfe"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:330
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:351
msgctxt "@action:button"
msgid "Open File"
msgstr "Datei öffnen"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:442
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:512
msgctxt "@title:tab"
msgid "Settings"
msgstr "Einstellungen"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:478
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:554
msgctxt "@title:window"
msgid "New project"
msgstr "Neues Projekt"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:479
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:555
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:721
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:797
msgctxt "@window:title"
msgid "Install Plugin"
msgstr "Plugin installieren"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:728
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:804
msgctxt "@title:window"
msgid "Open File(s)"
msgstr "Datei(en) öffnen"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:731
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:807
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."
@@ -3881,97 +4259,82 @@ 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:264
-msgctxt "@action:button"
-msgid "Save"
-msgstr "Speichern"
-
-#: /home/ruben/Projects/Cura/resources/qml/Topbar.qml:74
-msgctxt "@title:tab"
-msgid "Prepare"
-msgstr "Vorbereiten"
-
-#: /home/ruben/Projects/Cura/resources/qml/Topbar.qml:100
-msgctxt "@title:tab"
-msgid "Monitor"
-msgstr "Überwachen"
-
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:163
+#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:175
msgctxt "@label"
msgid "Layer Height"
msgstr "Schichtdicke"
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:323
+#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:345
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:340
+#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:362
msgctxt "@label"
msgid "Print Speed"
msgstr "Druckgeschwindigkeit"
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:350
+#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:374
msgctxt "@label"
msgid "Slower"
msgstr "Langsamer"
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:361
+#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:385
msgctxt "@label"
msgid "Faster"
msgstr "Schneller"
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:388
+#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:423
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:413
+#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:446
msgctxt "@label"
msgid "Infill"
msgstr "Füllung"
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:633
+#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:668
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:645
+#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:680
msgctxt "@label"
msgid "Enable gradual"
msgstr "Graduell aktivieren"
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:712
+#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:747
msgctxt "@label"
msgid "Generate Support"
msgstr "Stützstruktur generieren"
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:746
+#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:781
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:764
+#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:799
msgctxt "@label"
msgid "Support Extruder"
msgstr "Extruder für Stützstruktur"
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:816
+#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:851
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:839
+#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:874
msgctxt "@label"
msgid "Build Plate Adhesion"
msgstr "Druckplattenhaftung"
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:894
+#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:929
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:934
+#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:969
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>"
@@ -3988,17 +4351,22 @@ msgctxt "@title:window"
msgid "Open project file"
msgstr "Projektdatei öffnen"
-#: /home/ruben/Projects/Cura/resources/qml/AskOpenAsProjectOrModelsDialog.qml:72
+#: /home/ruben/Projects/Cura/resources/qml/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
+msgctxt "@text:window"
+msgid "Remember my choice"
+msgstr "Meine Auswahl merken"
+
+#: /home/ruben/Projects/Cura/resources/qml/AskOpenAsProjectOrModelsDialog.qml:122
msgctxt "@action:button"
msgid "Open as project"
msgstr "Als Projekt öffnen"
-#: /home/ruben/Projects/Cura/resources/qml/AskOpenAsProjectOrModelsDialog.qml:122
+#: /home/ruben/Projects/Cura/resources/qml/AskOpenAsProjectOrModelsDialog.qml:131
msgctxt "@action:button"
msgid "Import models"
msgstr "Modelle importieren"
@@ -4008,21 +4376,36 @@ msgctxt "@title:window"
msgid "Engine Log"
msgstr "Engine-Protokoll"
-#: /home/ruben/Projects/Cura/resources/qml/SidebarHeader.qml:242
+#: /home/ruben/Projects/Cura/resources/qml/SidebarHeader.qml:245
msgctxt "@label"
msgid "Material"
msgstr "Material"
-#: /home/ruben/Projects/Cura/resources/qml/SidebarHeader.qml:349
+#: /home/ruben/Projects/Cura/resources/qml/SidebarHeader.qml:352
msgctxt "@label"
-msgid "Check compatibility"
-msgstr "Kompatibilität prüfen"
+msgid "Check compatibility"
+msgstr "Kompatibilität prüfen"
-#: /home/ruben/Projects/Cura/resources/qml/SidebarHeader.qml:369
+#: /home/ruben/Projects/Cura/resources/qml/SidebarHeader.qml:372
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/ObjectsList.qml:211
+msgctxt "@option:check"
+msgid "See only current build plate"
+msgstr "Nur aktuelle Druckplatte anzeigen"
+
+#: /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/ObjectsList.qml:247
+msgctxt "@action:button"
+msgid "Arrange current build plate"
+msgstr "An aktueller Druckplatte ausrichten"
+
#: MachineSettingsAction/plugin.json
msgctxt "description"
msgid "Provides a way to change machine settings (such as build volume, nozzle size, etc)"
@@ -4113,6 +4496,26 @@ msgctxt "name"
msgid "USB printing"
msgstr "USB-Drucken"
+#: PrepareStage/plugin.json
+msgctxt "description"
+msgid "Provides a prepare stage in Cura."
+msgstr "Bietet eine Vorbereitungsstufe in Cura."
+
+#: PrepareStage/plugin.json
+msgctxt "name"
+msgid "Prepare Stage"
+msgstr "Vorbereitungsstufe"
+
+#: CuraLiveScriptingPlugin/plugin.json
+msgctxt "description"
+msgid "Provides an edit window for direct script editing."
+msgstr "Bietet ein Bearbeitungsfenster für direkte Skriptbearbeitung."
+
+#: CuraLiveScriptingPlugin/plugin.json
+msgctxt "name"
+msgid "Live scripting tool"
+msgstr "Live-Scripting-Tool"
+
#: RemovableDriveOutputDevice/plugin.json
msgctxt "description"
msgid "Provides removable drive hotplugging and writing support."
@@ -4133,6 +4536,16 @@ msgctxt "name"
msgid "UM3 Network Connection"
msgstr "UM3-Netzwerkverbindung"
+#: MonitorStage/plugin.json
+msgctxt "description"
+msgid "Provides a monitor stage in Cura."
+msgstr "Bietet eine Überwachungsstufe in Cura."
+
+#: MonitorStage/plugin.json
+msgctxt "name"
+msgid "Monitor Stage"
+msgstr "Überwachungsstufe"
+
#: FirmwareUpdateChecker/plugin.json
msgctxt "description"
msgid "Checks for firmware updates."
@@ -4145,8 +4558,8 @@ msgstr "Firmware-Update-Prüfer"
#: CuraSolidWorksPlugin/plugin.json
msgctxt "description"
-msgid "Gives you the possibility to open certain files via SolidWorks itself. These are then converted and loaded into Cura"
-msgstr "Bietet Ihnen die Möglichkeit, bestimmte Dateien über SolidWorks selbst zu öffnen. Diese werden anschließend konvertiert und in Cura geladen."
+msgid "Gives you the possibility to open certain files using SolidWorks itself. Conversion is done by this plugin and additional optimizations."
+msgstr "Bietet Ihnen die Möglichkeit, bestimmte Dateien über SolidWorks selbst zu öffnen. Die Konvertierung erfolgt über dieses Plugin und zusätzliche Optimierungen."
#: CuraSolidWorksPlugin/plugin.json
msgctxt "name"
@@ -4213,6 +4626,16 @@ msgctxt "name"
msgid "Legacy Cura Profile Reader"
msgstr "Cura-Vorgängerprofil-Reader"
+#: CuraBlenderPlugin/plugin.json
+msgctxt "description"
+msgid "Helps to open Blender files directly in Cura."
+msgstr "Unterstützt das Öffnen der Blender-Dateien direkt in Cura."
+
+#: CuraBlenderPlugin/plugin.json
+msgctxt "name"
+msgid "Blender Integration (experimental)"
+msgstr "Blender-Integration (experimentell)"
+
#: GCodeProfileReader/plugin.json
msgctxt "description"
msgid "Provides support for importing profiles from g-code files."
@@ -4373,6 +4796,16 @@ msgctxt "name"
msgid "Cura Profile Writer"
msgstr "Cura-Profil-Writer"
+#: CuraPrintProfileCreator/plugin.json
+msgctxt "description"
+msgid "Allows material manufacturers to create new material and quality profiles using a drop-in UI."
+msgstr "Ermöglichen Sie Materialherstellern die Erstellung neuer Material- und Qualitätsprofile, indem Sie eine Drop-In-Benutzerschnittstelle verwenden."
+
+#: CuraPrintProfileCreator/plugin.json
+msgctxt "name"
+msgid "Print Profile Assistant"
+msgstr "Druckprofil-Assistent"
+
#: 3MFWriter/plugin.json
msgctxt "description"
msgid "Provides support for writing 3MF files."
@@ -4413,6 +4846,156 @@ msgctxt "name"
msgid "Cura Profile Reader"
msgstr "Cura-Profil-Reader"
+#~ msgctxt "@label"
+#~ msgid "Unknown"
+#~ msgstr "Unbekannt"
+
+#~ msgctxt "@info:status"
+#~ msgid "Errors appeared while opening your SolidWorks file! Please check, whether it is possible to open your file in SolidWorks itself without any problems as well!"
+#~ msgstr "Beim Öffnen Ihrer SolidWorks Datei trat ein Fehler auf! Überprüfen Sie bitte, ob sich Ihre Datei in SolidWorks ohne Probleme öffnen lässt!"
+
+#~ msgctxt "@info:status"
+#~ msgid "Error while starting %s!"
+#~ msgstr "Fehler beim Starten %s!"
+
+#~ msgctxt "@item:inlistbox"
+#~ msgid "Simulation view"
+#~ msgstr "Simulationsansicht"
+
+#~ msgctxt "@info"
+#~ msgid "Cura collects anonymised slicing statistics. You can disable this in the preferences."
+#~ msgstr "Cura erfasst anonymisierte Slice-Informationen. Sie können dies in den Einstellungen deaktivieren."
+
+#~ msgctxt "@action:button"
+#~ msgid "Dismiss"
+#~ msgstr "Verwerfen"
+
+#~ msgctxt "@menuitem"
+#~ msgid "Global"
+#~ msgstr "Global"
+
+#~ msgctxt "@label crash message"
+#~ msgid ""
+#~ "
A fatal exception has occurred. Please send us this Crash Report to fix the problem
\n"
+#~ "
Please use the \"Send report\" button to post a bug report automatically to our servers
\n"
+#~ " "
+#~ msgstr ""
+#~ "
Ein schwerer Ausnahmefehler ist aufgetreten. Senden Sie uns diesen Absturzbericht, um das Problem zu beheben
\n"
+#~ "
Verwenden Sie bitte die Schaltfläche „Bericht senden“, um den Fehlerbericht automatisch an unsere Server zu senden
"
+
+#~ msgctxt "@action:inmenu menubar:view"
+#~ msgid "&Reset camera position"
+#~ msgstr "&Kameraposition zurücksetzen"
+
+#~ msgctxt "@title:menu menubar:file"
+#~ msgid "Save project"
+#~ msgstr "Projekt speichern"
+
+#~ msgctxt "@title:tab"
+#~ msgid "Prepare"
+#~ msgstr "Vorbereiten"
+
+#~ msgctxt "@title:tab"
+#~ msgid "Monitor"
+#~ msgstr "Überwachen"
+
+#~ msgctxt "@label"
+#~ msgid "Check compatibility"
+#~ msgstr "Kompatibilität prüfen"
+
+#~ msgctxt "description"
+#~ msgid "Gives you the possibility to open certain files via SolidWorks itself. These are then converted and loaded into Cura"
+#~ msgstr "Bietet Ihnen die Möglichkeit, bestimmte Dateien über SolidWorks selbst zu öffnen. Diese werden anschließend konvertiert und in Cura geladen."
+
#~ msgctxt "@label:status"
#~ msgid "Blocked"
#~ msgstr "Blockiert"
@@ -4433,13 +5016,9 @@ msgstr "Cura-Profil-Reader"
#~ msgid "To ensure that your {machine_name} is equipped with the latest features it is recommended to update the firmware regularly. This can be done on the {machine_name} (when connected to the network) or via USB."
#~ msgstr "Um sicherzustellen, dass Ihr {machine_name} mit den neuesten Funktionen ausgestattet ist, wird empfohlen, die Firmware regelmäßig zu aktualisieren Dies kann auf dem {machine_name} (bei Anschluss an ein Netzwerk) oder über USB erfolgen."
-msgctxt "@item:inlistbox"
-msgid "Layer view"
-msgstr "Schichtenansicht"
-
-msgctxt "@info:title"
-msgid "Layer View"
-msgstr "Schichtenansicht"
+#~ msgctxt "@info:title"
+#~ msgid "Layer View"
+#~ msgstr "Schichtenansicht"
#~ msgctxt "@menuitem"
#~ msgid "Browse plugins"
@@ -4541,9 +5120,9 @@ msgstr "Schichtenansicht"
#~ msgid "Provides the Layer view."
#~ msgstr "Bietet eine Schichtenansicht."
-msgctxt "name"
-msgid "Layer View"
-msgstr "Schichtenansicht"
+#~ msgctxt "name"
+#~ msgid "Layer View"
+#~ msgstr "Schichtenansicht"
#~ msgctxt "@item:inlistbox"
#~ msgid "X-Ray"
@@ -4864,9 +5443,9 @@ msgstr "Schichtenansicht"
#~ msgid "Provides support for importing profiles from g-code files."
#~ msgstr "Ermöglicht das Importieren von Profilen aus G-Code-Dateien."
-msgctxt "@label"
-msgid "Layer View"
-msgstr "Schichtenansicht"
+#~ msgctxt "@label"
+#~ msgid "Layer View"
+#~ msgstr "Schichtenansicht"
#~ msgctxt "@info:whatsthis"
#~ msgid "Provides the Layer view."
diff --git a/resources/i18n/de_DE/fdmextruder.def.json.po b/resources/i18n/de_DE/fdmextruder.def.json.po
index 1108f1a541..4c81c54c35 100644
--- a/resources/i18n/de_DE/fdmextruder.def.json.po
+++ b/resources/i18n/de_DE/fdmextruder.def.json.po
@@ -1,13 +1,13 @@
-# Cura JSON setting files
-# Copyright (C) 2017 Ultimaker
+# Cura
+# Copyright (C) 2018 Ultimaker
# This file is distributed under the same license as the Cura package.
-# Ruben Dulek , 2017.
-#
+# Ruben Dulek , 2018.
+#
msgid ""
msgstr ""
-"Project-Id-Version: Cura 3.0\n"
-"Report-Msgid-Bugs-To: http://github.com/ultimaker/uranium\n"
-"POT-Creation-Date: 2017-11-21 16:58+0000\n"
+"Project-Id-Version: Cura 3.2\n"
+"Report-Msgid-Bugs-To: r.dulek@ultimaker.com\n"
+"POT-Creation-Date: 2017-08-02 16:53+0000\n"
"PO-Revision-Date: 2017-11-30 13:05+0100\n"
"Last-Translator: Bothof \n"
"Language-Team: German\n"
diff --git a/resources/i18n/de_DE/fdmprinter.def.json.po b/resources/i18n/de_DE/fdmprinter.def.json.po
index 337df8bff2..95422bb589 100644
--- a/resources/i18n/de_DE/fdmprinter.def.json.po
+++ b/resources/i18n/de_DE/fdmprinter.def.json.po
@@ -1,13 +1,13 @@
-# Cura JSON setting files
-# Copyright (C) 2017 Ultimaker
+# Cura
+# Copyright (C) 2018 Ultimaker
# This file is distributed under the same license as the Cura package.
-# Ruben Dulek , 2017.
-#
+# Ruben Dulek , 2018.
+#
msgid ""
msgstr ""
-"Project-Id-Version: Cura 3.0\n"
-"Report-Msgid-Bugs-To: http://github.com/ultimaker/uranium\n"
-"POT-Creation-Date: 2017-11-21 16:58+0000\n"
+"Project-Id-Version: Cura 3.2\n"
+"Report-Msgid-Bugs-To: r.dulek@ultimaker.com\n"
+"POT-Creation-Date: 2018-01-29 09:48+0000\n"
"PO-Revision-Date: 2017-11-30 13:05+0100\n"
"Last-Translator: Bothof \n"
"Language-Team: German\n"
@@ -345,6 +345,16 @@ msgctxt "machine_gcode_flavor option Repetier"
msgid "Repetier"
msgstr "Repetier"
+#: fdmprinter.def.json
+msgctxt "machine_firmware_retract label"
+msgid "Firmware Retraction"
+msgstr "Firmware-Einzug"
+
+#: fdmprinter.def.json
+msgctxt "machine_firmware_retract description"
+msgid "Whether to use firmware retract commands (G10/G11) instead of using the E property in G1 commands to retract the material."
+msgstr "Definiert, ob Firmware-Einzugsbefehle (G10/G11) anstelle der E-Eigenschaft in G1-Befehlen verwendet wird, um das Material einzuziehen."
+
#: fdmprinter.def.json
msgctxt "machine_disallowed_areas label"
msgid "Disallowed areas"
@@ -605,31 +615,6 @@ msgctxt "layer_height_0 description"
msgid "The height of the initial layer in mm. A thicker initial layer makes adhesion to the build plate easier."
msgstr "Die Dicke der ersten Schicht in mm. Eine dicke erste Schicht erleichtert die Haftung am Druckbett."
-#: fdmprinter.def.json
-msgctxt "slicing_tolerance label"
-msgid "Slicing Tolerance"
-msgstr "Slicing-Toleranz"
-
-#: fdmprinter.def.json
-msgctxt "slicing_tolerance description"
-msgid "How to slice layers with diagonal surfaces. The areas of a layer can be generated based on where the middle of the layer intersects the surface (Middle). Alternatively each layer can have the areas which fall inside of the volume throughout the height of the layer (Exclusive) or a layer has the areas which fall inside anywhere within the layer (Inclusive). Exclusive retains the most details, Inclusive makes for the best fit and Middle takes the least time to process."
-msgstr "Slicen von Schichten mit diagonalen Flächen. Die Bereiche einer Schicht können anhand der Position generiert werden, an der die Mitte einer Schicht die Oberfläche kreuzt (Mitte). Optional kann jede Schicht die Bereiche enthalten, die in das Volumen entlang der Höhe der Schicht (Exklusiv) fallen oder eine Schicht enthält die Bereiche, die irgendwo innerhalb der Schicht positioniert sind (Inklusiv). Exklusiv bewahrt die meisten Details, Inklusiv ermöglicht die beste Passform und Mitte erfordert die kürzeste Bearbeitungszeit."
-
-#: fdmprinter.def.json
-msgctxt "slicing_tolerance option middle"
-msgid "Middle"
-msgstr "Mitte"
-
-#: fdmprinter.def.json
-msgctxt "slicing_tolerance option exclusive"
-msgid "Exclusive"
-msgstr "Exklusiv"
-
-#: fdmprinter.def.json
-msgctxt "slicing_tolerance option inclusive"
-msgid "Inclusive"
-msgstr "Inklusiv"
-
#: fdmprinter.def.json
msgctxt "line_width label"
msgid "Line Width"
@@ -670,16 +655,6 @@ msgctxt "wall_line_width_x description"
msgid "Width of a single wall line for all wall lines except the outermost one."
msgstr "Die Breite einer einzelnen Wandlinie für alle Wandlinien, außer der äußersten."
-#: fdmprinter.def.json
-msgctxt "roofing_line_width label"
-msgid "Top Surface Skin Line Width"
-msgstr "Oberfläche Außenhaut Linienbreite"
-
-#: fdmprinter.def.json
-msgctxt "roofing_line_width description"
-msgid "Width of a single line of the areas at the top of the print."
-msgstr "Die Breite einer einzelnen Linie der oberen Druckbereiche."
-
#: fdmprinter.def.json
msgctxt "skin_line_width label"
msgid "Top/Bottom Line Width"
@@ -860,41 +835,6 @@ msgctxt "roofing_layer_count description"
msgid "The number of top most skin layers. Usually only one top most layer is sufficient to generate higher quality top surfaces."
msgstr "Die Anzahl der obersten Außenhautschichten. Üblicherweise reicht eine einzige oberste Schicht aus, um höherwertige Oberflächen zu generieren."
-#: fdmprinter.def.json
-msgctxt "roofing_pattern label"
-msgid "Top Surface Skin Pattern"
-msgstr "Oberfläche Außenhaut Muster"
-
-#: fdmprinter.def.json
-msgctxt "roofing_pattern description"
-msgid "The pattern of the top most layers."
-msgstr "Das Muster der obersten Schichten."
-
-#: fdmprinter.def.json
-msgctxt "roofing_pattern option lines"
-msgid "Lines"
-msgstr "Linien"
-
-#: fdmprinter.def.json
-msgctxt "roofing_pattern option concentric"
-msgid "Concentric"
-msgstr "Konzentrisch"
-
-#: fdmprinter.def.json
-msgctxt "roofing_pattern option zigzag"
-msgid "Zig Zag"
-msgstr "Zickzack"
-
-#: fdmprinter.def.json
-msgctxt "roofing_angles label"
-msgid "Top Surface Skin Line Directions"
-msgstr "Linienrichtungen der Oberfläche Außenhaut"
-
-#: fdmprinter.def.json
-msgctxt "roofing_angles description"
-msgid "A list of integer line directions to use when the top surface skin layers use the lines or zig zag pattern. 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 traditional default angles (45 and 135 degrees)."
-msgstr "Eine Liste von Ganzzahl-Linienrichtungen für den Fall, wenn die oberen Außenhautschichten die Linien- oder Zickzack-Muster verwenden. Elemente aus der Liste werden während des Aufbaus der Schichten sequentiell verwendet und wenn das Listenende erreicht wird, beginnt die Liste von vorne. Die Listenobjekte werden durch Kommas getrennt und die gesamte Liste ist in eckige Klammern gesetzt. Standardmäßig ist eine leere Liste vorhanden, was bedeutet, dass herkömmliche Standardwinkel (45- und 135-Grad) verwendet werden."
-
#: fdmprinter.def.json
msgctxt "top_bottom_extruder_nr label"
msgid "Top/Bottom Extruder"
@@ -1025,6 +965,16 @@ msgctxt "wall_0_inset description"
msgid "Inset applied to the path of the outer wall. If the outer wall is smaller than the nozzle, and printed after the inner walls, use this offset to get the hole in the nozzle to overlap with the inner walls instead of the outside of the model."
msgstr "Verwendete Einfügung am Pfad zur Außenwand. Wenn die Außenwand kleiner als die Düse ist und nach den Innenwänden gedruckt wird, verwenden Sie diesen Versatz, damit die Öffnung in der Düse mit den Innenwänden überlappt, anstelle mit der Außenseite des Modells."
+#: fdmprinter.def.json
+msgctxt "optimize_wall_printing_order label"
+msgid "Optimize Wall Printing Order"
+msgstr "Reihenfolge des Wanddrucks optimieren"
+
+#: fdmprinter.def.json
+msgctxt "optimize_wall_printing_order description"
+msgid "Optimize the order in which walls are printed so as to reduce the number of retractions and the distance travelled. Most parts will benefit from this being enabled but some may actually take longer so please compare the print time estimates with and without optimization."
+msgstr "Optimieren Sie die Reihenfolge, in der die Wände gedruckt werden, um die Anzahl der Einzüge und die zurückgelegten Distanzen zu reduzieren. Dieser Schritt bringt für die meisten Teile Vorteile, allerdings werden einige möglicherweise länger benötigen. Vergleichen Sie deshalb bitte die Schätzung der Druckzeiten mit und ohne Optimierung."
+
#: fdmprinter.def.json
msgctxt "outer_inset_first label"
msgid "Outer Before Inner Walls"
@@ -1095,6 +1045,16 @@ msgctxt "fill_perimeter_gaps option everywhere"
msgid "Everywhere"
msgstr "Überall"
+#: fdmprinter.def.json
+msgctxt "filter_out_tiny_gaps label"
+msgid "Filter Out Tiny Gaps"
+msgstr "Kleine Lücken ausfiltern"
+
+#: fdmprinter.def.json
+msgctxt "filter_out_tiny_gaps description"
+msgid "Filter out tiny gaps to reduce blobs on outside of model."
+msgstr "Kleine Lücken ausfiltern, um Tropfen an der Außenseite des Modells zu reduzieren."
+
#: fdmprinter.def.json
msgctxt "fill_outline_gaps label"
msgid "Print Thin Walls"
@@ -1477,8 +1437,8 @@ msgstr "X-Versatz Füllung"
#: fdmprinter.def.json
msgctxt "infill_offset_x description"
-msgid "The infill pattern is offset this distance along the X axis."
-msgstr "Das Füllmuster wird um diese Distanz entlang der X-Achse versetzt."
+msgid "The infill pattern is moved this distance along the X axis."
+msgstr "Das Füllmuster wird um diese Distanz entlang der X-Achse verschoben."
#: fdmprinter.def.json
msgctxt "infill_offset_y label"
@@ -1487,8 +1447,8 @@ msgstr "Y-Versatz Füllung"
#: fdmprinter.def.json
msgctxt "infill_offset_y description"
-msgid "The infill pattern is offset this distance along the Y axis."
-msgstr "Das Füllmuster wird um diese Distanz entlang der Y-Achse versetzt."
+msgid "The infill pattern is moved this distance along the Y axis."
+msgstr "Das Füllmuster wird um diese Distanz entlang der Y-Achse verschoben."
#: fdmprinter.def.json
msgctxt "sub_div_rad_add label"
@@ -1507,8 +1467,8 @@ msgstr "Prozentsatz Füllung überlappen"
#: fdmprinter.def.json
msgctxt "infill_overlap description"
-msgid "The amount of overlap between the infill and the walls. A slight overlap allows the walls to connect firmly to the infill."
-msgstr "Das Ausmaß des Überlappens zwischen der Füllung und den Wänden. Ein leichtes Überlappen ermöglicht es den Wänden, eine solide Verbindung mit der Füllung herzustellen."
+msgid "The amount of overlap between the infill and the walls as a percentage of the infill line width. A slight overlap allows the walls to connect firmly to the infill."
+msgstr "Das Ausmaß des Überlappens zwischen der Füllung und den Wänden als Prozentwert der Füllungslinienbreite. Ein leichtes Überlappen ermöglicht es den Wänden, eine solide Verbindung mit der Füllung herzustellen."
#: fdmprinter.def.json
msgctxt "infill_overlap_mm label"
@@ -1527,8 +1487,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 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 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 "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."
#: fdmprinter.def.json
msgctxt "skin_overlap_mm label"
@@ -1690,16 +1650,6 @@ msgctxt "material description"
msgid "Material"
msgstr "Material"
-#: fdmprinter.def.json
-msgctxt "material_flow_dependent_temperature label"
-msgid "Auto Temperature"
-msgstr "Automatische Temperatur"
-
-#: fdmprinter.def.json
-msgctxt "material_flow_dependent_temperature description"
-msgid "Change the temperature for each layer automatically with the average flow speed of that layer."
-msgstr "Die Temperatur wird für jede Schicht automatisch anhand der durchschnittlichen Fließgeschwindigkeit dieser Schicht geändert."
-
#: fdmprinter.def.json
msgctxt "default_material_print_temperature label"
msgid "Default Printing Temperature"
@@ -1750,16 +1700,6 @@ msgctxt "material_final_print_temperature description"
msgid "The temperature to which to already start cooling down just before the end of printing."
msgstr "Die Temperatur, bei der das Abkühlen bereits beginnen kann, bevor der Druck beendet wird."
-#: fdmprinter.def.json
-msgctxt "material_flow_temp_graph label"
-msgid "Flow Temperature Graph"
-msgstr "Fließtemperaturgraf"
-
-#: fdmprinter.def.json
-msgctxt "material_flow_temp_graph description"
-msgid "Data linking material flow (in mm3 per second) to temperature (degrees Celsius)."
-msgstr "Der Materialfluss (in mm3 pro Sekunde) in Bezug zur Temperatur (Grad Celsius)."
-
#: fdmprinter.def.json
msgctxt "material_extrusion_cool_down_speed label"
msgid "Extrusion Cool Down Speed Modifier"
@@ -1777,8 +1717,8 @@ msgstr "Temperatur Druckplatte"
#: fdmprinter.def.json
msgctxt "material_bed_temperature description"
-msgid "The temperature used for the heated build plate. If this is 0, the bed will not heat up for this print."
-msgstr "Die Temperatur, die für die erhitzte Druckplatte verwendet wird. Wenn dieser Wert 0 beträgt, wird das Bett für diesen Druck nicht erhitzt."
+msgid "The temperature used for the heated build plate. If this is 0, the bed temperature will not be adjusted."
+msgstr "Die Temperatur, die für die erhitzte Druckplatte verwendet wird. Wenn dieser Wert 0 beträgt, wird die Betttemperatur nicht angepasst."
#: fdmprinter.def.json
msgctxt "material_bed_temperature_layer_0 label"
@@ -3450,6 +3390,16 @@ msgctxt "support_tower_roof_angle description"
msgid "The angle of a rooftop of a tower. A higher value results in pointed tower roofs, a lower value results in flattened tower roofs."
msgstr "Der Winkel eines Pfeilerdachs. Ein höherer Wert hat spitze Pfeilerdächer zur Folge, ein niedrigerer Wert führt zu flacheren Pfeilerdächern."
+#: fdmprinter.def.json
+msgctxt "support_mesh_drop_down label"
+msgid "Drop Down Support Mesh"
+msgstr "Stütznetz ablegen"
+
+#: fdmprinter.def.json
+msgctxt "support_mesh_drop_down description"
+msgid "Make support everywhere below the support mesh, so that there's no overhang in the support mesh."
+msgstr "Sorgt für Unterstützung überall unterhalb des Stütznetzes, sodass kein Überhang im Stütznetz vorhanden ist."
+
#: fdmprinter.def.json
msgctxt "platform_adhesion label"
msgid "Build Plate Adhesion"
@@ -4082,16 +4032,6 @@ msgctxt "meshfix_keep_open_polygons description"
msgid "Normally Cura tries to stitch up small holes in the mesh and remove parts of a layer with big holes. Enabling this option keeps those parts which cannot be stitched. This option should be used as a last resort option when everything else fails to produce proper GCode."
msgstr "Normalerweise versucht Cura kleine Löcher im Netz abzudecken und Teile von Schichten, die große Löcher aufweisen, zu entfernen. Die Aktivierung dieser Option erhält jene Teile, die nicht abgedeckt werden können. Diese Option sollte nur als letzter Ausweg verwendet werden, wenn es ansonsten nicht möglich ist, einen korrekten G-Code zu berechnen."
-#: fdmprinter.def.json
-msgctxt "meshfix_maximum_resolution label"
-msgid "Maximum Resolution"
-msgstr "Maximale Auflösung"
-
-#: fdmprinter.def.json
-msgctxt "meshfix_maximum_resolution description"
-msgid "The minimum size of a line segment after slicing. If you increase this, the mesh will have a lower resolution. This may allow the printer to keep up with the speed it has to process g-code and will increase slice speed by removing details of the mesh that it can't process anyway."
-msgstr "Die Mindestgröße eines Linienabschnitts nach dem Slicen. Wenn Sie diesen Wert erhöhen, führt dies zu einer niedrigeren Auslösung des Mesh. Damit kann der Drucker die erforderliche Geschwindigkeit für die Verarbeitung des G-Codes beibehalten; außerdem wird die Slice-Geschwindigkeit erhöht, indem Details des Mesh entfernt werden, die ohnehin nicht verarbeitet werden können."
-
#: fdmprinter.def.json
msgctxt "multiple_mesh_overlap label"
msgid "Merged Meshes Overlap"
@@ -4242,16 +4182,6 @@ msgctxt "support_mesh description"
msgid "Use this mesh to specify support areas. This can be used to generate support structure."
msgstr "Dieses Netz wird verwendet, um festzulegen, welche Bereiche gestützt werden sollen. Dies kann verwendet werden, um eine Stützstruktur zu errichten."
-#: fdmprinter.def.json
-msgctxt "support_mesh_drop_down label"
-msgid "Drop Down Support Mesh"
-msgstr "Stütznetz ablegen"
-
-#: fdmprinter.def.json
-msgctxt "support_mesh_drop_down description"
-msgid "Make support everywhere below the support mesh, so that there's no overhang in the support mesh."
-msgstr "Sorgt für Unterstützung überall unterhalb des Stütznetzes, sodass kein Überhang im Stütznetz vorhanden ist."
-
#: fdmprinter.def.json
msgctxt "anti_overhang_mesh label"
msgid "Anti Overhang Mesh"
@@ -4328,14 +4258,194 @@ msgid "experimental!"
msgstr "experimentell!"
#: fdmprinter.def.json
-msgctxt "optimize_wall_printing_order label"
-msgid "Optimize Wall Printing Order"
-msgstr "Reihenfolge des Wanddrucks optimieren"
+msgctxt "support_tree_enable label"
+msgid "Tree Support"
+msgstr "Baumstruktur"
#: fdmprinter.def.json
-msgctxt "optimize_wall_printing_order description"
-msgid "Optimize the order in which walls are printed so as to reduce the number of retractions and the distance travelled. Most parts will benefit from this being enabled but some may actually take longer so please compare the print time estimates with and without optimization."
-msgstr "Optimieren Sie die Reihenfolge, in der die Wände gedruckt werden, um die Anzahl der Einzüge und die zurückgelegten Distanzen zu reduzieren. Dieser Schritt bringt für die meisten Teile Vorteile, allerdings werden einige möglicherweise länger benötigen. Vergleichen Sie deshalb bitte die Schätzung der Druckzeiten mit und ohne Optimierung."
+msgctxt "support_tree_enable description"
+msgid "Generate a tree-like support with branches that support your print. This may reduce material usage and print time, but greatly increases slicing time."
+msgstr "Erstellen Sie eine baumähnliche Stützstruktur mit Ästen, die Ihren Druck stützen. Das reduziert möglicherweise den Materialverbrauch und die Druckdauer, erhöht jedoch die Slicing-Dauer erheblich."
+
+#: fdmprinter.def.json
+msgctxt "support_tree_angle label"
+msgid "Tree Support Branch Angle"
+msgstr "Astwinkel der Baumstützstruktur"
+
+#: fdmprinter.def.json
+msgctxt "support_tree_angle description"
+msgid "The angle of the branches. Use a lower angle to make them more vertical and more stable. Use a higher angle to be able to have more reach."
+msgstr "Dies bezeichnet den Winkel der Äste. Verwenden Sie einen geringeren Winkel, um sie vertikaler und stabiler zu gestalten. Verwenden Sie einen stärkeren Winkel, um mehr Reichweite zu erhalten."
+
+#: fdmprinter.def.json
+msgctxt "support_tree_branch_distance label"
+msgid "Tree Support Branch Distance"
+msgstr "Astabstand der Baumstützstruktur"
+
+#: fdmprinter.def.json
+msgctxt "support_tree_branch_distance description"
+msgid "How far apart the branches need to be when they touch the model. Making this distance small will cause the tree support to touch the model at more points, causing better overhang but making support harder to remove."
+msgstr "Dies beschreibt, wie weit die Äste weg sein müssen, wenn sie das Modell berühren. Eine geringe Entfernung lässt die Baumstützstruktur das Modell an mehreren Punkten berühren, und führt zu einem besseren Überhang, allerdings lässt sich die Stützstruktur auch schwieriger entfernen."
+
+#: fdmprinter.def.json
+msgctxt "support_tree_branch_diameter label"
+msgid "Tree Support Branch Diameter"
+msgstr "Astdurchmesser der Baumstützstruktur"
+
+#: fdmprinter.def.json
+msgctxt "support_tree_branch_diameter description"
+msgid "The diameter of the thinnest branches of tree support. Thicker branches are more sturdy. Branches towards the base will be thicker than this."
+msgstr "Dies beschreibt den Durchmesser der dünnsten Äste der Baumstützstruktur. Dickere Äste sind stabiler. Äste zur Basis hin werden dicker als diese sein."
+
+#: fdmprinter.def.json
+msgctxt "support_tree_branch_diameter_angle label"
+msgid "Tree Support Branch Diameter Angle"
+msgstr "Winkel Astdurchmesser der Baumstützstruktur"
+
+#: fdmprinter.def.json
+msgctxt "support_tree_branch_diameter_angle description"
+msgid "The angle of the branches' diameter as they gradually become thicker towards the bottom. An angle of 0 will cause the branches to have uniform thickness over their length. A bit of an angle can increase stability of the tree support."
+msgstr "Dies beschreibt den Winkel der Astdurchmesser, da sie stufenweise zum Boden hin dicker werden. Ein Winkel von 0 lässt die Äste über die gesamte Länge hinweg eine gleiche Dicke haben. Ein geringer Winkel kann die Stabilität der Baumstützstruktur erhöhen."
+
+#: fdmprinter.def.json
+msgctxt "support_tree_collision_resolution label"
+msgid "Tree Support Collision Resolution"
+msgstr "Kollisionsauflösung der Baumstützstruktur"
+
+#: fdmprinter.def.json
+msgctxt "support_tree_collision_resolution description"
+msgid "Resolution to compute collisions with to avoid hitting the model. Setting this lower will produce more accurate trees that fail less often, but increases slicing time dramatically."
+msgstr "Dies ist die Auflösung für die Berechnung von Kollisionen, um ein Anschlagen des Modells zu verhindern. Eine niedrigere Einstellung sorgt für akkuratere Bäume, die weniger häufig fehlschlagen, erhöht jedoch die Slicing-Zeit erheblich."
+
+#: fdmprinter.def.json
+msgctxt "support_tree_wall_thickness label"
+msgid "Tree Support Wall Thickness"
+msgstr "Wanddicke der Baumstützstruktur"
+
+#: fdmprinter.def.json
+msgctxt "support_tree_wall_thickness description"
+msgid "The thickness of the walls of the branches of tree support. Thicker walls take longer to print but don't fall over as easily."
+msgstr "Das ist die Dicke der Astwände der Baumstützstruktur. Dickere Wände benötigen eine längere Druckdauer, fallen jedoch nicht so leicht um."
+
+#: fdmprinter.def.json
+msgctxt "support_tree_wall_count label"
+msgid "Tree Support Wall Line Count"
+msgstr "Anzahl der Wandlinien der Baumstützstruktur"
+
+#: fdmprinter.def.json
+msgctxt "support_tree_wall_count description"
+msgid "The number of walls of the branches of tree support. Thicker walls take longer to print but don't fall over as easily."
+msgstr "Das ist die Anzahl der Astwände der Baumstützstruktur. Dickere Wände benötigen eine längere Druckdauer, fallen jedoch nicht so leicht um."
+
+#: fdmprinter.def.json
+msgctxt "slicing_tolerance label"
+msgid "Slicing Tolerance"
+msgstr "Slicing-Toleranz"
+
+#: fdmprinter.def.json
+msgctxt "slicing_tolerance description"
+msgid "How to slice layers with diagonal surfaces. The areas of a layer can be generated based on where the middle of the layer intersects the surface (Middle). Alternatively each layer can have the areas which fall inside of the volume throughout the height of the layer (Exclusive) or a layer has the areas which fall inside anywhere within the layer (Inclusive). Exclusive retains the most details, Inclusive makes for the best fit and Middle takes the least time to process."
+msgstr "Slicen von Schichten mit diagonalen Flächen. Die Bereiche einer Schicht können anhand der Position generiert werden, an der die Mitte einer Schicht die Oberfläche kreuzt (Mitte). Optional kann jede Schicht die Bereiche enthalten, die in das Volumen entlang der Höhe der Schicht (Exklusiv) fallen oder eine Schicht enthält die Bereiche, die irgendwo innerhalb der Schicht positioniert sind (Inklusiv). Exklusiv bewahrt die meisten Details, Inklusiv ermöglicht die beste Passform und Mitte erfordert die kürzeste Bearbeitungszeit."
+
+#: fdmprinter.def.json
+msgctxt "slicing_tolerance option middle"
+msgid "Middle"
+msgstr "Mitte"
+
+#: fdmprinter.def.json
+msgctxt "slicing_tolerance option exclusive"
+msgid "Exclusive"
+msgstr "Exklusiv"
+
+#: fdmprinter.def.json
+msgctxt "slicing_tolerance option inclusive"
+msgid "Inclusive"
+msgstr "Inklusiv"
+
+#: fdmprinter.def.json
+msgctxt "roofing_line_width label"
+msgid "Top Surface Skin Line Width"
+msgstr "Oberfläche Außenhaut Linienbreite"
+
+#: fdmprinter.def.json
+msgctxt "roofing_line_width description"
+msgid "Width of a single line of the areas at the top of the print."
+msgstr "Die Breite einer einzelnen Linie der oberen Druckbereiche."
+
+#: fdmprinter.def.json
+msgctxt "roofing_pattern label"
+msgid "Top Surface Skin Pattern"
+msgstr "Oberfläche Außenhaut Muster"
+
+#: fdmprinter.def.json
+msgctxt "roofing_pattern description"
+msgid "The pattern of the top most layers."
+msgstr "Das Muster der obersten Schichten."
+
+#: fdmprinter.def.json
+msgctxt "roofing_pattern option lines"
+msgid "Lines"
+msgstr "Linien"
+
+#: fdmprinter.def.json
+msgctxt "roofing_pattern option concentric"
+msgid "Concentric"
+msgstr "Konzentrisch"
+
+#: fdmprinter.def.json
+msgctxt "roofing_pattern option zigzag"
+msgid "Zig Zag"
+msgstr "Zickzack"
+
+#: fdmprinter.def.json
+msgctxt "roofing_angles label"
+msgid "Top Surface Skin Line Directions"
+msgstr "Linienrichtungen der Oberfläche Außenhaut"
+
+#: fdmprinter.def.json
+msgctxt "roofing_angles description"
+msgid "A list of integer line directions to use when the top surface skin layers use the lines or zig zag pattern. 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 traditional default angles (45 and 135 degrees)."
+msgstr "Eine Liste von Ganzzahl-Linienrichtungen für den Fall, wenn die oberen Außenhautschichten die Linien- oder Zickzack-Muster verwenden. Elemente aus der Liste werden während des Aufbaus der Schichten sequentiell verwendet und wenn das Listenende erreicht wird, beginnt die Liste von vorne. Die Listenobjekte werden durch Kommas getrennt und die gesamte Liste ist in eckige Klammern gesetzt. Standardmäßig ist eine leere Liste vorhanden, was bedeutet, dass herkömmliche Standardwinkel (45- und 135-Grad) verwendet werden."
+
+#: fdmprinter.def.json
+msgctxt "infill_enable_travel_optimization label"
+msgid "Infill Travel Optimization"
+msgstr "Bewegungsoptimierung Füllung"
+
+#: fdmprinter.def.json
+msgctxt "infill_enable_travel_optimization description"
+msgid "When enabled, the order in which the infill lines are printed is optimized to reduce the distance travelled. The reduction in travel time achieved very much depends on the model being sliced, infill pattern, density, etc. Note that, for some models that have many small areas of infill, the time to slice the model may be greatly increased."
+msgstr "Bei Aktivierung wird die Reihenfolge, in der die Fülllinien gedruckt werden, optimiert, um die gefahrene Distanz zu reduzieren. Diese erzielte Reduzierung der Bewegung ist sehr stark von dem zu slicenden Modell, dem Füllmuster, der Dichte usw. abhängig. Beachten Sie, dass die Dauer für das Slicen bei einigen Modellen mit vielen kleinen Füllbereichen erheblich länger ausfallen kann."
+
+#: fdmprinter.def.json
+msgctxt "material_flow_dependent_temperature label"
+msgid "Auto Temperature"
+msgstr "Automatische Temperatur"
+
+#: fdmprinter.def.json
+msgctxt "material_flow_dependent_temperature description"
+msgid "Change the temperature for each layer automatically with the average flow speed of that layer."
+msgstr "Die Temperatur wird für jede Schicht automatisch anhand der durchschnittlichen Fließgeschwindigkeit dieser Schicht geändert."
+
+#: fdmprinter.def.json
+msgctxt "material_flow_temp_graph label"
+msgid "Flow Temperature Graph"
+msgstr "Fließtemperaturgraf"
+
+#: fdmprinter.def.json
+msgctxt "material_flow_temp_graph description"
+msgid "Data linking material flow (in mm3 per second) to temperature (degrees Celsius)."
+msgstr "Der Materialfluss (in mm3 pro Sekunde) in Bezug zur Temperatur (Grad Celsius)."
+
+#: fdmprinter.def.json
+msgctxt "meshfix_maximum_resolution label"
+msgid "Maximum Resolution"
+msgstr "Maximale Auflösung"
+
+#: fdmprinter.def.json
+msgctxt "meshfix_maximum_resolution description"
+msgid "The minimum size of a line segment after slicing. If you increase this, the mesh will have a lower resolution. This may allow the printer to keep up with the speed it has to process g-code and will increase slice speed by removing details of the mesh that it can't process anyway."
+msgstr "Die Mindestgröße eines Linienabschnitts nach dem Slicen. Wenn Sie diesen Wert erhöhen, führt dies zu einer niedrigeren Auslösung des Mesh. Damit kann der Drucker die erforderliche Geschwindigkeit für die Verarbeitung des G-Codes beibehalten; außerdem wird die Slice-Geschwindigkeit erhöht, indem Details des Mesh entfernt werden, die ohnehin nicht verarbeitet werden können."
#: fdmprinter.def.json
msgctxt "support_skip_some_zags label"
@@ -4934,6 +5044,46 @@ msgctxt "wireframe_nozzle_clearance description"
msgid "Distance between the nozzle and horizontally downward lines. Larger clearance results in diagonally downward lines with a less steep angle, which in turn results in less upward connections with the next layer. Only applies to Wire Printing."
msgstr "Der Abstand zwischen der Düse und den horizontalen Abwärtslinien. Bei einem größeren Abstand haben die diagonalen Abwärtslinien einen weniger spitzen Winkel, was wiederum weniger Aufwärtsverbindungen zur nächsten Schicht zur Folge hat. Dies gilt nur für das Drucken mit Drahtstruktur."
+#: fdmprinter.def.json
+msgctxt "adaptive_layer_height_enabled label"
+msgid "Use adaptive layers"
+msgstr "Anpassschichten verwenden"
+
+#: fdmprinter.def.json
+msgctxt "adaptive_layer_height_enabled description"
+msgid "Adaptive layers computes the layer heights depending on the shape of the model."
+msgstr "Die Funktion Anpassschichten berechnet die Schichthöhe je nach Form des Modells."
+
+#: fdmprinter.def.json
+msgctxt "adaptive_layer_height_variation label"
+msgid "Adaptive layers maximum variation"
+msgstr "Maximale Abweichung für Anpassschichten"
+
+#: fdmprinter.def.json
+msgctxt "adaptive_layer_height_variation description"
+msgid "The maximum allowed height different from the base layer height in mm."
+msgstr "Das ist die maximal zulässige Höhendifferenz von der Basisschichthöhe in mm."
+
+#: fdmprinter.def.json
+msgctxt "adaptive_layer_height_variation_step label"
+msgid "Adaptive layers variation step size"
+msgstr "Abweichung Schrittgröße für Anpassschichten"
+
+#: fdmprinter.def.json
+msgctxt "adaptive_layer_height_variation_step description"
+msgid "The difference in height of the next layer height compared to the previous one."
+msgstr "Der Höhenunterscheid der nächsten Schichthöhe im Vergleich zur vorherigen."
+
+#: fdmprinter.def.json
+msgctxt "adaptive_layer_height_threshold label"
+msgid "Adaptive layers threshold"
+msgstr "Schwellenwert Anpassschichten"
+
+#: fdmprinter.def.json
+msgctxt "adaptive_layer_height_threshold description"
+msgid "Threshold whether to use a smaller layer or not. This number is compared to the tan of the steepest slope in a layer."
+msgstr "Das ist der Schwellenwert, der definiert, ob eine kleinere Schicht verwendet wird oder nicht. Dieser Wert wird mit dem der stärksten Neigung in einer Schicht verglichen."
+
#: fdmprinter.def.json
msgctxt "command_line_settings label"
msgid "Command Line Settings"
@@ -4994,6 +5144,26 @@ 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 "infill_offset_x description"
+#~ msgid "The infill pattern is offset this distance along the X axis."
+#~ msgstr "Das Füllmuster wird um diese Distanz entlang der X-Achse versetzt."
+
+#~ msgctxt "infill_offset_y description"
+#~ msgid "The infill pattern is offset this distance along the Y axis."
+#~ msgstr "Das Füllmuster wird um diese Distanz entlang der Y-Achse versetzt."
+
+#~ msgctxt "infill_overlap description"
+#~ msgid "The amount of overlap between the infill and the walls. A slight overlap allows the walls to connect firmly to the infill."
+#~ msgstr "Das Ausmaß des Überlappens zwischen der Füllung und den Wänden. Ein leichtes Überlappen ermöglicht es den Wänden, eine solide Verbindung mit der Füllung herzustellen."
+
+#~ msgctxt "skin_overlap description"
+#~ msgid "The amount of overlap between the skin and the walls as a percentage of the 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 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 "material_bed_temperature description"
+#~ msgid "The temperature used for the heated build plate. If this is 0, the bed will not heat up for this print."
+#~ msgstr "Die Temperatur, die für die erhitzte Druckplatte verwendet wird. Wenn dieser Wert 0 beträgt, wird das Bett für diesen Druck nicht erhitzt."
+
#~ msgctxt "wall_x_extruder_nr label"
#~ msgid "Inner Walls Extruder"
#~ msgstr "Extruder Innenwände"
diff --git a/resources/i18n/es_ES/cura.po b/resources/i18n/es_ES/cura.po
index 3a35477fc9..fa8cf61985 100644
--- a/resources/i18n/es_ES/cura.po
+++ b/resources/i18n/es_ES/cura.po
@@ -1,22 +1,24 @@
# Cura
-# Copyright (C) 2017 Ultimaker
+# Copyright (C) 2018 Ultimaker
# This file is distributed under the same license as the Cura package.
-# Ruben Dulek , 2017.
-#
+# Ruben Dulek , 2018.
+#
msgid ""
msgstr ""
-"Project-Id-Version: Cura 3.0\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2017-11-21 16:58+0100\n"
-"PO-Revision-Date: 2017-11-30 13:05+0100\n"
+"Project-Id-Version: Cura 3.2\n"
+"Report-Msgid-Bugs-To: r.dulek@ultimaker.com\n"
+"POT-Creation-Date: 2018-01-29 09:48+0000\n"
+"PO-Revision-Date: 2018-02-12 13:40+0100\n"
"Last-Translator: Bothof \n"
"Language-Team: 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"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.py:29
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.py:26
msgctxt "@action"
msgid "Machine Settings"
msgstr "Ajustes de la máquina"
@@ -53,12 +55,11 @@ msgstr "Conectar con Doodle3D Connect"
#: /home/ruben/Projects/Cura/plugins/Doodle3D-cura-plugin/Doodle3D/D3DCloudPrintOutputDevicePlugin.py:87
#: /home/ruben/Projects/Cura/plugins/Doodle3D-cura-plugin/Doodle3D/D3DCloudPrintOutputDevicePlugin.py:155
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:874
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:646
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:875
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:659
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/DiscoverUM3Action.qml:370
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/PrintWindow.qml:78
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/ConfigDialog.qml:104
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/ExportSTLUI.qml:99
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:355
#: /home/ruben/Projects/Cura/plugins/ImageReader/ConfigUI.qml:188
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:376
#: /home/ruben/Projects/Cura/plugins/PluginBrowser/PluginBrowser.qml:139
@@ -98,7 +99,7 @@ msgctxt "@info:tooltip"
msgid "Open the Doodle3D Connect web interface"
msgstr "Abrir la interfaz web de Doodle3D Connect"
-#: /home/ruben/Projects/Cura/plugins/ChangeLogPlugin/ChangeLog.py:34
+#: /home/ruben/Projects/Cura/plugins/ChangeLogPlugin/ChangeLog.py:33
msgctxt "@item:inmenu"
msgid "Show Changelog"
msgstr "Mostrar registro de cambios"
@@ -113,78 +114,83 @@ 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:26
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:27
msgctxt "@item:inmenu"
msgid "USB printing"
msgstr "Impresión USB"
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:27
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:28
msgctxt "@action:button Preceded by 'Ready to'."
msgid "Print via USB"
msgstr "Imprimir mediante USB"
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:28
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:29
msgctxt "@info:tooltip"
msgid "Print via USB"
msgstr "Imprimir mediante USB"
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:30
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:31
msgctxt "@info:status"
msgid "Connected via USB"
msgstr "Conectado mediante USB"
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:154
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:183
msgctxt "@info:status"
msgid "Unable to start a new job because the printer is busy or not connected."
msgstr "No se puede iniciar un trabajo nuevo porque la impresora está ocupada o no está conectada."
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:154
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:183
msgctxt "@info:title"
msgid "Printer Unavailable"
msgstr "Impresora no disponible"
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:457
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:485
msgctxt "@info:status"
msgid "This printer does not support USB printing because it uses UltiGCode flavor."
msgstr "Esta impresora no es compatible con la impresión USB porque utiliza el tipo UltiGCode."
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:457
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:485
msgctxt "@info:title"
msgid "USB Printing"
msgstr "Impresión USB"
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:461
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:489
msgctxt "@info:status"
msgid "Unable to start a new job because the printer does not support usb printing."
msgstr "No se puede iniciar un trabajo nuevo porque la impresora no es compatible con la impresión USB."
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:461
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDeviceManager.py:108
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:489
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDeviceManager.py:103
#: /home/ruben/Projects/Cura/plugins/RemovableDriveOutputDevice/RemovableDriveOutputDevice.py:146
#: /home/ruben/Projects/Cura/plugins/RemovableDriveOutputDevice/RemovableDriveOutputDevice.py:158
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:945
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1349
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1417
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:946
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1418
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1496
msgctxt "@info:title"
msgid "Warning"
msgstr "Advertencia"
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDeviceManager.py:108
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDeviceManager.py:103
msgctxt "@info"
msgid "Unable to update firmware because there are no printers connected."
msgstr "No se puede actualizar el firmware porque no hay impresoras conectadas."
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDeviceManager.py:122
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDeviceManager.py:117
#, python-format
msgctxt "@info"
msgid "Could not find firmware required for the printer at %s."
msgstr "No se pudo encontrar el firmware necesario para la impresora en %s."
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDeviceManager.py:122
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDeviceManager.py:117
msgctxt "@info:title"
msgid "Printer Firmware"
msgstr "Firmware de la impresora"
+#: /home/ruben/Projects/Cura/plugins/PrepareStage/__init__.py:12
+msgctxt "@item:inmenu"
+msgid "Prepare"
+msgstr "Preparar"
+
#: /home/ruben/Projects/Cura/plugins/RemovableDriveOutputDevice/RemovableDriveOutputDevice.py:23
msgctxt "@action:button Preceded by 'Ready to'."
msgid "Save to Removable Drive"
@@ -228,11 +234,11 @@ 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:132
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:692
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:700
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:146
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:693
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:701
#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:153
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1358
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:160
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1427
msgctxt "@info:title"
msgid "Error"
msgstr "Error"
@@ -282,7 +288,7 @@ msgid "Removable Drive"
msgstr "Unidad extraíble"
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:109
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:53
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:51
msgctxt "@action:button Preceded by 'Ready to'."
msgid "Print over network"
msgstr "Imprimir a través de la red"
@@ -396,110 +402,110 @@ msgctxt "@info:title"
msgid "Printer Status"
msgstr "Estado de la impresora"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:691
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:692
#, python-brace-format
msgctxt "@info:status"
msgid "Unable to start a new print job. No Printcore loaded in slot {0}"
msgstr "No se puede iniciar un trabajo nuevo de impresión. No se ha cargado ningún PrintCore en la ranura {0}."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:699
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:700
#, python-brace-format
msgctxt "@info:status"
msgid "Unable to start a new print job. No material loaded in slot {0}"
msgstr "No se puede iniciar un trabajo nuevo de impresión. No se ha cargado material en la ranura {0}."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:709
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:710
#, python-brace-format
msgctxt "@label"
msgid "Not enough material for spool {0}."
msgstr "No hay suficiente material para la bobina {0}."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:719
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:720
#, python-brace-format
msgctxt "@label"
msgid "Different PrintCore (Cura: {0}, Printer: {1}) selected for extruder {2}"
msgstr "PrintCore distinto (Cura: {0}, impresora: {1}) seleccionado para extrusor {2}"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:733
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:734
#, 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/NetworkPrinterOutputDevice.py:741
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:742
#, python-brace-format
msgctxt "@label"
msgid "PrintCore {0} is not properly calibrated. XY calibration needs to be performed on the printer."
msgstr "El PrintCore {0} no está calibrado correctamente. Debe llevarse a cabo una calibración XY de la impresora."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:746
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:747
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/NetworkPrinterOutputDevice.py:747
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:748
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/NetworkPrinterOutputDevice.py:753
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:754
msgctxt "@window:title"
msgid "Mismatched configuration"
msgstr "Configuración desajustada"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:864
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:262
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:865
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:258
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/NetworkPrinterOutputDevice.py:873
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:874
msgctxt "@info:status"
msgid "Sending data to printer"
msgstr "Enviando datos a la impresora"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:873
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:874
msgctxt "@info:title"
msgid "Sending Data"
msgstr "Enviando datos"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:944
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:945
msgctxt "@info:status"
msgid "Unable to send data to printer. Is another job still active?"
msgstr "No se puede enviar datos a la impresora. ¿Hay otro trabajo que todavía esté activo?"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:1085
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:1087
#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:196
msgctxt "@label:MonitorStatus"
msgid "Aborting print..."
msgstr "Cancelando impresión..."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:1091
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:1093
msgctxt "@label:MonitorStatus"
msgid "Print aborted. Please check the printer"
msgstr "Impresión cancelada. Compruebe la impresora."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:1097
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:1099
msgctxt "@label:MonitorStatus"
msgid "Pausing print..."
msgstr "Pausando impresión..."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:1099
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:1101
msgctxt "@label:MonitorStatus"
msgid "Resuming print..."
msgstr "Reanudando impresión..."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:1289
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:1291
msgctxt "@window:title"
msgid "Sync with your printer"
msgstr "Sincronizar con la impresora"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:1291
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:1293
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/NetworkPrinterOutputDevice.py:1293
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:1295
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."
@@ -520,145 +526,204 @@ msgid "{printer_name} has finished printing '{job_name}'. Please collect the pri
msgstr "{printer_name} ha terminado de imprimir «{job_name}». Recoja el impreso y confirme que ha borrado la placa de impresión."
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:115
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:520
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:533
#, python-brace-format
msgid "{printer_name} is reserved to print '{job_name}'. Please change the printer's configuration to match the job, for it to start printing."
msgstr "{printer_name} está reservada para imprimir «{job_name}». Modifique la configuración de la impresora de modo que se adapte al trabajo para comenzar la impresión."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:278
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:277
msgctxt "@info:status"
msgid "Unable to send new print job: this 3D printer is not (yet) set up to host a group of connected Ultimaker 3 printers."
msgstr "No se pudo enviar el nuevo trabajo de impresión: esta impresora 3D (todavía) no está configurada para alojar un grupo de impresoras de Ultimaker 3 conectadas."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:410
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:423
#, python-brace-format
msgctxt "@info:status"
msgid "Unable to send print job to group {cluster_name}."
msgstr "No se puede enviar el trabajo de impresión al grupo {cluster_name}."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:418
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:431
#, python-brace-format
msgctxt "@info:status"
msgid "Sent {file_name} to group {cluster_name}."
msgstr "Enviar {file_name} al grupo {cluster_name}."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:423
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:436
msgctxt "@action:button"
msgid "Show print jobs"
msgstr "Mostrar trabajos de impresión"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:424
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:437
msgctxt "@info:tooltip"
msgid "Opens the print jobs interface in your browser."
msgstr "Abre la interfaz de trabajos de impresión en el navegador."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:489
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:502
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/DiscoverUM3Action.qml:239
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/PrinterInfoBlock.qml:47
-msgctxt "@label"
+msgctxt "@label Printer name"
msgid "Unknown"
msgstr "Desconocido"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:492
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:505
#, 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/NetworkClusterPrinterOutputDevice.py:494
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:497
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:507
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:510
msgctxt "@info:status"
msgid "Print finished"
msgstr "Impresión terminada"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:522
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:525
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:535
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:538
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/PrinterInfoBlock.qml:282
msgctxt "@label:status"
msgid "Action required"
msgstr "Acción requerida"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:643
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:656
#, python-brace-format
msgctxt "@info:progress"
msgid "Sending {file_name} to group {cluster_name}"
msgstr "Enviando {file_name} al grupo {cluster_name}"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/DiscoverUM3Action.py:19
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/DiscoverUM3Action.py:17
msgctxt "@action"
msgid "Connect via Network"
msgstr "Conectar a través de la red"
-#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py:64
+#: /home/ruben/Projects/Cura/plugins/MonitorStage/__init__.py:12
+msgctxt "@item:inmenu"
+msgid "Monitor"
+msgstr "Supervisar"
+
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py:66
#, 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:65
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py:67
#, 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:66
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py:68
msgctxt "@action:button"
msgid "How to update"
msgstr "Cómo actualizar"
-#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py:77
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py:79
msgctxt "@info"
msgid "Could not access update information."
msgstr "No se pudo acceder a la información actualizada."
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksReader.py:199
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksReader.py:579
msgctxt "@info:status"
-msgid "Errors appeared while opening your SolidWorks file! Please check, whether it is possible to open your file in SolidWorks itself without any problems as well!"
-msgstr "Se han producido varios errores al abrir el archivo de SolidWorks. Compruebe que el archivo se puede abrir correctamente en SolidWorks."
+msgid "SolidWorks reported errors, while opening your file. We recommend to solve these issues inside SolidWorks itself."
+msgstr "SolidWorks ha informado de errores al abrir el archivo. Le recomendamos que solucione estos problemas dentro del propio SolidWorks."
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/__init__.py:31
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksReader.py:591
+msgctxt "@info:status"
+msgid ""
+"Found no models inside your drawing. Could you please check it's content again and make sure one part or assembly is inside?\n"
+"\n"
+" Thanks!."
+msgstr ""
+"No se han encontrado modelos en el dibujo. ¿Puede comprobar el contenido de nuevo y asegurarse de que hay una parte o un ensamblado dentro?\n"
+"\n"
+" Gracias."
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksReader.py:595
+msgctxt "@info:status"
+msgid ""
+"Found more then one part or assembly inside your drawing. We currently only support drawings with exactly one part or assembly inside.\n"
+"\n"
+"Sorry!"
+msgstr ""
+"Se ha encontrado más de una parte o ensamblado en el dibujo. Actualmente únicamente son compatibles dibujos con una sola parte o ensamblado.\n"
+"\n"
+" Disculpe."
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/__init__.py:25
msgctxt "@item:inlistbox"
msgid "SolidWorks part file"
msgstr "Archivo de elementos de SolidWorks"
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/__init__.py:35
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/__init__.py:29
msgctxt "@item:inlistbox"
msgid "SolidWorks assembly file"
msgstr "Archivo de ensamblado de SolidWorks"
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/ConfigDialog.py:21
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/__init__.py:33
+msgctxt "@item:inlistbox"
+msgid "SolidWorks drawing file"
+msgstr "Archivo de dibujo de SolidWorks"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/__init__.py:48
+msgctxt "@info:status"
+msgid ""
+"Dear customer,\n"
+"We could not find a valid installation of SolidWorks on your system. That means that either SolidWorks is not installed or you don't own an valid license. Please make sure that running SolidWorks itself works without issues and/or contact your ICT.\n"
+"\n"
+"With kind regards\n"
+" - Thomas Karl Pietrowski"
+msgstr ""
+"Estimado cliente:\n"
+"No hemos encontrado una instalación válida de SolidWorks en el sistema. Esto significa que SolidWorks no está instalado o que no dispone de una licencia válida. Asegúrese de que la ejecución del propio SolidWorks funciona sin problemas o póngase en contacto con su CDTI.\n"
+"\n"
+"Atentamente\n"
+" - Thomas Karl Pietrowski"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/__init__.py:57
+msgctxt "@info:status"
+msgid ""
+"Dear customer,\n"
+"You are currently running this plugin on an operating system other than Windows. This plugin will only work on Windows with SolidWorks installed, including an valid license. Please install this plugin on a Windows machine with SolidWorks installed.\n"
+"\n"
+"With kind regards\n"
+" - Thomas Karl Pietrowski"
+msgstr ""
+"Estimado cliente:\n"
+"Actualmente está ejecutando este complemento en un sistema operativo diferente a Windows. Este complemento solo funcionará en Windows con SolidWorks instalado, siempre que se disponga de una licencia válida. Instale este complemento en un equipo Windows con SolidWorks instalado.\n"
+"\n"
+"Atentamente\n"
+" - Thomas Karl Pietrowski"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksDialogHandler.py:70
msgid "Configure"
msgstr "Configurar"
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/CommonComReader.py:135
-#, python-format
-msgctxt "@info:status"
-msgid "Error while starting %s!"
-msgstr "Error al iniciar %s"
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksDialogHandler.py:71
+msgid "Installation guide for SolidWorks macro"
+msgstr "Guía de instalación para la macro de SolidWorks"
#: /home/ruben/Projects/Cura/plugins/SimulationView/__init__.py:14
msgctxt "@item:inlistbox"
-msgid "Simulation view"
-msgstr "Vista de simulación"
+msgid "Layer view"
+msgstr "Vista de capas"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.py:100
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.py:103
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:101
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.py:104
msgctxt "@info:title"
msgid "Simulation View"
msgstr "Vista de simulación"
-#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.py:26
+#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.py:25
msgid "Modify G-Code"
msgstr "Modificar GCode"
#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/SliceInfo.py:43
msgctxt "@info"
-msgid "Cura collects anonymised slicing statistics. You can disable this in the preferences."
-msgstr "Cura recopila de forma anónima información de la segmentación. Puede desactivar esta opción en las preferencias."
+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"
@@ -667,14 +732,43 @@ msgstr "Recopilando datos"
#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/SliceInfo.py:48
msgctxt "@action:button"
-msgid "Dismiss"
-msgstr "Descartar"
+msgid "Allow"
+msgstr "Permitir"
+
+#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/SliceInfo.py:49
+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/SliceInfoPlugin/SliceInfo.py:50
+msgctxt "@action:button"
+msgid "Disable"
+msgstr "Deshabilitar"
+
+#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/SliceInfo.py:51
+msgctxt "@action:tooltip"
+msgid "Don't allow Cura to send anonymized usage statistics. You can enable it again in the preferences."
+msgstr "No permitir a Cura enviar estadísticas de uso de forma anónima. Puede habilitarlo de nuevo en las preferencias."
#: /home/ruben/Projects/Cura/plugins/LegacyProfileReader/__init__.py:14
msgctxt "@item:inlistbox"
msgid "Cura 15.04 profiles"
msgstr "Perfiles de Cura 15.04"
+#: /home/ruben/Projects/Cura/plugins/CuraBlenderPlugin/__init__.py:15
+msgctxt "@item:inlistbox"
+msgid "Blender file"
+msgstr "Archivo Blender"
+
+#: /home/ruben/Projects/Cura/plugins/CuraBlenderPlugin/CadIntegrationUtils/CommonReader.py:199
+msgctxt "@info:status"
+msgid ""
+"Could not export using \"{}\" quality!\n"
+"Felt back to \"{}\"."
+msgstr ""
+"No ha podido exportarse con la calidad \"{}\"\n"
+"Retroceder a \"{}»."
+
#: /home/ruben/Projects/Cura/plugins/GCodeProfileReader/__init__.py:14
#: /home/ruben/Projects/Cura/plugins/GCodeReader/__init__.py:14
msgctxt "@item:inlistbox"
@@ -706,49 +800,49 @@ msgctxt "@item:inlistbox"
msgid "GIF Image"
msgstr "Imagen GIF"
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:269
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:299
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:269
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:297
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:319
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:299
#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:327
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:336
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:349
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:357
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:366
msgctxt "@info:title"
msgid "Unable to slice"
msgstr "No se puede segmentar"
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:296
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:326
#, 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:318
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:348
#, 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:326
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:356
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:335
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:365
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."
#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py:50
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py:239
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py:242
msgctxt "@info:status"
msgid "Processing Layers"
msgstr "Procesando capas"
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py:239
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py:242
msgctxt "@info:title"
msgid "Information"
msgstr "Información"
@@ -785,14 +879,14 @@ msgstr "Se ha producido un error al copiar los archivos de complemento de Siemen
msgid "Failed to install Siemens NX plugin. Could not set environment variable UGII_USER_DIR for Siemens NX."
msgstr "Se ha producido un error al instalar el complemento de Siemens NX. No se pudo definir la variable de entorno UGII_USER_DIR de Siemens NX."
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.py:167
-#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:585
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.py:165
+#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:590
msgctxt "@title:tab"
msgid "Recommended"
msgstr "Recomendado"
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.py:169
-#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:590
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.py:167
+#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:595
msgctxt "@title:tab"
msgid "Custom"
msgstr "Personalizado"
@@ -803,24 +897,24 @@ msgctxt "@item:inlistbox"
msgid "3MF File"
msgstr "Archivo 3MF"
-#: /home/ruben/Projects/Cura/plugins/3MFReader/ThreeMFWorkspaceReader.py:126
-#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:1142
+#: /home/ruben/Projects/Cura/plugins/3MFReader/ThreeMFWorkspaceReader.py:159
+#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:1185
msgctxt "@label"
msgid "Nozzle"
msgstr "Tobera"
-#: /home/ruben/Projects/Cura/plugins/PluginBrowser/PluginBrowser.py:164
+#: /home/ruben/Projects/Cura/plugins/PluginBrowser/PluginBrowser.py:152
#, python-brace-format
msgctxt "@info:status"
msgid "Failed to get plugin ID from {0}"
msgstr "No se pudo obtener la ID del complemento de {0}"
-#: /home/ruben/Projects/Cura/plugins/PluginBrowser/PluginBrowser.py:165
+#: /home/ruben/Projects/Cura/plugins/PluginBrowser/PluginBrowser.py:153
msgctxt "@info:tile"
msgid "Warning"
msgstr "Advertencia"
-#: /home/ruben/Projects/Cura/plugins/PluginBrowser/PluginBrowser.py:203
+#: /home/ruben/Projects/Cura/plugins/PluginBrowser/PluginBrowser.py:191
msgctxt "@window:title"
msgid "Plugin browser"
msgstr "Explorador de complementos"
@@ -835,18 +929,18 @@ msgctxt "@item:inlistbox"
msgid "G File"
msgstr "Archivo G"
-#: /home/ruben/Projects/Cura/plugins/GCodeReader/GCodeReader.py:314
+#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:321
msgctxt "@info:status"
msgid "Parsing G-code"
msgstr "Analizar GCode"
-#: /home/ruben/Projects/Cura/plugins/GCodeReader/GCodeReader.py:316
-#: /home/ruben/Projects/Cura/plugins/GCodeReader/GCodeReader.py:426
+#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:323
+#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:464
msgctxt "@info:title"
msgid "G-code Details"
msgstr "Datos de GCode"
-#: /home/ruben/Projects/Cura/plugins/GCodeReader/GCodeReader.py:424
+#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:462
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."
@@ -857,6 +951,16 @@ msgctxt "@item:inlistbox"
msgid "Cura Profile"
msgstr "Perfil de cura"
+#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/__init__.py:12
+msgctxt "@item:inmenu"
+msgid "Profile Assistant"
+msgstr "Asistente del perfil"
+
+#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/__init__.py:17
+msgctxt "@item:inlistbox"
+msgid "Profile Assistant"
+msgstr "Asistente del perfil"
+
#: /home/ruben/Projects/Cura/plugins/3MFWriter/__init__.py:30
msgctxt "@item:inlistbox"
msgid "3MF file"
@@ -888,142 +992,116 @@ msgctxt "@action"
msgid "Level build plate"
msgstr "Nivelar placa de impresión"
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:89
+#: /home/ruben/Projects/Cura/cura/PrintInformation.py:98
msgctxt "@tooltip"
msgid "Outer Wall"
msgstr "Pared exterior"
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:90
+#: /home/ruben/Projects/Cura/cura/PrintInformation.py:99
msgctxt "@tooltip"
msgid "Inner Walls"
msgstr "Paredes interiores"
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:91
+#: /home/ruben/Projects/Cura/cura/PrintInformation.py:100
msgctxt "@tooltip"
msgid "Skin"
msgstr "Forro"
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:92
+#: /home/ruben/Projects/Cura/cura/PrintInformation.py:101
msgctxt "@tooltip"
msgid "Infill"
msgstr "Relleno"
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:93
+#: /home/ruben/Projects/Cura/cura/PrintInformation.py:102
msgctxt "@tooltip"
msgid "Support Infill"
-msgstr "Relleno de soporte"
+msgstr "Relleno del soporte"
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:94
+#: /home/ruben/Projects/Cura/cura/PrintInformation.py:103
msgctxt "@tooltip"
msgid "Support Interface"
-msgstr "Interfaz de soporte"
+msgstr "Interfaz del soporte"
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:95
+#: /home/ruben/Projects/Cura/cura/PrintInformation.py:104
msgctxt "@tooltip"
msgid "Support"
msgstr "Soporte"
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:96
+#: /home/ruben/Projects/Cura/cura/PrintInformation.py:105
msgctxt "@tooltip"
msgid "Skirt"
msgstr "Falda"
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:97
+#: /home/ruben/Projects/Cura/cura/PrintInformation.py:106
msgctxt "@tooltip"
msgid "Travel"
msgstr "Desplazamiento"
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:98
+#: /home/ruben/Projects/Cura/cura/PrintInformation.py:107
msgctxt "@tooltip"
msgid "Retractions"
msgstr "Retracciones"
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:99
+#: /home/ruben/Projects/Cura/cura/PrintInformation.py:108
msgctxt "@tooltip"
msgid "Other"
msgstr "Otro"
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:199
+#: /home/ruben/Projects/Cura/cura/PrintInformation.py:231
msgctxt "@label unknown material"
msgid "Unknown"
msgstr "Desconocido"
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:284
+#: /home/ruben/Projects/Cura/cura/PrintInformation.py:318
#, python-brace-format
msgctxt "@label"
msgid "Pre-sliced file {0}"
msgstr "Archivo {0} presegmentado"
-#: /home/ruben/Projects/Cura/cura/PrinterOutputDevice.py:469
+#: /home/ruben/Projects/Cura/cura/PrinterOutputDevice.py:440
msgctxt "@item:material"
msgid "No material loaded"
msgstr "No se ha cargado material."
-#: /home/ruben/Projects/Cura/cura/PrinterOutputDevice.py:476
+#: /home/ruben/Projects/Cura/cura/PrinterOutputDevice.py:447
msgctxt "@item:material"
msgid "Unknown material"
msgstr "Material desconocido"
-#: /home/ruben/Projects/Cura/cura/ArrangeObjectsJob.py:30
-msgctxt "@info:status"
-msgid "Finding new location for objects"
-msgstr "Buscando nueva ubicación para los objetos"
-
-#: /home/ruben/Projects/Cura/cura/ArrangeObjectsJob.py:34
-msgctxt "@info:title"
-msgid "Finding Location"
-msgstr "Buscando ubicación"
-
-#: /home/ruben/Projects/Cura/cura/ArrangeObjectsJob.py:89
-#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:83
-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/ArrangeObjectsJob.py:90
-msgctxt "@info:title"
-msgid "Can't Find Location"
-msgstr "No se puede encontrar la ubicación"
-
-#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:431
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:113
+#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:437
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:120
msgctxt "@title:window"
msgid "File Already Exists"
msgstr "El archivo ya existe"
-#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:432
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:114
+#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:438
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:121
#, python-brace-format
msgctxt "@label Don't translate the XML tag !"
msgid "The file {0} already exists. Are you sure you want to overwrite it?"
msgstr "El archivo {0} ya existe. ¿Está seguro de que desea sobrescribirlo?"
-#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:815
+#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:872
msgctxt "@label"
msgid "Custom"
msgstr "Personalizado"
-#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:819
+#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:876
msgctxt "@label"
msgid "Custom Material"
msgstr "Material personalizado"
-#: /home/ruben/Projects/Cura/cura/Settings/ExtrudersModel.py:182
-msgctxt "@menuitem"
-msgid "Global"
-msgstr "Global"
-
-#: /home/ruben/Projects/Cura/cura/Settings/ExtrudersModel.py:229
+#: /home/ruben/Projects/Cura/cura/Settings/ExtrudersModel.py:205
msgctxt "@menuitem"
msgid "Not overridden"
msgstr "No reemplazado"
-#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:117
+#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:124
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."
-#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:118
+#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:125
#: /home/ruben/Projects/Cura/cura/Settings/MaterialManager.py:24
msgctxt "@info:title"
msgid "Incompatible Material"
@@ -1044,67 +1122,89 @@ msgctxt "@action"
msgid "Undo changing the material diameter."
msgstr "Deshacer cambio del diámetro del material."
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:144
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:151
#, 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:151
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:158
#, 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:156
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:163
#, 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:157
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:164
msgctxt "@info:title"
msgid "Export succeeded"
msgstr "Exportación correcta"
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:183
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:205
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:214
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:248
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:190
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:211
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:271
#, 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}"
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:216
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:252
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:230
+#, python-brace-format
+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."
+
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:240
+#, python-brace-format
+msgctxt "@info:status Don't translate the XML tags or !"
+msgid "The machine defined in profile {0} doesn't match with your current machine, could not import it."
+msgstr "El equipo definido en el perfil {0} no coincide con su equipo actual, no se ha podido importar."
+
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:274
#, python-brace-format
msgctxt "@info:status"
msgid "Successfully imported profile {0}"
msgstr "Perfil {0} importado correctamente"
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:255
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:277
+#, 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:280
#, 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:274
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:298
msgctxt "@label"
msgid "Custom profile"
msgstr "Perfil personalizado"
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:285
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:313
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:321
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:349
#, 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:46
+#, python-brace-format
+msgctxt "@label"
+msgid "Group #{group_nr}"
+msgstr "N.º de grupo {group_nr}"
+
#: /home/ruben/Projects/Cura/cura/BuildVolume.py:100
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."
@@ -1115,142 +1215,170 @@ msgctxt "@info:title"
msgid "Build Volume"
msgstr "Volumen de impresión"
-#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:34
+#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:25
msgctxt "@info:status"
msgid "Multiplying and placing objects"
msgstr "Multiplicar y colocar objetos"
-#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:35
-#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:83
+#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:26
+#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:78
msgctxt "@info:title"
msgid "Placing Object"
msgstr "Colocando objeto"
-#: /home/ruben/Projects/Cura/cura/CrashHandler.py:80
+#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:78
+#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsJob.py:88
+#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsAllBuildPlatesJob.py:152
+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:29
+#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsAllBuildPlatesJob.py:64
+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:33
+#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsAllBuildPlatesJob.py:68
+msgctxt "@info:title"
+msgid "Finding Location"
+msgstr "Buscando ubicación"
+
+#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsJob.py:89
+#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsAllBuildPlatesJob.py:153
+msgctxt "@info:title"
+msgid "Can't Find Location"
+msgstr "No se puede encontrar la ubicación"
+
+#: /home/ruben/Projects/Cura/cura/CrashHandler.py:81
msgctxt "@title:window"
msgid "Crash Report"
msgstr "Informe del accidente"
-#: /home/ruben/Projects/Cura/cura/CrashHandler.py:93
+#: /home/ruben/Projects/Cura/cura/CrashHandler.py:94
msgctxt "@label crash message"
msgid ""
-"
A fatal exception has occurred. Please send us this Crash Report to fix the problem
\n"
+"
A fatal error has occurred. Please send us this Crash Report to fix the problem
\n"
"
Please use the \"Send report\" button to post a bug report automatically to our servers
\n"
" "
-msgstr "
Se ha producido una excepción fatal. Envíenos este informe de errores para que podamos solucionar el problema.
\n
Utilice el botón «Enviar informe» para publicar automáticamente un informe de errores en nuestros servidores.
\n "
+msgstr ""
+"
Se ha producido un error grave. Envíenos este informe de incidencias para que podamos solucionar el problema.
\n"
+"
Utilice el botón «Enviar informe» para publicar automáticamente un informe de errores en nuestros servidores.
"
-#: /home/ruben/Projects/Cura/cura/CrashHandler.py:141
+#: /home/ruben/Projects/Cura/cura/CrashHandler.py:147
msgctxt "@title:groupbox"
-msgid "Exception traceback"
-msgstr "Rastreabilidad de excepciones"
+msgid "Error traceback"
+msgstr "Rastreabilidad de errores"
-#: /home/ruben/Projects/Cura/cura/CrashHandler.py:208
+#: /home/ruben/Projects/Cura/cura/CrashHandler.py:214
msgctxt "@title:groupbox"
msgid "Logs"
msgstr "Registros"
-#: /home/ruben/Projects/Cura/cura/CrashHandler.py:231
+#: /home/ruben/Projects/Cura/cura/CrashHandler.py:237
msgctxt "@title:groupbox"
msgid "User description"
msgstr "Descripción del usuario"
-#: /home/ruben/Projects/Cura/cura/CrashHandler.py:246
+#: /home/ruben/Projects/Cura/cura/CrashHandler.py:252
msgctxt "@action:button"
msgid "Send report"
msgstr "Enviar informe"
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:256
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:274
msgctxt "@info:progress"
msgid "Loading machines..."
msgstr "Cargando máquinas..."
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:661
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:660
msgctxt "@info:progress"
msgid "Setting up scene..."
msgstr "Configurando escena..."
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:703
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:702
msgctxt "@info:progress"
msgid "Loading interface..."
msgstr "Cargando interfaz..."
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:874
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:899
#, 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:1348
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1417
#, 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:1357
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1426
#, 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:1416
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1495
msgctxt "@info:status"
msgid "The selected model was too small to load."
msgstr "No se puede cargar el modelo seleccionado, es demasiado pequeño."
@@ -1279,12 +1407,11 @@ msgstr "X (anchura)"
#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:119
#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:129
#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:235
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:288
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:300
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:391
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:401
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:413
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:840
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:383
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:394
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:412
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:424
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:849
msgctxt "@label"
msgid "mm"
msgstr "mm"
@@ -1374,68 +1501,67 @@ 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:255
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:254
msgctxt "@label"
msgid "Number of Extruders"
msgstr "Número de extrusores"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:289
-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:291
-msgctxt "@label"
-msgid "Material diameter"
-msgstr "Diámetro del material"
-
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:299
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:390
-msgctxt "@label"
-msgid "Nozzle size"
-msgstr "Tamaño de la tobera"
-
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:317
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:310
msgctxt "@label"
msgid "Start Gcode"
msgstr "Iniciar GCode"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:327
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:320
msgctxt "@tooltip"
msgid "Gcode 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:336
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:329
msgctxt "@label"
msgid "End Gcode"
msgstr "Finalizar GCode"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:346
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:339
msgctxt "@tooltip"
msgid "Gcode 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:378
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:370
msgctxt "@label"
msgid "Nozzle Settings"
msgstr "Ajustes de la tobera"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:400
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:382
+msgctxt "@label"
+msgid "Nozzle size"
+msgstr "Tamaño de la tobera"
+
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:393
+msgctxt "@label"
+msgid "Compatible material diameter"
+msgstr "Diámetro del material compatible"
+
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:395
+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:411
msgctxt "@label"
msgid "Nozzle offset X"
msgstr "Desplazamiento de la tobera sobre el eje X"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:412
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:423
msgctxt "@label"
msgid "Nozzle offset Y"
msgstr "Desplazamiento de la tobera sobre el eje Y"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:433
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:444
msgctxt "@label"
msgid "Extruder Start Gcode"
msgstr "GCode inicial del extrusor"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:451
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:462
msgctxt "@label"
msgid "Extruder End Gcode"
msgstr "GCode final del extrusor"
@@ -1448,8 +1574,9 @@ msgstr "Registro de cambios"
#: /home/ruben/Projects/Cura/plugins/ChangeLogPlugin/ChangeLog.qml:37
#: /home/ruben/Projects/Cura/plugins/USBPrinting/FirmwareUpdateWindow.qml:107
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/UM3InfoComponents.qml:55
-#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.qml:445
-#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:357
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksMacroTutorial.qml:306
+#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.qml:456
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:492
#: /home/ruben/Projects/Cura/plugins/PluginBrowser/PluginBrowser.qml:80
#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:123
#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:147
@@ -1514,7 +1641,10 @@ 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\nSeleccione la impresora de la siguiente lista:"
+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:"
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/DiscoverUM3Action.qml:75
#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:44
@@ -1530,7 +1660,7 @@ msgstr "Editar"
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/DiscoverUM3Action.qml:96
#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:50
#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:95
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:190
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:171
msgctxt "@action:button"
msgid "Remove"
msgstr "Eliminar"
@@ -1552,12 +1682,12 @@ msgid "Type"
msgstr "Tipo"
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/DiscoverUM3Action.qml:233
-msgctxt "@label"
+msgctxt "@label Printer name"
msgid "Ultimaker 3"
msgstr "Ultimaker 3"
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/DiscoverUM3Action.qml:236
-msgctxt "@label"
+msgctxt "@label Printer name"
msgid "Ultimaker 3 Extended"
msgstr "Ultimaker 3 Extended"
@@ -1603,8 +1733,6 @@ msgid "Enter the IP address or hostname of your printer on the network."
msgstr "Introduzca la dirección IP o el nombre de host de la impresora en red."
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/DiscoverUM3Action.qml:379
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/ConfigDialog.qml:92
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/ExportSTLUI.qml:88
#: /home/ruben/Projects/Cura/plugins/ImageReader/ConfigUI.qml:181
msgctxt "@action:button"
msgid "OK"
@@ -1625,6 +1753,11 @@ msgctxt "@label: arg 1 is group name"
msgid "%1 is not set up to host a group of connected Ultimaker 3 printers"
msgstr "%1 no está configurada para alojar un grupo de impresoras conectadas de Ultimaker 3"
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/ClusterMonitorItem.qml:55
+msgctxt "@label link to connect manager"
+msgid "Add/Remove printers"
+msgstr "Agregar/eliminar impresoras"
+
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/OpenPanelButton.qml:14
msgctxt "@info:tooltip"
msgid "Opens the print jobs page with your default web browser."
@@ -1655,11 +1788,16 @@ msgid "Available"
msgstr "Disponible"
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/PrinterInfoBlock.qml:43
-#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:101
+#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:100
msgctxt "@label:MonitorStatus"
msgid "Lost connection with the printer"
msgstr "Se ha perdido la conexión con la impresora."
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/PrinterInfoBlock.qml:47
+msgctxt "@label Printer status"
+msgid "Unknown"
+msgstr "Desconocido"
+
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/PrinterInfoBlock.qml:257
msgctxt "@label:status"
msgid "Disabled"
@@ -1751,138 +1889,252 @@ msgctxt "@action:button"
msgid "Activate Configuration"
msgstr "Activar configuración"
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/ConfigDialog.qml:20
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksWizard.qml:21
msgctxt "@title:window"
-msgid "Cura SolidWorks Plugin Configuration"
-msgstr "Configuración de complementos Cura SolidWorks"
+msgid "SolidWorks: Export wizard"
+msgstr "SolidWorks: exportar asistente"
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/ConfigDialog.qml:44
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksWizard.qml:45
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:140
msgctxt "@action:label"
-msgid "Default quality of the exported STL:"
-msgstr "Calidad predeterminada del STL exportado:"
+msgid "Quality:"
+msgstr "Calidad:"
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/ConfigDialog.qml:79
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksWizard.qml:78
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:179
msgctxt "@option:curaSolidworksStlQuality"
-msgid "Always ask"
-msgstr "Preguntar siempre"
+msgid "Fine (3D-printing)"
+msgstr "Fina (impresión en 3D)"
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/ConfigDialog.qml:80
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksWizard.qml:79
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:180
msgctxt "@option:curaSolidworksStlQuality"
-msgid "Always use Fine quality"
-msgstr "Usar siempre calidad fina"
+msgid "Coarse (3D-printing)"
+msgstr "Gruesa (impresión en 3D)"
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/ConfigDialog.qml:81
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksWizard.qml:80
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:181
msgctxt "@option:curaSolidworksStlQuality"
-msgid "Always use Coarse quality"
-msgstr "Usar siempre calidad gruesa"
+msgid "Fine (SolidWorks)"
+msgstr "Fina (SolidWorks)"
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/ExportSTLUI.qml:20
-msgctxt "@title:window"
-msgid "Import SolidWorks File as STL..."
-msgstr "Importar el archivo SolidWorks como STL..."
-
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/ExportSTLUI.qml:43
-msgctxt "@info:tooltip"
-msgid "Quality of the Exported STL"
-msgstr "Calidad del STL exportado"
-
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/ExportSTLUI.qml:48
-msgctxt "@action:label"
-msgid "Quality"
-msgstr "Calidad"
-
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/ExportSTLUI.qml:62
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksWizard.qml:81
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:182
msgctxt "@option:curaSolidworksStlQuality"
-msgid "Coarse"
-msgstr "Gruesa"
+msgid "Coarse (SolidWorks)"
+msgstr "Gruesa (SolidWorks)"
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/ExportSTLUI.qml:63
-msgctxt "@option:curaSolidworksStlQuality"
-msgid "Fine"
-msgstr "Fina"
-
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/ExportSTLUI.qml:78
-#: /home/ruben/Projects/Cura/resources/qml/AskOpenAsProjectOrModelsDialog.qml:82
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksWizard.qml:94
msgctxt "@text:window"
-msgid "Remember my choice"
-msgstr "Recordar mi selección"
+msgid "Show this dialog again"
+msgstr "Mostrar este cuadro de diálogo de nuevo"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:81
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksWizard.qml:104
+msgctxt "@action:button"
+msgid "Continue"
+msgstr "Continuar"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksWizard.qml:116
+msgctxt "@action:button"
+msgid "Abort"
+msgstr "Cancelar"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksMacroTutorial.qml:21
+msgctxt "@title:window"
+msgid "How to install Cura SolidWorks macro"
+msgstr "Cómo instalar la macro SolidWorks de Cura"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksMacroTutorial.qml:62
+msgctxt "@description:label"
+msgid "Steps:"
+msgstr "Pasos:"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksMacroTutorial.qml:140
+msgctxt "@action:button"
+msgid ""
+"Open the directory\n"
+"with macro and icon"
+msgstr ""
+"Abra el directorio\n"
+"con la macro y el icono"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksMacroTutorial.qml:160
+msgctxt "@description:label"
+msgid "Instructions:"
+msgstr "Instrucciones:"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksMacroTutorial.qml:202
+msgctxt "@action:playpause"
+msgid "Play"
+msgstr "Reproducir"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksMacroTutorial.qml:206
+msgctxt "@action:playpause"
+msgid "Pause"
+msgstr "Pausar"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksMacroTutorial.qml:268
+msgctxt "@action:button"
+msgid "Previous Step"
+msgstr "Paso anterior"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksMacroTutorial.qml:283
+msgctxt "@action:button"
+msgid "Done"
+msgstr "Realizado"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksMacroTutorial.qml:287
+msgctxt "@action:button"
+msgid "Next Step"
+msgstr "Paso siguiente"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:21
+msgctxt "@title:window"
+msgid "SolidWorks plugin: Configuration"
+msgstr "Complementos de SolidWorks: configuración"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:39
+msgctxt "@title:tab"
+msgid "Conversion settings"
+msgstr "Ajustes de la conversión"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:66
+msgctxt "@label"
+msgid "First choice:"
+msgstr "Primera opción:"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:86
+msgctxt "@text:menu"
+msgid "Latest installed version (Recommended)"
+msgstr "Última versión instalada (recomendada)"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:95
+msgctxt "@text:menu"
+msgid "Default version"
+msgstr "Versión predeterminada"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:193
+msgctxt "@label"
+msgid "Show wizard before opening SolidWorks files"
+msgstr "Mostrar asistente antes de abrir los archivos de SolidWorks"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:203
+msgctxt "@label"
+msgid "Automatically rotate opened file into normed orientation"
+msgstr "Girar automáticamente el archivo abierto a la orientación normal"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:210
+msgctxt "@title:tab"
+msgid "Installation(s)"
+msgstr "Instalación(es)"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:284
+msgctxt "@label"
+msgid "COM service found"
+msgstr "Servicio COM encontrado"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:295
+msgctxt "@label"
+msgid "Executable found"
+msgstr "Ejecutable encontrado"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:306
+msgctxt "@label"
+msgid "COM starting"
+msgstr "Iniciando COM"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:317
+msgctxt "@label"
+msgid "Revision number"
+msgstr "Número de revisión"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:328
+msgctxt "@label"
+msgid "Functions available"
+msgstr "Funciones disponibles"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:341
+#: /home/ruben/Projects/Cura/resources/qml/WorkspaceSummaryDialog.qml:264
+msgctxt "@action:button"
+msgid "Save"
+msgstr "Guardar"
+
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:117
msgctxt "@label"
msgid "Color scheme"
msgstr "Combinación de colores"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:96
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:132
msgctxt "@label:listbox"
msgid "Material Color"
msgstr "Color del material"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:100
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:136
msgctxt "@label:listbox"
msgid "Line Type"
msgstr "Tipo de línea"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:104
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:140
msgctxt "@label:listbox"
msgid "Feedrate"
msgstr "Velocidad"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:108
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:144
msgctxt "@label:listbox"
msgid "Layer thickness"
msgstr "Grosor de la capa"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:148
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:185
msgctxt "@label"
msgid "Compatibility Mode"
msgstr "Modo de compatibilidad"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:230
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:264
msgctxt "@label"
msgid "Show Travels"
msgstr "Mostrar desplazamientos"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:236
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:270
msgctxt "@label"
msgid "Show Helpers"
msgstr "Mostrar asistentes"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:242
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:276
msgctxt "@label"
msgid "Show Shell"
msgstr "Mostrar perímetro"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:248
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:282
msgctxt "@label"
msgid "Show Infill"
msgstr "Mostrar relleno"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:297
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:330
msgctxt "@label"
msgid "Only Show Top Layers"
msgstr "Mostrar solo capas superiores"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:306
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:339
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:317
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:350
msgctxt "@label"
msgid "Top / Bottom"
msgstr "Superior o inferior"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:321
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:354
msgctxt "@label"
msgid "Inner Wall"
msgstr "Pared interior"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:378
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:410
msgctxt "@label"
msgid "min"
msgstr "mín."
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:420
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:452
msgctxt "@label"
msgid "max"
msgstr "máx."
@@ -1907,7 +2159,7 @@ msgctxt "@label"
msgid "Settings"
msgstr "Ajustes"
-#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.qml:455
+#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.qml:466
msgctxt "@info:tooltip"
msgid "Change active post-processing scripts"
msgstr "Cambia las secuencias de comandos de posprocesamiento."
@@ -1982,23 +2234,53 @@ msgctxt "@action:label"
msgid "Smoothing"
msgstr "Suavizado"
-#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:208
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:38
+msgctxt "@label"
+msgid "Mesh Type"
+msgstr "Tipo de malla"
+
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:69
+msgctxt "@label"
+msgid "Normal model"
+msgstr "Modelo normal"
+
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:76
+msgctxt "@label"
+msgid "Print as support"
+msgstr "Imprimir según compatibilidad"
+
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:84
+msgctxt "@label"
+msgid "Don't support overlap with other models"
+msgstr "No es compatible la superposición con otros modelos"
+
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:92
+msgctxt "@label"
+msgid "Modify settings for overlap with other models"
+msgstr "Modificar ajustes para superponer con otros modelos"
+
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:100
+msgctxt "@label"
+msgid "Modify settings for infill of other models"
+msgstr "Modificar ajustes para rellenar con otros modelos"
+
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:333
msgctxt "@action:button"
msgid "Select settings"
msgstr "Seleccionar ajustes"
-#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:248
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:375
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:272
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:402
#: /home/ruben/Projects/Cura/resources/qml/Preferences/SettingVisibilityPage.qml:91
msgctxt "@label:textbox"
msgid "Filter..."
msgstr "Filtrar..."
-#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:296
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:426
msgctxt "@label:checkbox"
msgid "Show all"
msgstr "Mostrar todo"
@@ -2166,7 +2448,10 @@ msgid ""
"This plugin contains a license.\n"
"You need to accept this license to install this plugin.\n"
"Do you agree with the terms below?"
-msgstr "Este complemento incluye una licencia.\nDebe aceptar dicha licencia para instalar el complemento.\n¿Acepta las condiciones que aparecen a continuación?"
+msgstr ""
+"Este complemento incluye una licencia.\n"
+"Debe aceptar dicha licencia para instalar el complemento.\n"
+"¿Acepta las condiciones que aparecen a continuación?"
#: /home/ruben/Projects/Cura/plugins/PluginBrowser/PluginBrowser.qml:242
msgctxt "@action:button"
@@ -2357,66 +2642,66 @@ 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:88
+#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:87
msgctxt "@label:MonitorStatus"
msgid "Not connected to a printer"
msgstr "No está conectado a ninguna impresora."
-#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:90
+#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:89
msgctxt "@label:MonitorStatus"
msgid "Printer does not accept commands"
msgstr "La impresora no acepta comandos."
-#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:96
+#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:95
#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:194
msgctxt "@label:MonitorStatus"
msgid "In maintenance. Please check the printer"
msgstr "En mantenimiento. Compruebe la impresora."
-#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:103
+#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:102
#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:184
msgctxt "@label:MonitorStatus"
msgid "Printing..."
msgstr "Imprimiendo..."
-#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:106
+#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:105
#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:186
msgctxt "@label:MonitorStatus"
msgid "Paused"
msgstr "En pausa"
-#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:109
+#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:108
#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:188
msgctxt "@label:MonitorStatus"
msgid "Preparing..."
msgstr "Preparando..."
-#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:111
+#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:110
msgctxt "@label:MonitorStatus"
msgid "Please remove the print"
msgstr "Retire la impresión."
-#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:237
+#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:241
msgctxt "@label:"
msgid "Resume"
msgstr "Reanudar"
-#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:241
+#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:245
msgctxt "@label:"
msgid "Pause"
msgstr "Pausar"
-#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:270
+#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:274
msgctxt "@label:"
msgid "Abort Print"
msgstr "Cancelar impresión"
-#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:280
+#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:284
msgctxt "@window:title"
msgid "Abort print"
msgstr "Cancela la impresión"
-#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:282
+#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:286
msgctxt "@label"
msgid "Are you sure you want to abort the print?"
msgstr "¿Está seguro de que desea cancelar la impresión?"
@@ -2431,7 +2716,9 @@ 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?"
+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"
@@ -2449,19 +2736,19 @@ msgid "Customized"
msgstr "Valor personalizado"
#: /home/ruben/Projects/Cura/resources/qml/DiscardOrKeepProfileChangesDialog.qml:157
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:593
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:595
msgctxt "@option:discardOrKeep"
msgid "Always ask me this"
msgstr "Preguntar siempre"
#: /home/ruben/Projects/Cura/resources/qml/DiscardOrKeepProfileChangesDialog.qml:158
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:594
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:596
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
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:595
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:597
msgctxt "@option:discardOrKeep"
msgid "Keep and never ask again"
msgstr "Guardar y no volver a preguntar"
@@ -2496,72 +2783,72 @@ msgctxt "@label"
msgid "Brand"
msgstr "Marca"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:92
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:88
msgctxt "@label"
msgid "Material Type"
msgstr "Tipo de material"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:105
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:97
msgctxt "@label"
msgid "Color"
msgstr "Color"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:139
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:141
msgctxt "@label"
msgid "Properties"
msgstr "Propiedades"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:141
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:143
msgctxt "@label"
msgid "Density"
msgstr "Densidad"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:156
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:158
msgctxt "@label"
msgid "Diameter"
msgstr "Diámetro"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:185
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:187
msgctxt "@label"
msgid "Filament Cost"
msgstr "Coste del filamento"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:201
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:203
msgctxt "@label"
msgid "Filament weight"
-msgstr "Anchura del filamento"
+msgstr "Peso del filamento"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:218
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:220
msgctxt "@label"
msgid "Filament length"
msgstr "Longitud del filamento"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:227
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:229
msgctxt "@label"
msgid "Cost per Meter"
msgstr "Coste por metro"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:241
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:243
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/MaterialView.qml:248
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:250
msgctxt "@label"
msgid "Unlink Material"
msgstr "Desvincular material"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:259
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:261
msgctxt "@label"
msgid "Description"
msgstr "Descripción"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:272
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:274
msgctxt "@label"
msgid "Adhesion Information"
msgstr "Información sobre adherencia"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:298
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:300
msgctxt "@label"
msgid "Print settings"
msgstr "Ajustes de impresión"
@@ -2602,7 +2889,7 @@ msgid "Unit"
msgstr "Unidad"
#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:14
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:439
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:509
msgctxt "@title:tab"
msgid "General"
msgstr "General"
@@ -2617,230 +2904,255 @@ msgctxt "@label"
msgid "Language:"
msgstr "Idioma:"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:205
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:207
msgctxt "@label"
msgid "Currency:"
msgstr "Moneda:"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:219
+#: /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:279
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:281
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:296
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:298
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:304
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:306
msgctxt "@option:check"
msgid "Slice automatically"
msgstr "Segmentar automáticamente"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:318
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:320
msgctxt "@label"
msgid "Viewport behavior"
msgstr "Comportamiento de la ventanilla"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:326
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:328
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:335
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:337
msgctxt "@option:check"
msgid "Display overhang"
msgstr "Mostrar voladizos"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:342
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:344
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:347
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:349
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:356
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:358
msgctxt "@info:tooltip"
msgid "Should the default zoom behavior of cura be inverted?"
msgstr "¿Se debería invertir el comportamiento predeterminado del zoom de cura?"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:361
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:363
msgctxt "@action:button"
msgid "Invert the direction of camera zoom."
msgstr "Invertir la dirección del zoom de la cámara."
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:370
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:372
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:375
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:377
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:384
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:386
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:389
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:391
msgctxt "@option:check"
msgid "Ensure models are kept apart"
msgstr "Asegúrese de que lo modelos están separados."
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:397
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:399
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:402
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:404
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:414
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:416
msgctxt "@info:tooltip"
msgid "Show caution message in gcode reader."
msgstr "Mostrar mensaje de advertencia en el lector de GCode."
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:423
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:425
msgctxt "@option:check"
msgid "Caution message in gcode reader"
msgstr "Mensaje de advertencia en el lector de GCode"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:430
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:432
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:435
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:437
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:451
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:453
msgctxt "@label"
msgid "Opening and saving files"
msgstr "Abrir y guardar archivos"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:457
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:459
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:462
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:464
msgctxt "@option:check"
msgid "Scale large models"
msgstr "Escalar modelos de gran tamaño"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:471
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:473
msgctxt "@info:tooltip"
msgid "An model may appear extremely small if its unit is for example in meters rather than millimeters. Should these models be scaled up?"
msgstr "Un modelo puede mostrarse demasiado pequeño si su unidad son metros en lugar de milímetros, por ejemplo. ¿Deben escalarse estos modelos?"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:476
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:478
msgctxt "@option:check"
msgid "Scale extremely small models"
msgstr "Escalar modelos demasiado pequeños"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:485
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:487
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:490
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:492
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:499
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:501
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:503
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:505
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:512
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:514
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:520
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:522
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:533
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:535
msgctxt "@option:openProject"
msgid "Always ask"
msgstr "Preguntar siempre"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:534
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:536
msgctxt "@option:openProject"
msgid "Always open as a project"
msgstr "Abrir siempre como un proyecto"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:535
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:537
msgctxt "@option:openProject"
msgid "Always import models"
msgstr "Importar modelos siempre"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:571
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:573
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:580
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:582
msgctxt "@label"
msgid "Override Profile"
msgstr "Anular perfil"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:629
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:631
msgctxt "@label"
msgid "Privacy"
msgstr "Privacidad"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:636
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:638
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:641
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:643
msgctxt "@option:check"
msgid "Check for updates on start"
msgstr "Buscar actualizaciones al iniciar"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:651
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:653
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:656
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:658
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:674
+msgctxt "@label"
+msgid "Experimental"
+msgstr "Experimental"
+
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:680
+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:685
+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/GeneralPage.qml:694
+msgctxt "@info:tooltip"
+msgid "Should newly loaded models be arranged on the build plate? Used in conjunction with multi build plate (EXPERIMENTAL)"
+msgstr "¿Los modelos recién cargados se deben organizar en la placa de impresión? Se han usado junto con la placa de impresión múltiple (EXPERIMENTAL)"
+
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:699
+msgctxt "@option:check"
+msgid "Do not arrange objects on load"
+msgstr "No organizar objetos al cargar"
+
#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:15
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:444
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:514
msgctxt "@title:tab"
msgid "Printers"
msgstr "Impresoras"
#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:37
#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:51
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:137
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:138
msgctxt "@action:button"
msgid "Activate"
msgstr "Activar"
@@ -2883,7 +3195,7 @@ msgid "Waiting for a printjob"
msgstr "Esperando un trabajo de impresión..."
#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:15
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:448
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:518
msgctxt "@title:tab"
msgid "Profiles"
msgstr "Perfiles"
@@ -2909,13 +3221,13 @@ msgid "Duplicate"
msgstr "Duplicado"
#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:113
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:201
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:182
msgctxt "@action:button"
msgid "Import"
msgstr "Importar"
#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:119
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:212
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:193
msgctxt "@action:button"
msgid "Export"
msgstr "Exportar"
@@ -2981,7 +3293,7 @@ msgid "Export Profile"
msgstr "Exportar perfil"
#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:15
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:446
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:516
msgctxt "@title:tab"
msgid "Materials"
msgstr "Materiales"
@@ -2996,60 +3308,60 @@ msgctxt "@action:label %1 is printer name"
msgid "Printer: %1"
msgstr "Impresora: %1"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:149
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:150
msgctxt "@action:button"
msgid "Create"
msgstr "Crear"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:168
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:160
msgctxt "@action:button"
msgid "Duplicate"
msgstr "Duplicado"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:311
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:319
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:298
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:306
msgctxt "@title:window"
msgid "Import Material"
msgstr "Importar material"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:320
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:307
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/MaterialsPage.qml:324
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:311
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/MaterialsPage.qml:343
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:358
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:329
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:344
msgctxt "@title:window"
msgid "Export Material"
msgstr "Exportar material"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:362
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:348
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/MaterialsPage.qml:368
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:354
msgctxt "@info:status Don't translate the XML tag !"
msgid "Successfully exported material to %1"
msgstr "El material se ha exportado correctamente a %1."
#: /home/ruben/Projects/Cura/resources/qml/AddMachineDialog.qml:18
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:793
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:869
msgctxt "@title:window"
msgid "Add Printer"
msgstr "Agregar impresora"
-#: /home/ruben/Projects/Cura/resources/qml/AddMachineDialog.qml:185
+#: /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:208
+#: /home/ruben/Projects/Cura/resources/qml/AddMachineDialog.qml:217
msgctxt "@action:button"
msgid "Add Printer"
msgstr "Agregar impresora"
@@ -3074,7 +3386,9 @@ 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.\nCura se enorgullece de utilizar los siguientes proyectos de código abierto:"
+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"
@@ -3176,158 +3490,167 @@ msgctxt "@label"
msgid "Profile:"
msgstr "Perfil:"
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:66
-msgctxt "@"
-msgid "No Profile Available"
-msgstr "No hay perfiles disponibles."
-
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:104
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:102
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\nHaga clic para abrir el administrador de perfiles."
+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:152
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:150
msgctxt "@label:textbox"
msgid "Search..."
msgstr "Buscar..."
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:483
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:482
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:498
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:497
msgctxt "@action:menu"
msgid "Hide this setting"
msgstr "Ocultar este ajuste"
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:508
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:507
msgctxt "@action:menu"
msgid "Don't show this setting"
msgstr "No mostrar este ajuste"
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:512
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:511
msgctxt "@action:menu"
msgid "Keep this setting visible"
msgstr "Mostrar este ajuste"
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:531
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:530
msgctxt "@action:menu"
msgid "Configure setting visiblity..."
msgstr "Configurar la visibilidad de los ajustes..."
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingCategory.qml:123
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingCategory.qml:250
msgctxt "@label"
msgid ""
"Some hidden settings use values different from their normal calculated value.\n"
"\n"
"Click to make these settings visible."
-msgstr "Algunos ajustes ocultos utilizan valores diferentes de los valores normales calculados.\n\nHaga clic para mostrar estos ajustes."
+msgstr ""
+"Algunos ajustes ocultos utilizan valores diferentes de los valores normales calculados.\n"
+"\n"
+"Haga clic para mostrar estos ajustes."
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:62
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:61
msgctxt "@label Header for list of settings."
msgid "Affects"
msgstr "Afecta a"
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:67
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:66
msgctxt "@label Header for list of settings."
msgid "Affected By"
msgstr "Afectado por"
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:157
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:156
msgctxt "@label"
-msgid "This setting is always shared between all extruders. Changing it here will change the value for all extruders"
+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:160
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:159
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:186
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:190
msgctxt "@label"
msgid ""
"This setting has a value that is different from the profile.\n"
"\n"
"Click to restore the value of the profile."
-msgstr "Este ajuste tiene un valor distinto del perfil.\n\nHaga clic para restaurar el valor del perfil."
+msgstr ""
+"Este ajuste tiene un valor distinto del perfil.\n"
+"\n"
+"Haga clic para restaurar el valor del perfil."
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:284
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:288
msgctxt "@label"
msgid ""
"This setting is normally calculated, but it currently has an absolute value set.\n"
"\n"
"Click to restore the calculated value."
-msgstr "Este ajuste se calcula normalmente pero actualmente tiene un valor absoluto establecido.\n\nHaga clic para restaurar el valor calculado."
+msgstr ""
+"Este ajuste se calcula normalmente pero actualmente tiene un valor absoluto establecido.\n"
+"\n"
+"Haga clic para restaurar el valor calculado."
-#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:120
+#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:128
msgctxt "@label:listbox"
msgid "Print Setup"
msgstr "Configuración de impresión"
-#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:120
+#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:128
msgctxt "@label:listbox"
msgid ""
"Print Setup disabled\n"
"G-code files cannot be modified"
-msgstr "Ajustes de impresión deshabilitados\nNo se pueden modificar los archivos GCode"
+msgstr ""
+"Ajustes de impresión deshabilitados\n"
+"No se pueden modificar los archivos GCode"
-#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:336
+#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:342
msgctxt "@label Hours and minutes"
msgid "00h 00min"
msgstr "00 h 00 min"
-#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:354
+#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:359
msgctxt "@tooltip"
-msgid "Time specification
"
-msgstr "Especificación de tiempo
"
+msgid "Time specification"
+msgstr "Especificación de tiempos"
-#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:429
+#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:441
msgctxt "@label"
msgid "Cost specification"
msgstr "Especificación de costes"
-#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:434
-#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:445
+#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:446
+#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:455
msgctxt "@label m for meter"
msgid "%1m"
msgstr "%1 m"
-#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:435
-#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:446
+#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:447
+#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:456
msgctxt "@label g for grams"
msgid "%1g"
msgstr "%1 g"
-#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:444
+#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:454
msgctxt "@label"
msgid "Total:"
msgstr "Total:"
-#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:498
+#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:504
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/resources/qml/Sidebar.qml:503
+#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:509
msgctxt "@label Print estimates: m for meters, g for grams"
msgid "%1m / ~ %2g"
msgstr "%1 m/~ %2 g"
-#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:586
+#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:591
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/Sidebar.qml:591
+#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:596
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/Menus/MaterialMenu.qml:49
+#: /home/ruben/Projects/Cura/resources/qml/Menus/MaterialMenu.qml:50
msgctxt "@title:menuitem %1 is the automatically selected material"
msgid "Automatic: %1"
msgstr "Automático: %1"
@@ -3337,6 +3660,16 @@ msgctxt "@title:menu menubar:toplevel"
msgid "&View"
msgstr "&Ver"
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ViewMenu.qml:37
+msgctxt "@action:inmenu menubar:view"
+msgid "&Camera position"
+msgstr "&Posición de la cámara"
+
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ViewMenu.qml:52
+msgctxt "@action:inmenu menubar:view"
+msgid "&Build plate"
+msgstr "&Placa de impresión"
+
#: /home/ruben/Projects/Cura/resources/qml/Menus/NozzleMenu.qml:40
msgctxt "@title:menuitem %1 is the nozzle currently loaded in the printer"
msgid "Automatic: %1"
@@ -3349,14 +3682,14 @@ msgid_plural "Print Selected Models With:"
msgstr[0] "Imprimir modelo seleccionado con:"
msgstr[1] "Imprimir modelos seleccionados con:"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/ContextMenu.qml:83
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ContextMenu.qml:114
msgctxt "@title:window"
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/Menus/ContextMenu.qml:108
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ContextMenu.qml:139
msgctxt "@label"
msgid "Number of Copies"
msgstr "Número de copias"
@@ -3372,7 +3705,7 @@ msgid "No printer connected"
msgstr "No hay ninguna impresora conectada"
#: /home/ruben/Projects/Cura/resources/qml/PrintMonitor.qml:90
-#: /home/ruben/Projects/Cura/resources/qml/SidebarHeader.qml:138
+#: /home/ruben/Projects/Cura/resources/qml/SidebarHeader.qml:139
msgctxt "@label"
msgid "Extruder"
msgstr "Extrusor"
@@ -3482,254 +3815,294 @@ msgctxt "@label"
msgid "Estimated time left"
msgstr "Tiempo restante estimado"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:72
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:79
msgctxt "@action:inmenu"
msgid "Toggle Fu&ll Screen"
msgstr "A<ernar pantalla completa"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:79
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:86
msgctxt "@action:inmenu menubar:edit"
msgid "&Undo"
msgstr "Des&hacer"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:89
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:96
msgctxt "@action:inmenu menubar:edit"
msgid "&Redo"
msgstr "&Rehacer"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:99
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:106
msgctxt "@action:inmenu menubar:file"
msgid "&Quit"
msgstr "&Salir"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:107
-msgctxt "@action:inmenu menubar:view"
-msgid "&Reset camera position"
-msgstr "&Restablecer posición de la cámara"
-
#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:114
+msgctxt "@action:inmenu menubar:view"
+msgid "&3D View"
+msgstr "&Vista en 3D"
+
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:121
+msgctxt "@action:inmenu menubar:view"
+msgid "&Front View"
+msgstr "&Vista frontal"
+
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:128
+msgctxt "@action:inmenu menubar:view"
+msgid "&Top View"
+msgstr "&Vista superior"
+
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:135
+msgctxt "@action:inmenu menubar:view"
+msgid "&Left Side View"
+msgstr "&Vista del lado izquierdo"
+
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:142
+msgctxt "@action:inmenu menubar:view"
+msgid "&Right Side View"
+msgstr "&Vista del lado derecho"
+
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:149
msgctxt "@action:inmenu"
msgid "Configure Cura..."
msgstr "Configurar Cura..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:121
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:156
msgctxt "@action:inmenu menubar:printer"
msgid "&Add Printer..."
msgstr "&Agregar impresora..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:127
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:162
msgctxt "@action:inmenu menubar:printer"
msgid "Manage Pr&inters..."
-msgstr "Adm&inistrar impresoras ..."
+msgstr "Adm&inistrar impresoras..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:134
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:169
msgctxt "@action:inmenu"
msgid "Manage Materials..."
msgstr "Administrar materiales..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:142
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:177
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:150
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:185
msgctxt "@action:inmenu menubar:profile"
msgid "&Discard current changes"
msgstr "&Descartar cambios actuales"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:162
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:197
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:168
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:203
msgctxt "@action:inmenu menubar:profile"
msgid "Manage Profiles..."
msgstr "Administrar perfiles..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:175
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:210
msgctxt "@action:inmenu menubar:help"
msgid "Show Online &Documentation"
msgstr "Mostrar &documentación en línea"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:183
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:218
msgctxt "@action:inmenu menubar:help"
msgid "Report a &Bug"
msgstr "Informar de un &error"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:191
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:226
msgctxt "@action:inmenu menubar:help"
msgid "&About..."
msgstr "&Acerca de..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:198
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:233
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:208
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:243
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:217
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:252
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:226
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:261
msgctxt "@action:inmenu"
msgid "Delete Model"
msgstr "Eliminar modelo"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:234
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:269
msgctxt "@action:inmenu"
msgid "Ce&nter Model on Platform"
msgstr "Ce&ntrar modelo en plataforma"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:240
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:275
msgctxt "@action:inmenu menubar:edit"
msgid "&Group Models"
msgstr "A&grupar modelos"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:250
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:295
msgctxt "@action:inmenu menubar:edit"
msgid "Ungroup Models"
msgstr "Desagrupar modelos"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:260
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:305
msgctxt "@action:inmenu menubar:edit"
msgid "&Merge Models"
msgstr "Co&mbinar modelos"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:270
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:315
msgctxt "@action:inmenu"
msgid "&Multiply Model..."
msgstr "&Multiplicar modelo..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:277
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:322
msgctxt "@action:inmenu menubar:edit"
msgid "&Select All Models"
msgstr "&Seleccionar todos los modelos"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:287
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:332
msgctxt "@action:inmenu menubar:edit"
msgid "&Clear Build Plate"
msgstr "&Borrar placa de impresión"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:297
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:342
msgctxt "@action:inmenu menubar:file"
msgid "Re&load All Models"
msgstr "&Recargar todos los modelos"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:306
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:351
+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:358
msgctxt "@action:inmenu menubar:edit"
msgid "Arrange All Models"
msgstr "Organizar todos los modelos"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:314
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:366
msgctxt "@action:inmenu menubar:edit"
msgid "Arrange Selection"
msgstr "Organizar selección"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:321
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:373
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:328
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:380
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:335
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:387
msgctxt "@action:inmenu menubar:file"
msgid "&Open File(s)..."
msgstr "&Abrir archivo(s)..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:343
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:395
msgctxt "@action:inmenu menubar:file"
msgid "&New Project..."
msgstr "&Nuevo proyecto..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:350
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:402
msgctxt "@action:inmenu menubar:help"
msgid "Show Engine &Log..."
msgstr "&Mostrar registro del motor..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:358
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:410
msgctxt "@action:inmenu menubar:help"
msgid "Show Configuration Folder"
msgstr "Mostrar carpeta de configuración"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:365
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:417
msgctxt "@action:menu"
msgid "Configure setting visibility..."
msgstr "Configurar visibilidad de los ajustes..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:372
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:424
msgctxt "@action:menu"
msgid "Browse plugins..."
msgstr "Examinar complementos..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:379
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:431
msgctxt "@action:menu"
msgid "Installed plugins..."
msgstr "Complementos instalados..."
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:28
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:438
+msgctxt "@action:inmenu menubar:view"
+msgid "Expand/Collapse Sidebar"
+msgstr "Expandir/contraer barra lateral"
+
+#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:26
msgctxt "@label:PrintjobStatus"
msgid "Please load a 3D model"
msgstr "Cargue un modelo en 3D"
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:34
+#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:36
msgctxt "@label:PrintjobStatus"
msgid "Ready to slice"
msgstr "Preparado para segmentar"
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:36
+#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:38
msgctxt "@label:PrintjobStatus"
msgid "Slicing..."
msgstr "Segmentando..."
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:38
+#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:40
msgctxt "@label:PrintjobStatus %1 is target operation"
msgid "Ready to %1"
msgstr "Listo para %1"
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:40
-msgctxt "@label:PrintjobStatus"
-msgid "Unable to Slice"
-msgstr "No se puede segmentar."
-
#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:42
msgctxt "@label:PrintjobStatus"
-msgid "Slicing unavailable"
+msgid "Unable to Slice"
msgstr "No se puede segmentar"
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:162
+#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:44
+msgctxt "@label:PrintjobStatus"
+msgid "Slicing unavailable"
+msgstr "Segmentación no disponible"
+
+#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:171
+msgctxt "@info:tooltip"
+msgid "Slice current printjob"
+msgstr "Fragmentar trabajo de impresión actual"
+
+#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:171
+msgctxt "@info:tooltip"
+msgid "Cancel slicing process"
+msgstr "Cancelar proceso de fragmentación"
+
+#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:183
msgctxt "@label:Printjob"
msgid "Prepare"
msgstr "Preparar"
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:162
+#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:183
msgctxt "@label:Printjob"
msgid "Cancel"
msgstr "Cancelar"
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:302
+#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:317
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:620
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:696
msgctxt "@title:window"
msgid "Open file(s)"
msgstr "Abrir archivo(s)"
@@ -3749,114 +4122,114 @@ msgctxt "@title:window"
msgid "Ultimaker Cura"
msgstr "Ultimaker Cura"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:81
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:102
msgctxt "@title:menu menubar:toplevel"
msgid "&File"
msgstr "&Archivo"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:98
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:119
msgctxt "@action:inmenu menubar:file"
msgid "&Save Selection to File"
msgstr "Guardar &selección en archivo"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:107
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:128
msgctxt "@title:menu menubar:file"
msgid "Save &As..."
msgstr "Guardar &como..."
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:118
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:139
msgctxt "@title:menu menubar:file"
-msgid "Save project"
-msgstr "Guardar proyecto"
+msgid "Save &Project..."
+msgstr "Guardar &proyecto..."
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:141
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:162
msgctxt "@title:menu menubar:toplevel"
msgid "&Edit"
msgstr "&Edición"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:158
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:179
msgctxt "@title:menu"
msgid "&View"
msgstr "&Ver"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:163
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:184
msgctxt "@title:menu"
msgid "&Settings"
msgstr "A&justes"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:165
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:186
msgctxt "@title:menu menubar:toplevel"
msgid "&Printer"
msgstr "&Impresora"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:175
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:187
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:196
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:208
msgctxt "@title:menu"
msgid "&Material"
msgstr "&Material"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:176
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:188
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:197
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:209
msgctxt "@title:menu"
msgid "&Profile"
msgstr "&Perfil"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:180
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:201
msgctxt "@action:inmenu"
msgid "Set as Active Extruder"
msgstr "Definir como extrusor activo"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:198
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:219
msgctxt "@title:menu menubar:toplevel"
msgid "E&xtensions"
msgstr "E&xtensiones"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:232
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:253
msgctxt "@title:menu menubar:toplevel"
msgid "P&lugins"
msgstr "&Complementos"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:240
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:261
msgctxt "@title:menu menubar:toplevel"
msgid "P&references"
msgstr "Pre&ferencias"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:248
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:269
msgctxt "@title:menu menubar:toplevel"
msgid "&Help"
msgstr "A&yuda"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:330
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:351
msgctxt "@action:button"
msgid "Open File"
msgstr "Abrir archivo"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:442
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:512
msgctxt "@title:tab"
msgid "Settings"
msgstr "Ajustes"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:478
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:554
msgctxt "@title:window"
msgid "New project"
msgstr "Nuevo proyecto"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:479
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:555
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:721
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:797
msgctxt "@window:title"
msgid "Install Plugin"
msgstr "Instalar complemento"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:728
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:804
msgctxt "@title:window"
msgid "Open File(s)"
msgstr "Abrir archivo(s)"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:731
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:807
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."
@@ -3881,97 +4254,82 @@ 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:264
-msgctxt "@action:button"
-msgid "Save"
-msgstr "Guardar"
-
-#: /home/ruben/Projects/Cura/resources/qml/Topbar.qml:74
-msgctxt "@title:tab"
-msgid "Prepare"
-msgstr "Preparar"
-
-#: /home/ruben/Projects/Cura/resources/qml/Topbar.qml:100
-msgctxt "@title:tab"
-msgid "Monitor"
-msgstr "Supervisar"
-
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:163
+#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:175
msgctxt "@label"
msgid "Layer Height"
msgstr "Altura de capa"
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:323
+#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:345
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:340
+#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:362
msgctxt "@label"
msgid "Print Speed"
msgstr "Velocidad de impresión"
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:350
+#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:374
msgctxt "@label"
msgid "Slower"
msgstr "Más lento"
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:361
+#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:385
msgctxt "@label"
msgid "Faster"
msgstr "Más rápido"
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:388
+#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:423
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:413
+#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:446
msgctxt "@label"
msgid "Infill"
msgstr "Relleno"
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:633
+#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:668
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:645
+#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:680
msgctxt "@label"
msgid "Enable gradual"
msgstr "Habilitar gradual"
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:712
+#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:747
msgctxt "@label"
msgid "Generate Support"
msgstr "Generar soporte"
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:746
+#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:781
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:764
+#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:799
msgctxt "@label"
msgid "Support Extruder"
msgstr "Extrusor del soporte"
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:816
+#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:851
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:839
+#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:874
msgctxt "@label"
msgid "Build Plate Adhesion"
msgstr "Adherencia de la placa de impresión"
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:894
+#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:929
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:934
+#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:969
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"
@@ -3988,17 +4346,22 @@ msgctxt "@title:window"
msgid "Open project file"
msgstr "Abrir archivo de proyecto"
-#: /home/ruben/Projects/Cura/resources/qml/AskOpenAsProjectOrModelsDialog.qml:72
+#: /home/ruben/Projects/Cura/resources/qml/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
+msgctxt "@text:window"
+msgid "Remember my choice"
+msgstr "Recordar mi selección"
+
+#: /home/ruben/Projects/Cura/resources/qml/AskOpenAsProjectOrModelsDialog.qml:122
msgctxt "@action:button"
msgid "Open as project"
msgstr "Abrir como proyecto"
-#: /home/ruben/Projects/Cura/resources/qml/AskOpenAsProjectOrModelsDialog.qml:122
+#: /home/ruben/Projects/Cura/resources/qml/AskOpenAsProjectOrModelsDialog.qml:131
msgctxt "@action:button"
msgid "Import models"
msgstr "Importar modelos"
@@ -4008,21 +4371,36 @@ msgctxt "@title:window"
msgid "Engine Log"
msgstr "Registro del motor"
-#: /home/ruben/Projects/Cura/resources/qml/SidebarHeader.qml:242
+#: /home/ruben/Projects/Cura/resources/qml/SidebarHeader.qml:245
msgctxt "@label"
msgid "Material"
msgstr "Material"
-#: /home/ruben/Projects/Cura/resources/qml/SidebarHeader.qml:349
+#: /home/ruben/Projects/Cura/resources/qml/SidebarHeader.qml:352
msgctxt "@label"
-msgid "Check compatibility"
-msgstr "Comprobar compatibilidad"
+msgid "Check compatibility"
+msgstr "Comprobar compatibilidad"
-#: /home/ruben/Projects/Cura/resources/qml/SidebarHeader.qml:369
+#: /home/ruben/Projects/Cura/resources/qml/SidebarHeader.qml:372
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/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/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/ObjectsList.qml:247
+msgctxt "@action:button"
+msgid "Arrange current build plate"
+msgstr "Organizar placa de impresión actual"
+
#: MachineSettingsAction/plugin.json
msgctxt "description"
msgid "Provides a way to change machine settings (such as build volume, nozzle size, etc)"
@@ -4113,6 +4491,26 @@ msgctxt "name"
msgid "USB printing"
msgstr "Impresión USB"
+#: PrepareStage/plugin.json
+msgctxt "description"
+msgid "Provides a prepare stage in Cura."
+msgstr "Proporciona una fase de preparación en Cura."
+
+#: PrepareStage/plugin.json
+msgctxt "name"
+msgid "Prepare Stage"
+msgstr "Fase de preparación"
+
+#: CuraLiveScriptingPlugin/plugin.json
+msgctxt "description"
+msgid "Provides an edit window for direct script editing."
+msgstr "Proporciona una ventana de edición para la edición directa de secuencias de comandos."
+
+#: CuraLiveScriptingPlugin/plugin.json
+msgctxt "name"
+msgid "Live scripting tool"
+msgstr "Herramienta de secuencia de comandos en directo"
+
#: RemovableDriveOutputDevice/plugin.json
msgctxt "description"
msgid "Provides removable drive hotplugging and writing support."
@@ -4133,6 +4531,16 @@ msgctxt "name"
msgid "UM3 Network Connection"
msgstr "Conexión de red UM3"
+#: MonitorStage/plugin.json
+msgctxt "description"
+msgid "Provides a monitor stage in Cura."
+msgstr "Proporciona una fase de supervisión en Cura."
+
+#: MonitorStage/plugin.json
+msgctxt "name"
+msgid "Monitor Stage"
+msgstr "Fase de supervisión"
+
#: FirmwareUpdateChecker/plugin.json
msgctxt "description"
msgid "Checks for firmware updates."
@@ -4145,8 +4553,8 @@ msgstr "Buscador de actualizaciones de firmware"
#: CuraSolidWorksPlugin/plugin.json
msgctxt "description"
-msgid "Gives you the possibility to open certain files via SolidWorks itself. These are then converted and loaded into Cura"
-msgstr "Permite abrir ciertos archivos con el propio SolidWorks que, a continuación, puede convertirse y cargarse en Cura."
+msgid "Gives you the possibility to open certain files using SolidWorks itself. Conversion is done by this plugin and additional optimizations."
+msgstr "Permite abrir determinados archivos con el propio SolidWorks. La conversión se lleva a cabo mediante este complemento y optimizaciones adicionales."
#: CuraSolidWorksPlugin/plugin.json
msgctxt "name"
@@ -4213,6 +4621,16 @@ msgctxt "name"
msgid "Legacy Cura Profile Reader"
msgstr "Lector de perfiles antiguos de Cura"
+#: CuraBlenderPlugin/plugin.json
+msgctxt "description"
+msgid "Helps to open Blender files directly in Cura."
+msgstr "Ayuda a abrir archivos de Blender directamente en Cura."
+
+#: CuraBlenderPlugin/plugin.json
+msgctxt "name"
+msgid "Blender Integration (experimental)"
+msgstr "Integración de Blender (experimental)"
+
#: GCodeProfileReader/plugin.json
msgctxt "description"
msgid "Provides support for importing profiles from g-code files."
@@ -4316,7 +4734,7 @@ msgstr "Herramienta de ajustes por modelo"
#: cura-siemensnx-plugin/plugin.json
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."
#: cura-siemensnx-plugin/plugin.json
msgctxt "name"
@@ -4373,6 +4791,16 @@ msgctxt "name"
msgid "Cura Profile Writer"
msgstr "Escritor de perfiles de Cura"
+#: CuraPrintProfileCreator/plugin.json
+msgctxt "description"
+msgid "Allows material manufacturers to create new material and quality profiles using a drop-in UI."
+msgstr "Permite a los fabricantes de material crear nuevos perfiles de material y calidad mediante una IU integrada."
+
+#: CuraPrintProfileCreator/plugin.json
+msgctxt "name"
+msgid "Print Profile Assistant"
+msgstr "Imprimir asistente del perfil"
+
#: 3MFWriter/plugin.json
msgctxt "description"
msgid "Provides support for writing 3MF files."
@@ -4413,6 +4841,156 @@ msgctxt "name"
msgid "Cura Profile Reader"
msgstr "Lector de perfiles de Cura"
+#~ msgctxt "@label"
+#~ msgid "Unknown"
+#~ msgstr "Desconocido"
+
+#~ msgctxt "@info:status"
+#~ msgid "Errors appeared while opening your SolidWorks file! Please check, whether it is possible to open your file in SolidWorks itself without any problems as well!"
+#~ msgstr "Se han producido varios errores al abrir el archivo de SolidWorks. Compruebe que el archivo se puede abrir correctamente en SolidWorks."
+
+#~ msgctxt "@info:status"
+#~ msgid "Error while starting %s!"
+#~ msgstr "Error al iniciar %s"
+
+#~ msgctxt "@item:inlistbox"
+#~ msgid "Simulation view"
+#~ msgstr "Vista de simulación"
+
+#~ msgctxt "@info"
+#~ msgid "Cura collects anonymised slicing statistics. You can disable this in the preferences."
+#~ msgstr "Cura recopila de forma anónima información de la segmentación. Puede desactivar esta opción en las preferencias."
+
+#~ msgctxt "@action:button"
+#~ msgid "Dismiss"
+#~ msgstr "Descartar"
+
+#~ msgctxt "@menuitem"
+#~ msgid "Global"
+#~ msgstr "Global"
+
+#~ msgctxt "@label crash message"
+#~ msgid ""
+#~ "
A fatal exception has occurred. Please send us this Crash Report to fix the problem
\n"
+#~ "
Please use the \"Send report\" button to post a bug report automatically to our servers
\n"
+#~ " "
+#~ msgstr ""
+#~ "
Se ha producido una excepción fatal. Envíenos este informe de errores para que podamos solucionar el problema.
\n"
+#~ "
Utilice el botón «Enviar informe» para publicar automáticamente un informe de errores en nuestros servidores.
\n"
+#~ " "
+
+#~ msgctxt "@label Cura version"
+#~ msgid "Cura version: {version} "
+#~ msgstr "Versión de Cura: {version} "
+
+#~ msgctxt "@label Platform"
+#~ msgid "Platform: {platform} "
+#~ msgstr "Platforma: {platform} "
+
+#~ msgctxt "@label Qt version"
+#~ msgid "Qt version: {qt} "
+#~ msgstr "Versión de Qt: {qt} "
+
+#~ msgctxt "@label PyQt version"
+#~ msgid "PyQt version: {pyqt} "
+#~ msgstr "Versión de PyQt: {pyqt} "
+
+#~ msgctxt "@label OpenGL"
+#~ msgid "OpenGL: {opengl} "
+#~ msgstr "OpenGL: {opengl} "
+
+#~ msgctxt "@title:groupbox"
+#~ msgid "Exception traceback"
+#~ msgstr "Rastreabilidad de excepciones"
+
+#~ msgctxt "@label"
+#~ msgid "Material diameter"
+#~ msgstr "Diámetro del material"
+
+#~ msgctxt "@label"
+#~ msgid "Ultimaker 3"
+#~ msgstr "Ultimaker 3"
+
+#~ msgctxt "@label"
+#~ msgid "Ultimaker 3 Extended"
+#~ msgstr "Ultimaker 3 Extended"
+
+#~ msgctxt "@title:window"
+#~ msgid "Cura SolidWorks Plugin Configuration"
+#~ msgstr "Configuración de complementos Cura SolidWorks"
+
+#~ msgctxt "@action:label"
+#~ msgid "Default quality of the exported STL:"
+#~ msgstr "Calidad predeterminada del STL exportado:"
+
+#~ msgctxt "@option:curaSolidworksStlQuality"
+#~ msgid "Always ask"
+#~ msgstr "Preguntar siempre"
+
+#~ msgctxt "@option:curaSolidworksStlQuality"
+#~ msgid "Always use Fine quality"
+#~ msgstr "Usar siempre calidad fina"
+
+#~ msgctxt "@option:curaSolidworksStlQuality"
+#~ msgid "Always use Coarse quality"
+#~ msgstr "Usar siempre calidad gruesa"
+
+#~ msgctxt "@title:window"
+#~ msgid "Import SolidWorks File as STL..."
+#~ msgstr "Importar el archivo SolidWorks como STL..."
+
+#~ msgctxt "@info:tooltip"
+#~ msgid "Quality of the Exported STL"
+#~ msgstr "Calidad del STL exportado"
+
+#~ msgctxt "@action:label"
+#~ msgid "Quality"
+#~ msgstr "Calidad"
+
+#~ msgctxt "@option:curaSolidworksStlQuality"
+#~ msgid "Coarse"
+#~ msgstr "Gruesa"
+
+#~ msgctxt "@option:curaSolidworksStlQuality"
+#~ msgid "Fine"
+#~ msgstr "Fina"
+
+#~ msgctxt "@"
+#~ msgid "No Profile Available"
+#~ msgstr "No hay perfiles disponibles."
+
+#~ 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."
+
+#~ msgctxt "@tooltip"
+#~ msgid "Time specification
"
+#~ msgstr "Especificación de tiempo
"
+
+#~ msgctxt "@action:inmenu menubar:view"
+#~ msgid "&Reset camera position"
+#~ msgstr "&Restablecer posición de la cámara"
+
+#~ msgctxt "@title:menu menubar:file"
+#~ msgid "Save project"
+#~ msgstr "Guardar proyecto"
+
+#~ msgctxt "@title:tab"
+#~ msgid "Prepare"
+#~ msgstr "Preparar"
+
+#~ msgctxt "@title:tab"
+#~ msgid "Monitor"
+#~ msgstr "Supervisar"
+
+#~ msgctxt "@label"
+#~ msgid "Check compatibility"
+#~ msgstr "Comprobar compatibilidad"
+
+#~ msgctxt "description"
+#~ msgid "Gives you the possibility to open certain files via SolidWorks itself. These are then converted and loaded into Cura"
+#~ msgstr "Permite abrir ciertos archivos con el propio SolidWorks que, a continuación, puede convertirse y cargarse en Cura."
+
#~ msgctxt "@label:status"
#~ msgid "Blocked"
#~ msgstr "Deshabilitada"
@@ -4433,13 +5011,9 @@ msgstr "Lector de perfiles de Cura"
#~ msgid "To ensure that your {machine_name} is equipped with the latest features it is recommended to update the firmware regularly. This can be done on the {machine_name} (when connected to the network) or via USB."
#~ msgstr "Para garantizar que su {machine_name} disponga de las prestaciones más recientes, se recomienda actualizar el firmware con regularidad. Esto se puede hacer en la {machine_name} (cuando esté conectada a la red) o vía USB."
-msgctxt "@item:inlistbox"
-msgid "Layer view"
-msgstr "Vista de capas"
-
-msgctxt "@info:title"
-msgid "Layer View"
-msgstr "Vista de capas"
+#~ msgctxt "@info:title"
+#~ msgid "Layer View"
+#~ msgstr "Vista de capas"
#~ msgctxt "@menuitem"
#~ msgid "Browse plugins"
@@ -4541,9 +5115,9 @@ msgstr "Vista de capas"
#~ msgid "Provides the Layer view."
#~ msgstr "Proporciona la vista de capas."
-msgctxt "name"
-msgid "Layer View"
-msgstr "Vista de capas"
+#~ msgctxt "name"
+#~ msgid "Layer View"
+#~ msgstr "Vista de capas"
#~ msgctxt "@item:inlistbox"
#~ msgid "X-Ray"
@@ -4864,9 +5438,9 @@ msgstr "Vista de capas"
#~ msgid "Provides support for importing profiles from g-code files."
#~ msgstr "Proporciona asistencia para la importación de perfiles de archivos GCode."
-msgctxt "@label"
-msgid "Layer View"
-msgstr "Vista de capas"
+#~ msgctxt "@label"
+#~ msgid "Layer View"
+#~ msgstr "Vista de capas"
#~ msgctxt "@info:whatsthis"
#~ msgid "Provides the Layer view."
diff --git a/resources/i18n/es_ES/fdmextruder.def.json.po b/resources/i18n/es_ES/fdmextruder.def.json.po
index 1d0986f4e1..e895c053e3 100644
--- a/resources/i18n/es_ES/fdmextruder.def.json.po
+++ b/resources/i18n/es_ES/fdmextruder.def.json.po
@@ -2,12 +2,12 @@
# Copyright (C) 2017 Ultimaker
# This file is distributed under the same license as the Cura package.
# Ruben Dulek , 2017.
-#
+#
msgid ""
msgstr ""
"Project-Id-Version: Cura 3.0\n"
-"Report-Msgid-Bugs-To: http://github.com/ultimaker/uranium\n"
-"POT-Creation-Date: 2017-11-21 16:58+0000\n"
+"Report-Msgid-Bugs-To: r.dulek@ultimaker.com\n"
+"POT-Creation-Date: 2017-08-02 16:53+0000\n"
"PO-Revision-Date: 2017-11-30 13:05+0100\n"
"Last-Translator: Bothof \n"
"Language-Team: Spanish\n"
diff --git a/resources/i18n/es_ES/fdmprinter.def.json.po b/resources/i18n/es_ES/fdmprinter.def.json.po
index d3515844e3..98c2d1da7f 100644
--- a/resources/i18n/es_ES/fdmprinter.def.json.po
+++ b/resources/i18n/es_ES/fdmprinter.def.json.po
@@ -1,20 +1,21 @@
# Cura JSON setting files
-# Copyright (C) 2017 Ultimaker
+# Copyright (C) 2018 Ultimaker
# This file is distributed under the same license as the Cura package.
-# Ruben Dulek , 2017.
-#
+# Ruben Dulek , 2018.
+#
msgid ""
msgstr ""
-"Project-Id-Version: Cura 3.0\n"
-"Report-Msgid-Bugs-To: http://github.com/ultimaker/uranium\n"
-"POT-Creation-Date: 2017-11-21 16:58+0000\n"
-"PO-Revision-Date: 2017-11-30 13:05+0100\n"
+"Project-Id-Version: Cura 3.2\n"
+"Report-Msgid-Bugs-To: r.dulek@ultimaker.com\n"
+"POT-Creation-Date: 2018-01-29 09:48+0000\n"
+"PO-Revision-Date: 2018-02-12 13:40+0100\n"
"Last-Translator: Bothof \n"
"Language-Team: 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"
#: fdmprinter.def.json
msgctxt "machine_settings label"
@@ -56,7 +57,9 @@ msgctxt "machine_start_gcode description"
msgid ""
"Gcode commands to be executed at the very start - separated by \n"
"."
-msgstr "Los comandos de Gcode que se ejecutarán justo al inicio - separados por \n."
+msgstr ""
+"Los comandos de Gcode que se ejecutarán justo al inicio - separados por \n"
+"."
#: fdmprinter.def.json
msgctxt "machine_end_gcode label"
@@ -68,7 +71,9 @@ msgctxt "machine_end_gcode description"
msgid ""
"Gcode commands to be executed at the very end - separated by \n"
"."
-msgstr "Los comandos de Gcode que se ejecutarán justo al final - separados por \n."
+msgstr ""
+"Los comandos de Gcode que se ejecutarán justo al final - separados por \n"
+"."
#: fdmprinter.def.json
msgctxt "material_guid label"
@@ -93,7 +98,7 @@ msgstr "Elija si desea escribir un comando para esperar a que la temperatura de
#: fdmprinter.def.json
msgctxt "material_print_temp_wait label"
msgid "Wait for Nozzle Heatup"
-msgstr "Esperar a la que la tobera se caliente"
+msgstr "Esperar a que la tobera se caliente"
#: fdmprinter.def.json
msgctxt "material_print_temp_wait description"
@@ -345,6 +350,16 @@ msgctxt "machine_gcode_flavor option Repetier"
msgid "Repetier"
msgstr "Repetier"
+#: fdmprinter.def.json
+msgctxt "machine_firmware_retract label"
+msgid "Firmware Retraction"
+msgstr "Retracción de firmware"
+
+#: fdmprinter.def.json
+msgctxt "machine_firmware_retract description"
+msgid "Whether to use firmware retract commands (G10/G11) instead of using the E property in G1 commands to retract the material."
+msgstr "Utilizar o no los comandos de retracción de firmware (G10/G11) en lugar de utilizar la propiedad E en comandos G1 para retraer el material."
+
#: fdmprinter.def.json
msgctxt "machine_disallowed_areas label"
msgid "Disallowed areas"
@@ -398,12 +413,12 @@ msgstr "Diferencia de altura entre la punta de la tobera y el sistema del puente
#: fdmprinter.def.json
msgctxt "machine_nozzle_id label"
msgid "Nozzle ID"
-msgstr "Id. de la tobera"
+msgstr "ID de la tobera"
#: fdmprinter.def.json
msgctxt "machine_nozzle_id description"
msgid "The nozzle ID for an extruder train, such as \"AA 0.4\" and \"BB 0.8\"."
-msgstr "Id. de la tobera de un tren extrusor, como \"AA 0.4\" y \"BB 0.8\"."
+msgstr "ID de la tobera de un tren extrusor, como \"AA 0.4\" y \"BB 0.8\"."
#: fdmprinter.def.json
msgctxt "machine_nozzle_size label"
@@ -605,31 +620,6 @@ msgctxt "layer_height_0 description"
msgid "The height of the initial layer in mm. A thicker initial layer makes adhesion to the build plate easier."
msgstr "Altura de capa inicial en mm. Una capa inicial más gruesa se adhiere a la placa de impresión con mayor facilidad."
-#: fdmprinter.def.json
-msgctxt "slicing_tolerance label"
-msgid "Slicing Tolerance"
-msgstr "Tolerancia de segmentación"
-
-#: fdmprinter.def.json
-msgctxt "slicing_tolerance description"
-msgid "How to slice layers with diagonal surfaces. The areas of a layer can be generated based on where the middle of the layer intersects the surface (Middle). Alternatively each layer can have the areas which fall inside of the volume throughout the height of the layer (Exclusive) or a layer has the areas which fall inside anywhere within the layer (Inclusive). Exclusive retains the most details, Inclusive makes for the best fit and Middle takes the least time to process."
-msgstr "Cómo segmentar capas con superficies diagonales. Las áreas de una capa se pueden crear según el punto en el que el centro de esta intersecta con la superficie (Media). Las capas también pueden tener áreas comprendidas en el volumen a lo largo de la altura de la capa (Exclusiva) o una capa puede tener áreas comprendidas en cualquier lugar de la capa (Inclusiva). Las capas exclusivas tienen un mayor nivel de detalle, mientras que las inclusivas son las que mejor se ajustan y las medias las que tardan menos en procesarse."
-
-#: fdmprinter.def.json
-msgctxt "slicing_tolerance option middle"
-msgid "Middle"
-msgstr "Media"
-
-#: fdmprinter.def.json
-msgctxt "slicing_tolerance option exclusive"
-msgid "Exclusive"
-msgstr "Exclusiva"
-
-#: fdmprinter.def.json
-msgctxt "slicing_tolerance option inclusive"
-msgid "Inclusive"
-msgstr "Inclusiva"
-
#: fdmprinter.def.json
msgctxt "line_width label"
msgid "Line Width"
@@ -670,16 +660,6 @@ msgctxt "wall_line_width_x description"
msgid "Width of a single wall line for all wall lines except the outermost one."
msgstr "Ancho de una sola línea de pared para todas las líneas de pared excepto la más externa."
-#: fdmprinter.def.json
-msgctxt "roofing_line_width label"
-msgid "Top Surface Skin Line Width"
-msgstr "Ancho de línea de la superficie superior del forro"
-
-#: fdmprinter.def.json
-msgctxt "roofing_line_width description"
-msgid "Width of a single line of the areas at the top of the print."
-msgstr "Ancho de una sola línea de las áreas superiores de la impresión."
-
#: fdmprinter.def.json
msgctxt "skin_line_width label"
msgid "Top/Bottom Line Width"
@@ -860,41 +840,6 @@ msgctxt "roofing_layer_count description"
msgid "The number of top most skin layers. Usually only one top most layer is sufficient to generate higher quality top surfaces."
msgstr "El número de capas del nivel superior del forro. Normalmente es suficiente con una sola capa para generar superficies superiores con mayor calidad."
-#: fdmprinter.def.json
-msgctxt "roofing_pattern label"
-msgid "Top Surface Skin Pattern"
-msgstr "Patrón de la superficie superior del forro"
-
-#: fdmprinter.def.json
-msgctxt "roofing_pattern description"
-msgid "The pattern of the top most layers."
-msgstr "El patrón de las capas de nivel superior."
-
-#: fdmprinter.def.json
-msgctxt "roofing_pattern option lines"
-msgid "Lines"
-msgstr "Líneas"
-
-#: fdmprinter.def.json
-msgctxt "roofing_pattern option concentric"
-msgid "Concentric"
-msgstr "Concéntrico"
-
-#: fdmprinter.def.json
-msgctxt "roofing_pattern option zigzag"
-msgid "Zig Zag"
-msgstr "Zigzag"
-
-#: fdmprinter.def.json
-msgctxt "roofing_angles label"
-msgid "Top Surface Skin Line Directions"
-msgstr "Direcciones de línea de la superficie superior del forro"
-
-#: fdmprinter.def.json
-msgctxt "roofing_angles description"
-msgid "A list of integer line directions to use when the top surface skin layers use the lines or zig zag pattern. 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 traditional default angles (45 and 135 degrees)."
-msgstr "Una lista de los valores enteros de las direcciones de línea si las capas de la superficie superior del forro utilizan líneas o el patrón en zigzag. Los elementos de esta lista se utilizan de forma secuencial a medida que las capas se utilizan y, cuando se alcanza el final, la lista vuelve a comenzar desde el principio. Los elementos de la lista están separados por comas y toda la lista aparece entre corchetes. El valor predeterminado es una lista vacía que utiliza los ángulos predeterminados típicos (45 y 135 grados)."
-
#: fdmprinter.def.json
msgctxt "top_bottom_extruder_nr label"
msgid "Top/Bottom Extruder"
@@ -1025,6 +970,16 @@ msgctxt "wall_0_inset description"
msgid "Inset applied to the path of the outer wall. If the outer wall is smaller than the nozzle, and printed after the inner walls, use this offset to get the hole in the nozzle to overlap with the inner walls instead of the outside of the model."
msgstr "Entrante aplicado a la trayectoria de la pared exterior. Si la pared exterior es más pequeña que la tobera y se imprime a continuación de las paredes interiores, utilice este valor de desplazamiento para hacer que el agujero de la tobera se superponga a las paredes interiores del modelo en lugar de a las exteriores."
+#: fdmprinter.def.json
+msgctxt "optimize_wall_printing_order label"
+msgid "Optimize Wall Printing Order"
+msgstr "Optimizar el orden de impresión de paredes"
+
+#: fdmprinter.def.json
+msgctxt "optimize_wall_printing_order description"
+msgid "Optimize the order in which walls are printed so as to reduce the number of retractions and the distance travelled. Most parts will benefit from this being enabled but some may actually take longer so please compare the print time estimates with and without optimization."
+msgstr "Optimizar el orden en el que se imprimen las paredes a fin de reducir el número de retracciones y la distancia recorrida. La mayoría de los componentes se beneficiarán si este ajuste está habilitado pero, en algunos casos, se puede tardar más, por lo que deben compararse las previsiones de tiempo de impresión con y sin optimización."
+
#: fdmprinter.def.json
msgctxt "outer_inset_first label"
msgid "Outer Before Inner Walls"
@@ -1053,7 +1008,7 @@ msgstr "Compensar superposiciones de pared"
#: fdmprinter.def.json
msgctxt "travel_compensate_overlapping_walls_enabled description"
msgid "Compensate the flow for parts of a wall being printed where there is already a wall in place."
-msgstr "Compensa el flujo en partes de una pared que se están imprimiendo dónde ya hay una pared."
+msgstr "Compensa el flujo en partes de una pared que se están imprimiendo donde ya hay una pared."
#: fdmprinter.def.json
msgctxt "travel_compensate_overlapping_walls_0_enabled label"
@@ -1095,6 +1050,16 @@ msgctxt "fill_perimeter_gaps option everywhere"
msgid "Everywhere"
msgstr "En todas partes"
+#: fdmprinter.def.json
+msgctxt "filter_out_tiny_gaps label"
+msgid "Filter Out Tiny Gaps"
+msgstr "Filtrar pequeños huecos"
+
+#: fdmprinter.def.json
+msgctxt "filter_out_tiny_gaps description"
+msgid "Filter out tiny gaps to reduce blobs on outside of model."
+msgstr "Filtrar pequeños huecos para reducir las gotas en la parte externa del modelo."
+
#: fdmprinter.def.json
msgctxt "fill_outline_gaps label"
msgid "Print Thin Walls"
@@ -1383,7 +1348,7 @@ 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."
+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, 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 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"
@@ -1477,8 +1442,8 @@ msgstr "Desplazamiento del relleno sobre el eje X"
#: fdmprinter.def.json
msgctxt "infill_offset_x description"
-msgid "The infill pattern is offset this distance along the X axis."
-msgstr "El patrón de relleno se desplaza esta distancia a lo largo del eje X."
+msgid "The infill pattern is moved this distance along the X axis."
+msgstr "El patrón de relleno se mueve esta distancia a lo largo del eje X."
#: fdmprinter.def.json
msgctxt "infill_offset_y label"
@@ -1487,8 +1452,8 @@ msgstr "Desplazamiento del relleno sobre el eje X"
#: fdmprinter.def.json
msgctxt "infill_offset_y description"
-msgid "The infill pattern is offset this distance along the Y axis."
-msgstr "El patrón de relleno se desplaza esta distancia a lo largo del eje Y."
+msgid "The infill pattern is moved this distance along the Y axis."
+msgstr "El patrón de relleno se mueve esta distancia a lo largo del eje Y."
#: fdmprinter.def.json
msgctxt "sub_div_rad_add label"
@@ -1507,8 +1472,8 @@ msgstr "Porcentaje de superposición del relleno"
#: fdmprinter.def.json
msgctxt "infill_overlap description"
-msgid "The amount of overlap between the infill and the walls. A slight overlap allows the walls to connect firmly to the infill."
-msgstr "Cantidad de superposición entre el relleno y las paredes. Una ligera superposición permite que las paredes conecten firmemente con el relleno."
+msgid "The amount of overlap between the infill and the walls as a percentage of the infill line width. A slight overlap allows the walls to connect firmly to the infill."
+msgstr "La cantidad de superposición entre el relleno y las paredes son un porcentaje del ancho de la línea de relleno. Una ligera superposición permite que las paredes estén firmemente unidas al relleno."
#: fdmprinter.def.json
msgctxt "infill_overlap_mm label"
@@ -1527,8 +1492,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 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 "Cantidad de superposición entre el forro y las paredes como porcentaje del ancho de línea. Una ligera superposición permite que las paredes conecten firmemente con el forro. Este es el porcentaje de la media de los anchos de las líneas del forro y la pared más profunda."
+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."
#: fdmprinter.def.json
msgctxt "skin_overlap_mm label"
@@ -1690,16 +1655,6 @@ msgctxt "material description"
msgid "Material"
msgstr "Material"
-#: fdmprinter.def.json
-msgctxt "material_flow_dependent_temperature label"
-msgid "Auto Temperature"
-msgstr "Temperatura automática"
-
-#: fdmprinter.def.json
-msgctxt "material_flow_dependent_temperature description"
-msgid "Change the temperature for each layer automatically with the average flow speed of that layer."
-msgstr "Cambia automáticamente la temperatura para cada capa con la velocidad media de flujo de esa capa."
-
#: fdmprinter.def.json
msgctxt "default_material_print_temperature label"
msgid "Default Printing Temperature"
@@ -1750,16 +1705,6 @@ msgctxt "material_final_print_temperature description"
msgid "The temperature to which to already start cooling down just before the end of printing."
msgstr "La temperatura a la que se puede empezar a enfriar justo antes de finalizar la impresión."
-#: fdmprinter.def.json
-msgctxt "material_flow_temp_graph label"
-msgid "Flow Temperature Graph"
-msgstr "Gráfico de flujo y temperatura"
-
-#: fdmprinter.def.json
-msgctxt "material_flow_temp_graph description"
-msgid "Data linking material flow (in mm3 per second) to temperature (degrees Celsius)."
-msgstr "Datos que vinculan el flujo de materiales (en 3 mm por segundo) a la temperatura (grados centígrados)."
-
#: fdmprinter.def.json
msgctxt "material_extrusion_cool_down_speed label"
msgid "Extrusion Cool Down Speed Modifier"
@@ -1777,8 +1722,8 @@ msgstr "Temperatura de la placa de impresión"
#: fdmprinter.def.json
msgctxt "material_bed_temperature description"
-msgid "The temperature used for the heated build plate. If this is 0, the bed will not heat up for this print."
-msgstr "Temperatura de la placa de impresión una vez caliente. Si el valor es 0, la plataforma no se calentará en esta impresión."
+msgid "The temperature used for the heated build plate. If this is 0, the bed temperature will not be adjusted."
+msgstr "La temperatura utilizada para la placa de impresión caliente. Si el valor es 0, la temperatura de la plataforma no se ajustará."
#: fdmprinter.def.json
msgctxt "material_bed_temperature_layer_0 label"
@@ -1848,7 +1793,7 @@ msgstr "Retracción en el cambio de capa"
#: fdmprinter.def.json
msgctxt "retract_at_layer_change description"
msgid "Retract the filament when the nozzle is moving to the next layer."
-msgstr "Retrae el filamento cuando la tobera se mueve a la siguiente capa. "
+msgstr "Retrae el filamento cuando la tobera se mueve a la siguiente capa."
#: fdmprinter.def.json
msgctxt "retraction_amount label"
@@ -3450,6 +3395,16 @@ msgctxt "support_tower_roof_angle description"
msgid "The angle of a rooftop of a tower. A higher value results in pointed tower roofs, a lower value results in flattened tower roofs."
msgstr "Ángulo del techo superior de una torre. Un valor más alto da como resultado techos de torre en punta, un valor más bajo da como resultado techos de torre planos."
+#: fdmprinter.def.json
+msgctxt "support_mesh_drop_down label"
+msgid "Drop Down Support Mesh"
+msgstr "Malla de soporte desplegable"
+
+#: fdmprinter.def.json
+msgctxt "support_mesh_drop_down description"
+msgid "Make support everywhere below the support mesh, so that there's no overhang in the support mesh."
+msgstr "Disponga un soporte en todas partes por debajo de la malla de soporte, para que no haya voladizo en la malla de soporte."
+
#: fdmprinter.def.json
msgctxt "platform_adhesion label"
msgid "Build Plate Adhesion"
@@ -3550,7 +3505,9 @@ msgctxt "skirt_gap description"
msgid ""
"The horizontal distance between the skirt and the first layer of the print.\n"
"This is the minimum distance. Multiple skirt lines will extend outwards from this distance."
-msgstr "La distancia horizontal entre la falda y la primera capa de la impresión.\nSe trata de la distancia mínima. Múltiples líneas de falda se extenderán hacia el exterior a partir de esta distancia."
+msgstr ""
+"La distancia horizontal entre la falda y la primera capa de la impresión.\n"
+"Se trata de la distancia mínima. Múltiples líneas de falda se extenderán hacia el exterior a partir de esta distancia."
#: fdmprinter.def.json
msgctxt "skirt_brim_minimal_length label"
@@ -4082,16 +4039,6 @@ msgctxt "meshfix_keep_open_polygons description"
msgid "Normally Cura tries to stitch up small holes in the mesh and remove parts of a layer with big holes. Enabling this option keeps those parts which cannot be stitched. This option should be used as a last resort option when everything else fails to produce proper GCode."
msgstr "Normalmente, Cura intenta coser los pequeños agujeros de la malla y eliminar las partes de una capa con grandes agujeros. Al habilitar esta opción se mantienen aquellas partes que no puedan coserse. Esta opción se debe utilizar como una opción de último recurso cuando todo lo demás falla para producir un GCode adecuado."
-#: fdmprinter.def.json
-msgctxt "meshfix_maximum_resolution label"
-msgid "Maximum Resolution"
-msgstr "Resolución máxima"
-
-#: fdmprinter.def.json
-msgctxt "meshfix_maximum_resolution description"
-msgid "The minimum size of a line segment after slicing. If you increase this, the mesh will have a lower resolution. This may allow the printer to keep up with the speed it has to process g-code and will increase slice speed by removing details of the mesh that it can't process anyway."
-msgstr "El tamaño mínimo de un segmento de línea tras la segmentación. Si se aumenta, la resolución de la malla será menor. Esto puede permitir a la impresora mantener la velocidad que necesita para procesar GCode y aumentará la velocidad de segmentación al eliminar detalles de la malla que, de todas formas, no puede procesar."
-
#: fdmprinter.def.json
msgctxt "multiple_mesh_overlap label"
msgid "Merged Meshes Overlap"
@@ -4242,16 +4189,6 @@ msgctxt "support_mesh description"
msgid "Use this mesh to specify support areas. This can be used to generate support structure."
msgstr "Utilice esta malla para especificar las áreas de soporte. Esta opción puede utilizarse para generar estructuras de soporte."
-#: fdmprinter.def.json
-msgctxt "support_mesh_drop_down label"
-msgid "Drop Down Support Mesh"
-msgstr "Malla de soporte desplegable"
-
-#: fdmprinter.def.json
-msgctxt "support_mesh_drop_down description"
-msgid "Make support everywhere below the support mesh, so that there's no overhang in the support mesh."
-msgstr "Disponga un soporte en todas partes por debajo de la malla de soporte, para que no haya voladizo en la malla de soporte."
-
#: fdmprinter.def.json
msgctxt "anti_overhang_mesh label"
msgid "Anti Overhang Mesh"
@@ -4328,14 +4265,194 @@ msgid "experimental!"
msgstr "Experimental"
#: fdmprinter.def.json
-msgctxt "optimize_wall_printing_order label"
-msgid "Optimize Wall Printing Order"
-msgstr "Optimizar el orden de impresión de paredes"
+msgctxt "support_tree_enable label"
+msgid "Tree Support"
+msgstr "Soporte en árbol"
#: fdmprinter.def.json
-msgctxt "optimize_wall_printing_order description"
-msgid "Optimize the order in which walls are printed so as to reduce the number of retractions and the distance travelled. Most parts will benefit from this being enabled but some may actually take longer so please compare the print time estimates with and without optimization."
-msgstr "Optimizar el orden en el que se imprimen las paredes a fin de reducir el número de retracciones y la distancia recorrida. La mayoría de los componentes se beneficiarán si este ajuste está habilitado pero, en algunos casos, se puede tardar más, por lo que deben compararse las previsiones de tiempo de impresión con y sin optimización."
+msgctxt "support_tree_enable description"
+msgid "Generate a tree-like support with branches that support your print. This may reduce material usage and print time, but greatly increases slicing time."
+msgstr "Generar un soporte en forma de árbol con ramas que apoyan la impresión. Esto puede reducir el uso de material y el tiempo de impresión, pero aumenta considerablemente el tiempo de fragmentación."
+
+#: fdmprinter.def.json
+msgctxt "support_tree_angle label"
+msgid "Tree Support Branch Angle"
+msgstr "Ángulo de las ramas del soporte en árbol"
+
+#: fdmprinter.def.json
+msgctxt "support_tree_angle description"
+msgid "The angle of the branches. Use a lower angle to make them more vertical and more stable. Use a higher angle to be able to have more reach."
+msgstr "El ángulo de las ramas. Utilice un ángulo inferior para que sean más verticales y estables. Utilice un ángulo superior para poder tener más alcance."
+
+#: fdmprinter.def.json
+msgctxt "support_tree_branch_distance label"
+msgid "Tree Support Branch Distance"
+msgstr "Distancia de las ramas del soporte en árbol"
+
+#: fdmprinter.def.json
+msgctxt "support_tree_branch_distance description"
+msgid "How far apart the branches need to be when they touch the model. Making this distance small will cause the tree support to touch the model at more points, causing better overhang but making support harder to remove."
+msgstr "Qué separación deben tener las ramas cuando tocan el modelo. Reducir esta distancia ocasionará que el soporte en árbol toque el modelo en más puntos, produciendo mejor cobertura pero dificultando la tarea de retirar el soporte."
+
+#: fdmprinter.def.json
+msgctxt "support_tree_branch_diameter label"
+msgid "Tree Support Branch Diameter"
+msgstr "Diámetro de las ramas del soporte en árbol"
+
+#: fdmprinter.def.json
+msgctxt "support_tree_branch_diameter description"
+msgid "The diameter of the thinnest branches of tree support. Thicker branches are more sturdy. Branches towards the base will be thicker than this."
+msgstr "El diámetro de las ramas más finas del soporte en árbol. Cuanto más gruesas sean las ramas, más robustas serán. Las ramas que estén cerca de la base serán más gruesas que esto."
+
+#: fdmprinter.def.json
+msgctxt "support_tree_branch_diameter_angle label"
+msgid "Tree Support Branch Diameter Angle"
+msgstr "Ángulo de diámetro de las ramas del soporte en árbol"
+
+#: fdmprinter.def.json
+msgctxt "support_tree_branch_diameter_angle description"
+msgid "The angle of the branches' diameter as they gradually become thicker towards the bottom. An angle of 0 will cause the branches to have uniform thickness over their length. A bit of an angle can increase stability of the tree support."
+msgstr "El ángulo del diámetro de las ramas es gradualmente más alto según se acercan a la base. Un ángulo de 0 ocasionará que las ramas tengan un grosor uniforme en toda su longitud. Un poco de ángulo puede aumentar la estabilidad del soporte en árbol."
+
+#: fdmprinter.def.json
+msgctxt "support_tree_collision_resolution label"
+msgid "Tree Support Collision Resolution"
+msgstr "Resolución de colisión del soporte en árbol"
+
+#: fdmprinter.def.json
+msgctxt "support_tree_collision_resolution description"
+msgid "Resolution to compute collisions with to avoid hitting the model. Setting this lower will produce more accurate trees that fail less often, but increases slicing time dramatically."
+msgstr "Resolución para computar colisiones para evitar golpear el modelo. Establecer un ajuste bajo producirá árboles más precisos que producen fallos con menor frecuencia, pero aumenta significativamente el tiempo de fragmentación."
+
+#: fdmprinter.def.json
+msgctxt "support_tree_wall_thickness label"
+msgid "Tree Support Wall Thickness"
+msgstr "Grosor de las paredes del soporte en árbol"
+
+#: fdmprinter.def.json
+msgctxt "support_tree_wall_thickness description"
+msgid "The thickness of the walls of the branches of tree support. Thicker walls take longer to print but don't fall over as easily."
+msgstr "El grosor de las paredes de las ramas del soporte en árbol. Imprimir paredes más gruesas llevará más tiempo pero no se caerán tan fácilmente."
+
+#: fdmprinter.def.json
+msgctxt "support_tree_wall_count label"
+msgid "Tree Support Wall Line Count"
+msgstr "Recuento de líneas de pared del soporte en árbol"
+
+#: fdmprinter.def.json
+msgctxt "support_tree_wall_count description"
+msgid "The number of walls of the branches of tree support. Thicker walls take longer to print but don't fall over as easily."
+msgstr "El número de las paredes de las ramas del soporte en árbol. Imprimir paredes más gruesas llevará más tiempo pero no se caerán tan fácilmente."
+
+#: fdmprinter.def.json
+msgctxt "slicing_tolerance label"
+msgid "Slicing Tolerance"
+msgstr "Tolerancia de segmentación"
+
+#: fdmprinter.def.json
+msgctxt "slicing_tolerance description"
+msgid "How to slice layers with diagonal surfaces. The areas of a layer can be generated based on where the middle of the layer intersects the surface (Middle). Alternatively each layer can have the areas which fall inside of the volume throughout the height of the layer (Exclusive) or a layer has the areas which fall inside anywhere within the layer (Inclusive). Exclusive retains the most details, Inclusive makes for the best fit and Middle takes the least time to process."
+msgstr "Cómo segmentar capas con superficies diagonales. Las áreas de una capa se pueden crear según el punto en el que el centro de esta intersecta con la superficie (Media). Las capas también pueden tener áreas comprendidas en el volumen a lo largo de la altura de la capa (Exclusiva) o una capa puede tener áreas comprendidas en cualquier lugar de la capa (Inclusiva). Las capas exclusivas tienen un mayor nivel de detalle, mientras que las inclusivas son las que mejor se ajustan y las medias las que tardan menos en procesarse."
+
+#: fdmprinter.def.json
+msgctxt "slicing_tolerance option middle"
+msgid "Middle"
+msgstr "Media"
+
+#: fdmprinter.def.json
+msgctxt "slicing_tolerance option exclusive"
+msgid "Exclusive"
+msgstr "Exclusiva"
+
+#: fdmprinter.def.json
+msgctxt "slicing_tolerance option inclusive"
+msgid "Inclusive"
+msgstr "Inclusiva"
+
+#: fdmprinter.def.json
+msgctxt "roofing_line_width label"
+msgid "Top Surface Skin Line Width"
+msgstr "Ancho de línea de la superficie superior del forro"
+
+#: fdmprinter.def.json
+msgctxt "roofing_line_width description"
+msgid "Width of a single line of the areas at the top of the print."
+msgstr "Ancho de una sola línea de las áreas superiores de la impresión."
+
+#: fdmprinter.def.json
+msgctxt "roofing_pattern label"
+msgid "Top Surface Skin Pattern"
+msgstr "Patrón de la superficie superior del forro"
+
+#: fdmprinter.def.json
+msgctxt "roofing_pattern description"
+msgid "The pattern of the top most layers."
+msgstr "El patrón de las capas de nivel superior."
+
+#: fdmprinter.def.json
+msgctxt "roofing_pattern option lines"
+msgid "Lines"
+msgstr "Líneas"
+
+#: fdmprinter.def.json
+msgctxt "roofing_pattern option concentric"
+msgid "Concentric"
+msgstr "Concéntrico"
+
+#: fdmprinter.def.json
+msgctxt "roofing_pattern option zigzag"
+msgid "Zig Zag"
+msgstr "Zigzag"
+
+#: fdmprinter.def.json
+msgctxt "roofing_angles label"
+msgid "Top Surface Skin Line Directions"
+msgstr "Direcciones de línea de la superficie superior del forro"
+
+#: fdmprinter.def.json
+msgctxt "roofing_angles description"
+msgid "A list of integer line directions to use when the top surface skin layers use the lines or zig zag pattern. 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 traditional default angles (45 and 135 degrees)."
+msgstr "Una lista de los valores enteros de las direcciones de línea si las capas de la superficie superior del forro utilizan líneas o el patrón en zigzag. Los elementos de esta lista se utilizan de forma secuencial a medida que las capas se utilizan y, cuando se alcanza el final, la lista vuelve a comenzar desde el principio. Los elementos de la lista están separados por comas y toda la lista aparece entre corchetes. El valor predeterminado es una lista vacía que utiliza los ángulos predeterminados típicos (45 y 135 grados)."
+
+#: fdmprinter.def.json
+msgctxt "infill_enable_travel_optimization label"
+msgid "Infill Travel Optimization"
+msgstr "Optimización del desplazamiento del relleno"
+
+#: fdmprinter.def.json
+msgctxt "infill_enable_travel_optimization description"
+msgid "When enabled, the order in which the infill lines are printed is optimized to reduce the distance travelled. The reduction in travel time achieved very much depends on the model being sliced, infill pattern, density, etc. Note that, for some models that have many small areas of infill, the time to slice the model may be greatly increased."
+msgstr "Cuando está habilitado, se optimiza el orden en el que se imprimen las líneas de relleno para reducir la distancia de desplazamiento. La reducción del tiempo de desplazamiento obtenido depende en gran parte del modelo que se está fragmentando, el patrón de relleno, la densidad, etc. Tenga en cuenta que, para algunos modelos que tienen pequeñas áreas de relleno, el tiempo para fragmentar el modelo se puede aumentar en gran medida."
+
+#: fdmprinter.def.json
+msgctxt "material_flow_dependent_temperature label"
+msgid "Auto Temperature"
+msgstr "Temperatura automática"
+
+#: fdmprinter.def.json
+msgctxt "material_flow_dependent_temperature description"
+msgid "Change the temperature for each layer automatically with the average flow speed of that layer."
+msgstr "Cambia automáticamente la temperatura para cada capa con la velocidad media de flujo de esa capa."
+
+#: fdmprinter.def.json
+msgctxt "material_flow_temp_graph label"
+msgid "Flow Temperature Graph"
+msgstr "Gráfico de flujo y temperatura"
+
+#: fdmprinter.def.json
+msgctxt "material_flow_temp_graph description"
+msgid "Data linking material flow (in mm3 per second) to temperature (degrees Celsius)."
+msgstr "Datos que vinculan el flujo de materiales (en 3 mm por segundo) a la temperatura (grados centígrados)."
+
+#: fdmprinter.def.json
+msgctxt "meshfix_maximum_resolution label"
+msgid "Maximum Resolution"
+msgstr "Resolución máxima"
+
+#: fdmprinter.def.json
+msgctxt "meshfix_maximum_resolution description"
+msgid "The minimum size of a line segment after slicing. If you increase this, the mesh will have a lower resolution. This may allow the printer to keep up with the speed it has to process g-code and will increase slice speed by removing details of the mesh that it can't process anyway."
+msgstr "El tamaño mínimo de un segmento de línea tras la segmentación. Si se aumenta, la resolución de la malla será menor. Esto puede permitir a la impresora mantener la velocidad que necesita para procesar GCode y aumentará la velocidad de segmentación al eliminar detalles de la malla que, de todas formas, no puede procesar."
#: fdmprinter.def.json
msgctxt "support_skip_some_zags label"
@@ -4827,7 +4944,9 @@ msgctxt "wireframe_up_half_speed description"
msgid ""
"Distance of an upward move which is extruded with half speed.\n"
"This can cause better adhesion to previous layers, while not heating the material in those layers too much. Only applies to Wire Printing."
-msgstr "Distancia de un movimiento ascendente que se extrude a media velocidad.\nEsto puede causar una mejor adherencia a las capas anteriores, aunque no calienta demasiado el material en esas capas. Solo se aplica a la impresión de alambre."
+msgstr ""
+"Distancia de un movimiento ascendente que se extrude a media velocidad.\n"
+"Esto puede causar una mejor adherencia a las capas anteriores, aunque no calienta demasiado el material en esas capas. Solo se aplica a la impresión de alambre."
#: fdmprinter.def.json
msgctxt "wireframe_top_jump label"
@@ -4934,6 +5053,46 @@ msgctxt "wireframe_nozzle_clearance description"
msgid "Distance between the nozzle and horizontally downward lines. Larger clearance results in diagonally downward lines with a less steep angle, which in turn results in less upward connections with the next layer. Only applies to Wire Printing."
msgstr "Distancia entre la tobera y líneas descendentes en horizontal. Cuanto mayor sea la holgura, menos pronunciado será el ángulo de las líneas descendentes en diagonal, lo que a su vez se traduce en menos conexiones ascendentes con la siguiente capa. Solo se aplica a la impresión de alambre."
+#: fdmprinter.def.json
+msgctxt "adaptive_layer_height_enabled label"
+msgid "Use adaptive layers"
+msgstr "Utilizar capas de adaptación"
+
+#: fdmprinter.def.json
+msgctxt "adaptive_layer_height_enabled description"
+msgid "Adaptive layers computes the layer heights depending on the shape of the model."
+msgstr "Las capas de adaptación calculan las alturas de las capas dependiendo de la forma del modelo."
+
+#: fdmprinter.def.json
+msgctxt "adaptive_layer_height_variation label"
+msgid "Adaptive layers maximum variation"
+msgstr "Variación máxima de las capas de adaptación"
+
+#: fdmprinter.def.json
+msgctxt "adaptive_layer_height_variation description"
+msgid "The maximum allowed height different from the base layer height in mm."
+msgstr "La diferencia de altura máxima permitida en comparación con la altura de la capa base en mm."
+
+#: fdmprinter.def.json
+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"
+
+#: fdmprinter.def.json
+msgctxt "adaptive_layer_height_variation_step description"
+msgid "The difference in height of the next layer height compared to the previous one."
+msgstr "La diferencia de altura de la siguiente altura de capa en comparación con la anterior."
+
+#: fdmprinter.def.json
+msgctxt "adaptive_layer_height_threshold label"
+msgid "Adaptive layers threshold"
+msgstr "Umbral de las capas de adaptación"
+
+#: fdmprinter.def.json
+msgctxt "adaptive_layer_height_threshold description"
+msgid "Threshold whether to use a smaller layer or not. This number is compared to the tan of the steepest slope in a layer."
+msgstr "Umbral para usar o no una capa más pequeña. Este número se compara con el curtido de la pendiente más empinada de una capa."
+
#: fdmprinter.def.json
msgctxt "command_line_settings label"
msgid "Command Line Settings"
@@ -4994,6 +5153,26 @@ 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 "infill_offset_x description"
+#~ msgid "The infill pattern is offset this distance along the X axis."
+#~ msgstr "El patrón de relleno se desplaza esta distancia a lo largo del eje X."
+
+#~ msgctxt "infill_offset_y description"
+#~ msgid "The infill pattern is offset this distance along the Y axis."
+#~ msgstr "El patrón de relleno se desplaza esta distancia a lo largo del eje Y."
+
+#~ msgctxt "infill_overlap description"
+#~ msgid "The amount of overlap between the infill and the walls. A slight overlap allows the walls to connect firmly to the infill."
+#~ msgstr "Cantidad de superposición entre el relleno y las paredes. Una ligera superposición permite que las paredes conecten firmemente con el relleno."
+
+#~ msgctxt "skin_overlap description"
+#~ msgid "The amount of overlap between the skin and the walls as a percentage of the 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 "Cantidad de superposición entre el forro y las paredes como porcentaje del ancho de línea. Una ligera superposición permite que las paredes conecten firmemente con el forro. Este es el porcentaje de la media de los anchos de las líneas del forro y la pared más profunda."
+
+#~ msgctxt "material_bed_temperature description"
+#~ msgid "The temperature used for the heated build plate. If this is 0, the bed will not heat up for this print."
+#~ msgstr "Temperatura de la placa de impresión una vez caliente. Si el valor es 0, la plataforma no se calentará en esta impresión."
+
#~ msgctxt "wall_x_extruder_nr label"
#~ msgid "Inner Walls Extruder"
#~ msgstr "Extrusor de paredes interiores"
diff --git a/resources/i18n/fdmextruder.def.json.pot b/resources/i18n/fdmextruder.def.json.pot
index af77729254..454d324874 100644
--- a/resources/i18n/fdmextruder.def.json.pot
+++ b/resources/i18n/fdmextruder.def.json.pot
@@ -1,11 +1,11 @@
# Cura JSON setting files
-# Copyright (C) 2017 Ultimaker
+# Copyright (C) 2018 Ultimaker
# This file is distributed under the same license as the Cura package.
-# Ruben Dulek , 2017.
+# Ruben Dulek , 2018.
#
msgid ""
msgstr ""
-"Project-Id-Version: Cura 3.1\n"
+"Project-Id-Version: Cura 3.2\n"
"Report-Msgid-Bugs-To: r.dulek@ultimaker.com\n"
"POT-Creation-Date: 2017-08-02 16:53+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
diff --git a/resources/i18n/fdmprinter.def.json.pot b/resources/i18n/fdmprinter.def.json.pot
index 9d5ef93fc3..126c02a207 100644
--- a/resources/i18n/fdmprinter.def.json.pot
+++ b/resources/i18n/fdmprinter.def.json.pot
@@ -1,11 +1,11 @@
# Cura JSON setting files
-# Copyright (C) 2017 Ultimaker
+# Copyright (C) 2018 Ultimaker
# This file is distributed under the same license as the Cura package.
-# Ruben Dulek , 2017.
+# Ruben Dulek , 2018.
#
msgid ""
msgstr ""
-"Project-Id-Version: Cura 3.1\n"
+"Project-Id-Version: Cura 3.2\n"
"Report-Msgid-Bugs-To: r.dulek@ultimaker.com\n"
"POT-Creation-Date: 2017-08-02 16:53+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
@@ -377,6 +377,18 @@ msgctxt "machine_gcode_flavor option Repetier"
msgid "Repetier"
msgstr ""
+#: fdmprinter.def.json
+msgctxt "machine_firmware_retract label"
+msgid "Firmware Retraction"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "machine_firmware_retract description"
+msgid ""
+"Whether to use firmware retract commands (G10/G11) instead of using the E "
+"property in G1 commands to retract the material."
+msgstr ""
+
#: fdmprinter.def.json
msgctxt "machine_disallowed_areas label"
msgid "Disallowed areas"
@@ -651,38 +663,6 @@ msgid ""
"adhesion to the build plate easier."
msgstr ""
-#: fdmprinter.def.json
-msgctxt "slicing_tolerance label"
-msgid "Slicing Tolerance"
-msgstr ""
-
-#: fdmprinter.def.json
-msgctxt "slicing_tolerance description"
-msgid ""
-"How to slice layers with diagonal surfaces. The areas of a layer can be "
-"generated based on where the middle of the layer intersects the surface "
-"(Middle). Alternatively each layer can have the areas which fall inside of "
-"the volume throughout the height of the layer (Exclusive) or a layer has the "
-"areas which fall inside anywhere within the layer (Inclusive). Exclusive "
-"retains the most details, Inclusive makes for the best fit and Middle takes "
-"the least time to process."
-msgstr ""
-
-#: fdmprinter.def.json
-msgctxt "slicing_tolerance option middle"
-msgid "Middle"
-msgstr ""
-
-#: fdmprinter.def.json
-msgctxt "slicing_tolerance option exclusive"
-msgid "Exclusive"
-msgstr ""
-
-#: fdmprinter.def.json
-msgctxt "slicing_tolerance option inclusive"
-msgid "Inclusive"
-msgstr ""
-
#: fdmprinter.def.json
msgctxt "line_width label"
msgid "Line Width"
@@ -729,16 +709,6 @@ msgid ""
"Width of a single wall line for all wall lines except the outermost one."
msgstr ""
-#: fdmprinter.def.json
-msgctxt "roofing_line_width label"
-msgid "Top Surface Skin Line Width"
-msgstr ""
-
-#: fdmprinter.def.json
-msgctxt "roofing_line_width description"
-msgid "Width of a single line of the areas at the top of the print."
-msgstr ""
-
#: fdmprinter.def.json
msgctxt "skin_line_width label"
msgid "Top/Bottom Line Width"
@@ -937,47 +907,6 @@ msgid ""
"sufficient to generate higher quality top surfaces."
msgstr ""
-#: fdmprinter.def.json
-msgctxt "roofing_pattern label"
-msgid "Top Surface Skin Pattern"
-msgstr ""
-
-#: fdmprinter.def.json
-msgctxt "roofing_pattern description"
-msgid "The pattern of the top most layers."
-msgstr ""
-
-#: fdmprinter.def.json
-msgctxt "roofing_pattern option lines"
-msgid "Lines"
-msgstr ""
-
-#: fdmprinter.def.json
-msgctxt "roofing_pattern option concentric"
-msgid "Concentric"
-msgstr ""
-
-#: fdmprinter.def.json
-msgctxt "roofing_pattern option zigzag"
-msgid "Zig Zag"
-msgstr ""
-
-#: fdmprinter.def.json
-msgctxt "roofing_angles label"
-msgid "Top Surface Skin Line Directions"
-msgstr ""
-
-#: fdmprinter.def.json
-msgctxt "roofing_angles description"
-msgid ""
-"A list of integer line directions to use when the top surface skin layers "
-"use the lines or zig zag pattern. 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 traditional default angles (45 and 135 degrees)."
-msgstr ""
-
#: fdmprinter.def.json
msgctxt "top_bottom_extruder_nr label"
msgid "Top/Bottom Extruder"
@@ -1130,6 +1059,20 @@ msgid ""
"outside of the model."
msgstr ""
+#: fdmprinter.def.json
+msgctxt "optimize_wall_printing_order label"
+msgid "Optimize Wall Printing Order"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "optimize_wall_printing_order description"
+msgid ""
+"Optimize the order in which walls are printed so as to reduce the number of "
+"retractions and the distance travelled. Most parts will benefit from this "
+"being enabled but some may actually take longer so please compare the print "
+"time estimates with and without optimization."
+msgstr ""
+
#: fdmprinter.def.json
msgctxt "outer_inset_first label"
msgid "Outer Before Inner Walls"
@@ -1212,6 +1155,16 @@ msgctxt "fill_perimeter_gaps option everywhere"
msgid "Everywhere"
msgstr ""
+#: fdmprinter.def.json
+msgctxt "filter_out_tiny_gaps label"
+msgid "Filter Out Tiny Gaps"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "filter_out_tiny_gaps description"
+msgid "Filter out tiny gaps to reduce blobs on outside of model."
+msgstr ""
+
#: fdmprinter.def.json
msgctxt "fill_outline_gaps label"
msgid "Print Thin Walls"
@@ -1656,7 +1609,7 @@ msgstr ""
#: fdmprinter.def.json
msgctxt "infill_offset_x description"
-msgid "The infill pattern is offset this distance along the X axis."
+msgid "The infill pattern is moved this distance along the X axis."
msgstr ""
#: fdmprinter.def.json
@@ -1666,7 +1619,7 @@ msgstr ""
#: fdmprinter.def.json
msgctxt "infill_offset_y description"
-msgid "The infill pattern is offset this distance along the Y axis."
+msgid "The infill pattern is moved this distance along the Y axis."
msgstr ""
#: fdmprinter.def.json
@@ -1691,8 +1644,9 @@ msgstr ""
#: fdmprinter.def.json
msgctxt "infill_overlap description"
msgid ""
-"The amount of overlap between the infill and the walls. A slight overlap "
-"allows the walls to connect firmly to the infill."
+"The amount of overlap between the infill and the walls as a percentage of "
+"the infill line width. A slight overlap allows the walls to connect firmly "
+"to the infill."
msgstr ""
#: fdmprinter.def.json
@@ -1716,9 +1670,9 @@ msgstr ""
msgctxt "skin_overlap description"
msgid ""
"The amount of overlap between the skin and the walls as a percentage of the "
-"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."
+"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 ""
#: fdmprinter.def.json
@@ -1927,18 +1881,6 @@ msgctxt "material description"
msgid "Material"
msgstr ""
-#: fdmprinter.def.json
-msgctxt "material_flow_dependent_temperature label"
-msgid "Auto Temperature"
-msgstr ""
-
-#: fdmprinter.def.json
-msgctxt "material_flow_dependent_temperature description"
-msgid ""
-"Change the temperature for each layer automatically with the average flow "
-"speed of that layer."
-msgstr ""
-
#: fdmprinter.def.json
msgctxt "default_material_print_temperature label"
msgid "Default Printing Temperature"
@@ -1998,18 +1940,6 @@ msgid ""
"of printing."
msgstr ""
-#: fdmprinter.def.json
-msgctxt "material_flow_temp_graph label"
-msgid "Flow Temperature Graph"
-msgstr ""
-
-#: fdmprinter.def.json
-msgctxt "material_flow_temp_graph description"
-msgid ""
-"Data linking material flow (in mm3 per second) to temperature (degrees "
-"Celsius)."
-msgstr ""
-
#: fdmprinter.def.json
msgctxt "material_extrusion_cool_down_speed label"
msgid "Extrusion Cool Down Speed Modifier"
@@ -2030,8 +1960,8 @@ msgstr ""
#: fdmprinter.def.json
msgctxt "material_bed_temperature description"
msgid ""
-"The temperature used for the heated build plate. If this is 0, the bed will "
-"not heat up for this print."
+"The temperature used for the heated build plate. If this is 0, the bed "
+"temperature will not be adjusted."
msgstr ""
#: fdmprinter.def.json
@@ -3962,6 +3892,18 @@ msgid ""
"roofs, a lower value results in flattened tower roofs."
msgstr ""
+#: fdmprinter.def.json
+msgctxt "support_mesh_drop_down label"
+msgid "Drop Down Support Mesh"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "support_mesh_drop_down description"
+msgid ""
+"Make support everywhere below the support mesh, so that there's no overhang "
+"in the support mesh."
+msgstr ""
+
#: fdmprinter.def.json
msgctxt "platform_adhesion label"
msgid "Build Plate Adhesion"
@@ -4699,20 +4641,6 @@ msgid ""
"everything else fails to produce proper GCode."
msgstr ""
-#: fdmprinter.def.json
-msgctxt "meshfix_maximum_resolution label"
-msgid "Maximum Resolution"
-msgstr ""
-
-#: fdmprinter.def.json
-msgctxt "meshfix_maximum_resolution description"
-msgid ""
-"The minimum size of a line segment after slicing. If you increase this, the "
-"mesh will have a lower resolution. This may allow the printer to keep up "
-"with the speed it has to process g-code and will increase slice speed by "
-"removing details of the mesh that it can't process anyway."
-msgstr ""
-
#: fdmprinter.def.json
msgctxt "multiple_mesh_overlap label"
msgid "Merged Meshes Overlap"
@@ -4897,18 +4825,6 @@ msgid ""
"structure."
msgstr ""
-#: fdmprinter.def.json
-msgctxt "support_mesh_drop_down label"
-msgid "Drop Down Support Mesh"
-msgstr ""
-
-#: fdmprinter.def.json
-msgctxt "support_mesh_drop_down description"
-msgid ""
-"Make support everywhere below the support mesh, so that there's no overhang "
-"in the support mesh."
-msgstr ""
-
#: fdmprinter.def.json
msgctxt "anti_overhang_mesh label"
msgid "Anti Overhang Mesh"
@@ -5005,17 +4921,239 @@ msgid "experimental!"
msgstr ""
#: fdmprinter.def.json
-msgctxt "optimize_wall_printing_order label"
-msgid "Optimize Wall Printing Order"
+msgctxt "support_tree_enable label"
+msgid "Tree Support"
msgstr ""
#: fdmprinter.def.json
-msgctxt "optimize_wall_printing_order description"
+msgctxt "support_tree_enable description"
msgid ""
-"Optimize the order in which walls are printed so as to reduce the number of "
-"retractions and the distance travelled. Most parts will benefit from this "
-"being enabled but some may actually take longer so please compare the print "
-"time estimates with and without optimization."
+"Generate a tree-like support with branches that support your print. This may "
+"reduce material usage and print time, but greatly increases slicing time."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "support_tree_angle label"
+msgid "Tree Support Branch Angle"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "support_tree_angle description"
+msgid ""
+"The angle of the branches. Use a lower angle to make them more vertical and "
+"more stable. Use a higher angle to be able to have more reach."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "support_tree_branch_distance label"
+msgid "Tree Support Branch Distance"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "support_tree_branch_distance description"
+msgid ""
+"How far apart the branches need to be when they touch the model. Making this "
+"distance small will cause the tree support to touch the model at more "
+"points, causing better overhang but making support harder to remove."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "support_tree_branch_diameter label"
+msgid "Tree Support Branch Diameter"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "support_tree_branch_diameter description"
+msgid ""
+"The diameter of the thinnest branches of tree support. Thicker branches are "
+"more sturdy. Branches towards the base will be thicker than this."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "support_tree_branch_diameter_angle label"
+msgid "Tree Support Branch Diameter Angle"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "support_tree_branch_diameter_angle description"
+msgid ""
+"The angle of the branches' diameter as they gradually become thicker towards "
+"the bottom. An angle of 0 will cause the branches to have uniform thickness "
+"over their length. A bit of an angle can increase stability of the tree "
+"support."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "support_tree_collision_resolution label"
+msgid "Tree Support Collision Resolution"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "support_tree_collision_resolution description"
+msgid ""
+"Resolution to compute collisions with to avoid hitting the model. Setting "
+"this lower will produce more accurate trees that fail less often, but "
+"increases slicing time dramatically."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "support_tree_wall_thickness label"
+msgid "Tree Support Wall Thickness"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "support_tree_wall_thickness description"
+msgid ""
+"The thickness of the walls of the branches of tree support. Thicker walls "
+"take longer to print but don't fall over as easily."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "support_tree_wall_count label"
+msgid "Tree Support Wall Line Count"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "support_tree_wall_count description"
+msgid ""
+"The number of walls of the branches of tree support. Thicker walls take "
+"longer to print but don't fall over as easily."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "slicing_tolerance label"
+msgid "Slicing Tolerance"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "slicing_tolerance description"
+msgid ""
+"How to slice layers with diagonal surfaces. The areas of a layer can be "
+"generated based on where the middle of the layer intersects the surface "
+"(Middle). Alternatively each layer can have the areas which fall inside of "
+"the volume throughout the height of the layer (Exclusive) or a layer has the "
+"areas which fall inside anywhere within the layer (Inclusive). Exclusive "
+"retains the most details, Inclusive makes for the best fit and Middle takes "
+"the least time to process."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "slicing_tolerance option middle"
+msgid "Middle"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "slicing_tolerance option exclusive"
+msgid "Exclusive"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "slicing_tolerance option inclusive"
+msgid "Inclusive"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "roofing_line_width label"
+msgid "Top Surface Skin Line Width"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "roofing_line_width description"
+msgid "Width of a single line of the areas at the top of the print."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "roofing_pattern label"
+msgid "Top Surface Skin Pattern"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "roofing_pattern description"
+msgid "The pattern of the top most layers."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "roofing_pattern option lines"
+msgid "Lines"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "roofing_pattern option concentric"
+msgid "Concentric"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "roofing_pattern option zigzag"
+msgid "Zig Zag"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "roofing_angles label"
+msgid "Top Surface Skin Line Directions"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "roofing_angles description"
+msgid ""
+"A list of integer line directions to use when the top surface skin layers "
+"use the lines or zig zag pattern. 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 traditional default angles (45 and 135 degrees)."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "infill_enable_travel_optimization label"
+msgid "Infill Travel Optimization"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "infill_enable_travel_optimization description"
+msgid ""
+"When enabled, the order in which the infill lines are printed is optimized "
+"to reduce the distance travelled. The reduction in travel time achieved very "
+"much depends on the model being sliced, infill pattern, density, etc. Note "
+"that, for some models that have many small areas of infill, the time to "
+"slice the model may be greatly increased."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "material_flow_dependent_temperature label"
+msgid "Auto Temperature"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "material_flow_dependent_temperature description"
+msgid ""
+"Change the temperature for each layer automatically with the average flow "
+"speed of that layer."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "material_flow_temp_graph label"
+msgid "Flow Temperature Graph"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "material_flow_temp_graph description"
+msgid ""
+"Data linking material flow (in mm3 per second) to temperature (degrees "
+"Celsius)."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "meshfix_maximum_resolution label"
+msgid "Maximum Resolution"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "meshfix_maximum_resolution description"
+msgid ""
+"The minimum size of a line segment after slicing. If you increase this, the "
+"mesh will have a lower resolution. This may allow the printer to keep up "
+"with the speed it has to process g-code and will increase slice speed by "
+"removing details of the mesh that it can't process anyway."
msgstr ""
#: fdmprinter.def.json
@@ -5745,6 +5883,52 @@ msgid ""
"applies to Wire Printing."
msgstr ""
+#: fdmprinter.def.json
+msgctxt "adaptive_layer_height_enabled label"
+msgid "Use adaptive layers"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "adaptive_layer_height_enabled description"
+msgid ""
+"Adaptive layers computes the layer heights depending on the shape of the "
+"model."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "adaptive_layer_height_variation label"
+msgid "Adaptive layers maximum variation"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "adaptive_layer_height_variation description"
+msgid "The maximum allowed height different from the base layer height in mm."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "adaptive_layer_height_variation_step label"
+msgid "Adaptive layers variation step size"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "adaptive_layer_height_variation_step description"
+msgid ""
+"The difference in height of the next layer height compared to the previous "
+"one."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "adaptive_layer_height_threshold label"
+msgid "Adaptive layers threshold"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "adaptive_layer_height_threshold description"
+msgid ""
+"Threshold whether to use a smaller layer or not. This number is compared to "
+"the tan of the steepest slope in a layer."
+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 461bfd63db..5b16d0b323 100644
--- a/resources/i18n/fi_FI/cura.po
+++ b/resources/i18n/fi_FI/cura.po
@@ -6,8 +6,8 @@
msgid ""
msgstr ""
"Project-Id-Version: Cura 3.0\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2017-11-21 16:58+0100\n"
+"Report-Msgid-Bugs-To: r.dulek@ultimaker.com\n"
+"POT-Creation-Date: 2017-08-02 16:53+0000\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:29
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.py:26
msgctxt "@action"
msgid "Machine Settings"
msgstr "Laitteen asetukset"
@@ -53,12 +53,11 @@ msgstr "Yhteyden muodostaminen Doodle3D Connectiin"
#: /home/ruben/Projects/Cura/plugins/Doodle3D-cura-plugin/Doodle3D/D3DCloudPrintOutputDevicePlugin.py:87
#: /home/ruben/Projects/Cura/plugins/Doodle3D-cura-plugin/Doodle3D/D3DCloudPrintOutputDevicePlugin.py:155
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:874
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:646
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:875
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:659
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/DiscoverUM3Action.qml:370
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/PrintWindow.qml:78
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/ConfigDialog.qml:104
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/ExportSTLUI.qml:99
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:355
#: /home/ruben/Projects/Cura/plugins/ImageReader/ConfigUI.qml:188
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:376
#: /home/ruben/Projects/Cura/plugins/PluginBrowser/PluginBrowser.qml:139
@@ -98,7 +97,7 @@ msgctxt "@info:tooltip"
msgid "Open the Doodle3D Connect web interface"
msgstr "Avaa Doodle3D Connect -verkkoliittymä"
-#: /home/ruben/Projects/Cura/plugins/ChangeLogPlugin/ChangeLog.py:34
+#: /home/ruben/Projects/Cura/plugins/ChangeLogPlugin/ChangeLog.py:33
msgctxt "@item:inmenu"
msgid "Show Changelog"
msgstr "Näytä muutosloki"
@@ -113,78 +112,83 @@ msgctxt "@info:status"
msgid "Profile has been flattened & activated."
msgstr "Profiili on tasoitettu ja aktivoitu."
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:26
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:27
msgctxt "@item:inmenu"
msgid "USB printing"
msgstr "USB-tulostus"
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:27
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:28
msgctxt "@action:button Preceded by 'Ready to'."
msgid "Print via USB"
msgstr "Tulosta USB:n kautta"
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:28
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:29
msgctxt "@info:tooltip"
msgid "Print via USB"
msgstr "Tulosta USB:n kautta"
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:30
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:31
msgctxt "@info:status"
msgid "Connected via USB"
msgstr "Yhdistetty USB:n kautta"
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:154
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:183
msgctxt "@info:status"
msgid "Unable to start a new job because the printer is busy or not connected."
msgstr "Uuden työn aloittaminen ei onnistu, koska tulostin on varattu tai sitä ei ole yhdistetty."
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:154
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:183
msgctxt "@info:title"
msgid "Printer Unavailable"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:457
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:485
msgctxt "@info:status"
msgid "This printer does not support USB printing because it uses UltiGCode flavor."
msgstr "Tämä tulostin ei tue USB-tulostusta, koska se käyttää UltiGCode-tyyppiä."
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:457
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:485
msgctxt "@info:title"
msgid "USB Printing"
msgstr "USB-tulostus"
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:461
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:489
msgctxt "@info:status"
msgid "Unable to start a new job because the printer does not support usb printing."
msgstr "Uuden työn aloittaminen ei onnistu, koska tulostin ei tue USB-tulostusta."
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:461
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDeviceManager.py:108
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:489
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDeviceManager.py:103
#: /home/ruben/Projects/Cura/plugins/RemovableDriveOutputDevice/RemovableDriveOutputDevice.py:146
#: /home/ruben/Projects/Cura/plugins/RemovableDriveOutputDevice/RemovableDriveOutputDevice.py:158
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:945
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1349
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1417
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:946
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1418
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1496
msgctxt "@info:title"
msgid "Warning"
msgstr "Varoitus"
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDeviceManager.py:108
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDeviceManager.py:103
msgctxt "@info"
msgid "Unable to update firmware because there are no printers connected."
msgstr "Laiteohjelmistoa ei voida päivittää, koska yhtään tulostinta ei ole yhdistetty."
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDeviceManager.py:122
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDeviceManager.py:117
#, python-format
msgctxt "@info"
msgid "Could not find firmware required for the printer at %s."
msgstr "Tulostimelle ei löydetty laiteohjelmistoa (%s)."
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDeviceManager.py:122
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDeviceManager.py:117
msgctxt "@info:title"
msgid "Printer Firmware"
msgstr "Tulostimen laiteohjelmisto"
+#: /home/ruben/Projects/Cura/plugins/PrepareStage/__init__.py:12
+msgctxt "@item:inmenu"
+msgid "Prepare"
+msgstr ""
+
#: /home/ruben/Projects/Cura/plugins/RemovableDriveOutputDevice/RemovableDriveOutputDevice.py:23
msgctxt "@action:button Preceded by 'Ready to'."
msgid "Save to Removable Drive"
@@ -228,11 +232,11 @@ msgid "Could not save to removable drive {0}: {1}"
msgstr "Ei voitu tallentaa siirrettävälle asemalle {0}: {1}"
#: /home/ruben/Projects/Cura/plugins/RemovableDriveOutputDevice/RemovableDriveOutputDevice.py:132
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:692
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:700
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:146
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:693
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:701
#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:153
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1358
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:160
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1427
msgctxt "@info:title"
msgid "Error"
msgstr "Virhe"
@@ -282,7 +286,7 @@ msgid "Removable Drive"
msgstr "Siirrettävä asema"
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:109
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:53
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:51
msgctxt "@action:button Preceded by 'Ready to'."
msgid "Print over network"
msgstr "Tulosta verkon kautta"
@@ -396,110 +400,110 @@ msgctxt "@info:title"
msgid "Printer Status"
msgstr "Tulostimen tila"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:691
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:692
#, python-brace-format
msgctxt "@info:status"
msgid "Unable to start a new print job. No Printcore loaded in slot {0}"
msgstr "Uuden tulostustyön aloittaminen ei onnistu. PrintCorea ei ole ladattu aukkoon {0}"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:699
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:700
#, python-brace-format
msgctxt "@info:status"
msgid "Unable to start a new print job. No material loaded in slot {0}"
msgstr "Uuden tulostustyön aloittaminen ei onnistu. Materiaalia ei ole ladattu aukkoon {0}"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:709
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:710
#, python-brace-format
msgctxt "@label"
msgid "Not enough material for spool {0}."
msgstr "Kelalle {0} ei ole tarpeeksi materiaalia."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:719
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:720
#, python-brace-format
msgctxt "@label"
msgid "Different PrintCore (Cura: {0}, Printer: {1}) selected for extruder {2}"
msgstr "Eri PrintCore (Cura: {0}, tulostin: {1}) valittu suulakkeelle {2}"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:733
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:734
#, python-brace-format
msgctxt "@label"
msgid "Different material (Cura: {0}, Printer: {1}) selected for extruder {2}"
msgstr "Eri materiaali (Cura: {0}, tulostin: {1}) valittu suulakkeelle {2}"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:741
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:742
#, python-brace-format
msgctxt "@label"
msgid "PrintCore {0} is not properly calibrated. XY calibration needs to be performed on the printer."
msgstr "Print Core -tulostusydintä {0} ei ole kalibroitu oikein. Tulostimen XY-kalibrointi tulee suorittaa."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:746
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:747
msgctxt "@label"
msgid "Are you sure you wish to print with the selected configuration?"
msgstr "Haluatko varmasti tulostaa valitulla määrityksellä?"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:747
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:748
msgctxt "@label"
msgid "There is a mismatch between the configuration or calibration of the printer and Cura. For the best result, always slice for the PrintCores and materials that are inserted in your printer."
msgstr "Tulostimen ja Curan määrityksen tai kalibroinnin välillä on ristiriita. Parhaat tulokset saavutetaan viipaloimalla aina tulostimeen asetetuille PrintCoreille ja materiaaleille."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:753
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:754
msgctxt "@window:title"
msgid "Mismatched configuration"
msgstr "Ristiriitainen määritys"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:864
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:262
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:865
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:258
msgctxt "@info:status"
msgid "Sending new jobs (temporarily) blocked, still sending the previous print job."
msgstr "Uusien töiden lähettäminen (tilapäisesti) estetty, edellistä tulostustyötä lähetetään vielä."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:873
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:874
msgctxt "@info:status"
msgid "Sending data to printer"
msgstr "Lähetetään tietoja tulostimeen"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:873
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:874
msgctxt "@info:title"
msgid "Sending Data"
msgstr "Lähetetään tietoja"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:944
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:945
msgctxt "@info:status"
msgid "Unable to send data to printer. Is another job still active?"
msgstr "Tietojen lähetys tulostimeen ei onnistu. Onko toinen työ yhä aktiivinen?"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:1085
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:1087
#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:196
msgctxt "@label:MonitorStatus"
msgid "Aborting print..."
msgstr "Keskeytetään tulostus..."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:1091
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:1093
msgctxt "@label:MonitorStatus"
msgid "Print aborted. Please check the printer"
msgstr "Tulostus keskeytetty. Tarkista tulostin"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:1097
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:1099
msgctxt "@label:MonitorStatus"
msgid "Pausing print..."
msgstr "Tulostus pysäytetään..."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:1099
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:1101
msgctxt "@label:MonitorStatus"
msgid "Resuming print..."
msgstr "Tulostusta jatketaan..."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:1289
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:1291
msgctxt "@window:title"
msgid "Sync with your printer"
msgstr "Synkronoi tulostimen kanssa"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:1291
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:1293
msgctxt "@label"
msgid "Would you like to use your current printer configuration in Cura?"
msgstr "Haluatko käyttää nykyistä tulostimen määritystä Curassa?"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:1293
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:1295
msgctxt "@label"
msgid "The PrintCores and/or materials on your printer differ from those within your current project. For the best result, always slice for the PrintCores and materials that are inserted in your printer."
msgstr "Tulostimen PrintCoret tai materiaalit eivät vastaa tulostettavan projektin asetuksia. Parhaat tulokset saavutetaan viipaloimalla aina tulostimeen asetetuille PrintCoreille ja materiaaleille."
@@ -520,145 +524,188 @@ msgid "{printer_name} has finished printing '{job_name}'. Please collect the pri
msgstr "{printer_name} on tulostanut työn '{job_name}'. Nouda työ ja vahvista alustan tyhjennys."
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:115
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:520
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:533
#, python-brace-format
msgid "{printer_name} is reserved to print '{job_name}'. Please change the printer's configuration to match the job, for it to start printing."
msgstr "{printer_name} on varattu työn {job_name} tulostamiseen. Muuta tulostimen määritys vastaamaan työtä, jotta tulostus alkaa."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:278
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:277
msgctxt "@info:status"
msgid "Unable to send new print job: this 3D printer is not (yet) set up to host a group of connected Ultimaker 3 printers."
msgstr "Uuden tulostustyön lähetys ei onnistu: tätä 3D-tulostinta ei ole (vielä) määritetty yhdistetyn Ultimaker 3 -tulostinryhmän isännäksi."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:410
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:423
#, python-brace-format
msgctxt "@info:status"
msgid "Unable to send print job to group {cluster_name}."
msgstr "Tulostustyön lähetys ryhmään {cluster_name} ei onnistu."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:418
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:431
#, python-brace-format
msgctxt "@info:status"
msgid "Sent {file_name} to group {cluster_name}."
msgstr "Lähetettiin {file_name} ryhmään {cluster_name}."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:423
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:436
msgctxt "@action:button"
msgid "Show print jobs"
msgstr "Näytä tulostustyöt"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:424
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:437
msgctxt "@info:tooltip"
msgid "Opens the print jobs interface in your browser."
msgstr "Avaa tulostustöiden käyttöliittymän selaimessa."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:489
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:502
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/DiscoverUM3Action.qml:239
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/PrinterInfoBlock.qml:47
-msgctxt "@label"
+msgctxt "@label Printer name"
msgid "Unknown"
-msgstr "Tuntematon"
+msgstr ""
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:492
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:505
#, python-brace-format
msgctxt "@info:status"
msgid "Printer '{printer_name}' has finished printing '{job_name}'."
msgstr "{printer_name} on tulostanut työn '{job_name}'."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:494
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:497
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:507
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:510
msgctxt "@info:status"
msgid "Print finished"
msgstr "Tulosta valmis"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:522
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:525
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:535
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:538
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/PrinterInfoBlock.qml:282
msgctxt "@label:status"
msgid "Action required"
msgstr "Vaatii toimenpiteitä"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:643
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:656
#, python-brace-format
msgctxt "@info:progress"
msgid "Sending {file_name} to group {cluster_name}"
msgstr "Lähetetään tiedostoa {file_name} ryhmään {cluster_name}"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/DiscoverUM3Action.py:19
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/DiscoverUM3Action.py:17
msgctxt "@action"
msgid "Connect via Network"
msgstr "Yhdistä verkon kautta"
-#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py:64
+#: /home/ruben/Projects/Cura/plugins/MonitorStage/__init__.py:12
+msgctxt "@item:inmenu"
+msgid "Monitor"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py:66
#, 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 ""
-#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py:65
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py:67
#, python-format
msgctxt "@info:title The %s gets replaced with the printer name."
msgid "New %s firmware available"
msgstr "Uusi tulostimen %s laiteohjelmisto saatavilla"
-#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py:66
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py:68
msgctxt "@action:button"
msgid "How to update"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py:77
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py:79
msgctxt "@info"
msgid "Could not access update information."
msgstr "Päivitystietoja ei löytynyt."
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksReader.py:199
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksReader.py:579
msgctxt "@info:status"
-msgid "Errors appeared while opening your SolidWorks file! Please check, whether it is possible to open your file in SolidWorks itself without any problems as well!"
-msgstr "SolidWorks-tiedostoa avattaessa ilmeni virheitä! Tarkista, voiko tiedoston avata SolidWorks-ohjelmistossa ilman ongelmia."
+msgid "SolidWorks reported errors, while opening your file. We recommend to solve these issues inside SolidWorks itself."
+msgstr ""
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/__init__.py:31
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksReader.py:591
+msgctxt "@info:status"
+msgid ""
+"Found no models inside your drawing. Could you please check it's content again and make sure one part or assembly is inside?\n"
+"\n"
+" Thanks!."
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksReader.py:595
+msgctxt "@info:status"
+msgid ""
+"Found more then one part or assembly inside your drawing. We currently only support drawings with exactly one part or assembly inside.\n"
+"\n"
+"Sorry!"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/__init__.py:25
msgctxt "@item:inlistbox"
msgid "SolidWorks part file"
msgstr "SolidWorks-osatiedosto"
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/__init__.py:35
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/__init__.py:29
msgctxt "@item:inlistbox"
msgid "SolidWorks assembly file"
msgstr "SolidWorks-kokoonpanotiedosto"
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/ConfigDialog.py:21
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/__init__.py:33
+msgctxt "@item:inlistbox"
+msgid "SolidWorks drawing file"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/__init__.py:48
+msgctxt "@info:status"
+msgid ""
+"Dear customer,\n"
+"We could not find a valid installation of SolidWorks on your system. That means that either SolidWorks is not installed or you don't own an valid license. Please make sure that running SolidWorks itself works without issues and/or contact your ICT.\n"
+"\n"
+"With kind regards\n"
+" - Thomas Karl Pietrowski"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/__init__.py:57
+msgctxt "@info:status"
+msgid ""
+"Dear customer,\n"
+"You are currently running this plugin on an operating system other than Windows. This plugin will only work on Windows with SolidWorks installed, including an valid license. Please install this plugin on a Windows machine with SolidWorks installed.\n"
+"\n"
+"With kind regards\n"
+" - Thomas Karl Pietrowski"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksDialogHandler.py:70
msgid "Configure"
msgstr "Määritä"
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/CommonComReader.py:135
-#, python-format
-msgctxt "@info:status"
-msgid "Error while starting %s!"
-msgstr "%s:n käynnistyksen aikana ilmeni virhe!"
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksDialogHandler.py:71
+msgid "Installation guide for SolidWorks macro"
+msgstr ""
#: /home/ruben/Projects/Cura/plugins/SimulationView/__init__.py:14
msgctxt "@item:inlistbox"
-msgid "Simulation view"
-msgstr ""
+msgid "Layer view"
+msgstr "Kerrosnäkymä"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.py:100
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.py:103
msgctxt "@info:status"
msgid "Cura does not accurately display layers when Wire Printing is enabled"
msgstr "Cura ei näytä kerroksia täsmällisesti, kun rautalankatulostus on käytössä"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.py:101
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.py:104
msgctxt "@info:title"
msgid "Simulation View"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.py:26
+#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.py:25
msgid "Modify G-Code"
msgstr "Muokkaa GCode-arvoa"
#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/SliceInfo.py:43
msgctxt "@info"
-msgid "Cura collects anonymised slicing statistics. You can disable this in the preferences."
-msgstr "Cura kerää anonyymejä viipalointiin liittyviä tilastotietoja. Tämän voi poistaa käytöstä asetuksien kautta."
+msgid "Cura collects anonymized usage statistics."
+msgstr ""
#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/SliceInfo.py:46
msgctxt "@info:title"
@@ -667,14 +714,41 @@ msgstr "Kerätään tietoja"
#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/SliceInfo.py:48
msgctxt "@action:button"
-msgid "Dismiss"
-msgstr "Ohita"
+msgid "Allow"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/SliceInfo.py:49
+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/SliceInfoPlugin/SliceInfo.py:50
+msgctxt "@action:button"
+msgid "Disable"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/SliceInfo.py:51
+msgctxt "@action:tooltip"
+msgid "Don't allow Cura to send anonymized usage statistics. You can enable it again in the preferences."
+msgstr ""
#: /home/ruben/Projects/Cura/plugins/LegacyProfileReader/__init__.py:14
msgctxt "@item:inlistbox"
msgid "Cura 15.04 profiles"
msgstr "Cura 15.04 -profiilit"
+#: /home/ruben/Projects/Cura/plugins/CuraBlenderPlugin/__init__.py:15
+msgctxt "@item:inlistbox"
+msgid "Blender file"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/CuraBlenderPlugin/CadIntegrationUtils/CommonReader.py:199
+msgctxt "@info:status"
+msgid ""
+"Could not export using \"{}\" quality!\n"
+"Felt back to \"{}\"."
+msgstr ""
+
#: /home/ruben/Projects/Cura/plugins/GCodeProfileReader/__init__.py:14
#: /home/ruben/Projects/Cura/plugins/GCodeReader/__init__.py:14
msgctxt "@item:inlistbox"
@@ -706,49 +780,49 @@ msgctxt "@item:inlistbox"
msgid "GIF Image"
msgstr "GIF-kuva"
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:269
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:299
msgctxt "@info:status"
msgid "Unable to slice with the current material as it is incompatible with the selected machine or configuration."
msgstr "Viipalointi ei onnistu nykyisellä materiaalilla, sillä se ei sovellu käytettäväksi valitun laitteen tai kokoonpanon kanssa."
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:269
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:297
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:319
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:299
#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:327
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:336
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:349
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:357
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:366
msgctxt "@info:title"
msgid "Unable to slice"
msgstr "Viipalointi ei onnistu"
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:296
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:326
#, python-brace-format
msgctxt "@info:status"
msgid "Unable to slice with the current settings. The following settings have errors: {0}"
msgstr "Viipalointi ei onnistu nykyisten asetuksien ollessa voimassa. Seuraavissa asetuksissa on virheitä: {0}"
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:318
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:348
#, python-brace-format
msgctxt "@info:status"
msgid "Unable to slice due to some per-model settings. The following settings have errors on one or more models: {error_labels}"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:326
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:356
msgctxt "@info:status"
msgid "Unable to slice because the prime tower or prime position(s) are invalid."
msgstr "Viipalointi ei onnistu, koska esitäyttötorni tai esitäytön sijainti tai sijainnit eivät kelpaa."
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:335
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:365
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."
#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py:50
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py:239
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py:242
msgctxt "@info:status"
msgid "Processing Layers"
msgstr "Käsitellään kerroksia"
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py:239
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py:242
msgctxt "@info:title"
msgid "Information"
msgstr "Tiedot"
@@ -785,14 +859,14 @@ msgstr ""
msgid "Failed to install Siemens NX plugin. Could not set environment variable UGII_USER_DIR for Siemens NX."
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.py:167
-#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:585
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.py:165
+#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:590
msgctxt "@title:tab"
msgid "Recommended"
msgstr "Suositeltu"
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.py:169
-#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:590
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.py:167
+#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:595
msgctxt "@title:tab"
msgid "Custom"
msgstr "Mukautettu"
@@ -803,24 +877,24 @@ msgctxt "@item:inlistbox"
msgid "3MF File"
msgstr "3MF-tiedosto"
-#: /home/ruben/Projects/Cura/plugins/3MFReader/ThreeMFWorkspaceReader.py:126
-#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:1142
+#: /home/ruben/Projects/Cura/plugins/3MFReader/ThreeMFWorkspaceReader.py:159
+#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:1185
msgctxt "@label"
msgid "Nozzle"
msgstr "Suutin"
-#: /home/ruben/Projects/Cura/plugins/PluginBrowser/PluginBrowser.py:164
+#: /home/ruben/Projects/Cura/plugins/PluginBrowser/PluginBrowser.py:152
#, python-brace-format
msgctxt "@info:status"
msgid "Failed to get plugin ID from {0}"
msgstr "Lisäosan tunnuksen hankkiminen epäonnistui tiedostosta {0}"
-#: /home/ruben/Projects/Cura/plugins/PluginBrowser/PluginBrowser.py:165
+#: /home/ruben/Projects/Cura/plugins/PluginBrowser/PluginBrowser.py:153
msgctxt "@info:tile"
msgid "Warning"
msgstr "Varoitus"
-#: /home/ruben/Projects/Cura/plugins/PluginBrowser/PluginBrowser.py:203
+#: /home/ruben/Projects/Cura/plugins/PluginBrowser/PluginBrowser.py:191
msgctxt "@window:title"
msgid "Plugin browser"
msgstr "Lisäosien selain"
@@ -835,18 +909,18 @@ msgctxt "@item:inlistbox"
msgid "G File"
msgstr "G File -tiedosto"
-#: /home/ruben/Projects/Cura/plugins/GCodeReader/GCodeReader.py:314
+#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:321
msgctxt "@info:status"
msgid "Parsing G-code"
msgstr "G-coden jäsennys"
-#: /home/ruben/Projects/Cura/plugins/GCodeReader/GCodeReader.py:316
-#: /home/ruben/Projects/Cura/plugins/GCodeReader/GCodeReader.py:426
+#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:323
+#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:464
msgctxt "@info:title"
msgid "G-code Details"
msgstr "G-coden tiedot"
-#: /home/ruben/Projects/Cura/plugins/GCodeReader/GCodeReader.py:424
+#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:462
msgctxt "@info:generic"
msgid "Make sure the g-code is suitable for your printer and printer configuration before sending the file to it. The g-code representation may not be accurate."
msgstr "Varmista, että G-code on tulostimelle ja sen tulostusasetuksille soveltuva, ennen kuin lähetät tiedoston siihen. G-coden esitys ei välttämättä ole tarkka."
@@ -857,6 +931,16 @@ msgctxt "@item:inlistbox"
msgid "Cura Profile"
msgstr "Cura-profiili"
+#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/__init__.py:12
+msgctxt "@item:inmenu"
+msgid "Profile Assistant"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/__init__.py:17
+msgctxt "@item:inlistbox"
+msgid "Profile Assistant"
+msgstr ""
+
#: /home/ruben/Projects/Cura/plugins/3MFWriter/__init__.py:30
msgctxt "@item:inlistbox"
msgid "3MF file"
@@ -888,142 +972,116 @@ msgctxt "@action"
msgid "Level build plate"
msgstr "Tasaa alusta"
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:89
+#: /home/ruben/Projects/Cura/cura/PrintInformation.py:98
msgctxt "@tooltip"
msgid "Outer Wall"
msgstr "Ulkoseinämä"
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:90
+#: /home/ruben/Projects/Cura/cura/PrintInformation.py:99
msgctxt "@tooltip"
msgid "Inner Walls"
msgstr "Sisäseinämät"
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:91
+#: /home/ruben/Projects/Cura/cura/PrintInformation.py:100
msgctxt "@tooltip"
msgid "Skin"
msgstr "Pintakalvo"
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:92
+#: /home/ruben/Projects/Cura/cura/PrintInformation.py:101
msgctxt "@tooltip"
msgid "Infill"
msgstr "Täyttö"
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:93
+#: /home/ruben/Projects/Cura/cura/PrintInformation.py:102
msgctxt "@tooltip"
msgid "Support Infill"
msgstr "Tuen täyttö"
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:94
+#: /home/ruben/Projects/Cura/cura/PrintInformation.py:103
msgctxt "@tooltip"
msgid "Support Interface"
msgstr "Tukiliittymä"
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:95
+#: /home/ruben/Projects/Cura/cura/PrintInformation.py:104
msgctxt "@tooltip"
msgid "Support"
msgstr "Tuki"
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:96
+#: /home/ruben/Projects/Cura/cura/PrintInformation.py:105
msgctxt "@tooltip"
msgid "Skirt"
msgstr "Helma"
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:97
+#: /home/ruben/Projects/Cura/cura/PrintInformation.py:106
msgctxt "@tooltip"
msgid "Travel"
msgstr "Siirtoliike"
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:98
+#: /home/ruben/Projects/Cura/cura/PrintInformation.py:107
msgctxt "@tooltip"
msgid "Retractions"
msgstr "Takaisinvedot"
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:99
+#: /home/ruben/Projects/Cura/cura/PrintInformation.py:108
msgctxt "@tooltip"
msgid "Other"
msgstr "Muu"
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:199
+#: /home/ruben/Projects/Cura/cura/PrintInformation.py:231
msgctxt "@label unknown material"
msgid "Unknown"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:284
+#: /home/ruben/Projects/Cura/cura/PrintInformation.py:318
#, python-brace-format
msgctxt "@label"
msgid "Pre-sliced file {0}"
msgstr "Esiviipaloitu tiedosto {0}"
-#: /home/ruben/Projects/Cura/cura/PrinterOutputDevice.py:469
+#: /home/ruben/Projects/Cura/cura/PrinterOutputDevice.py:440
msgctxt "@item:material"
msgid "No material loaded"
msgstr "Ei ladattua materiaalia"
-#: /home/ruben/Projects/Cura/cura/PrinterOutputDevice.py:476
+#: /home/ruben/Projects/Cura/cura/PrinterOutputDevice.py:447
msgctxt "@item:material"
msgid "Unknown material"
msgstr "Tuntematon materiaali"
-#: /home/ruben/Projects/Cura/cura/ArrangeObjectsJob.py:30
-msgctxt "@info:status"
-msgid "Finding new location for objects"
-msgstr "Uusien paikkojen etsiminen kappaleille"
-
-#: /home/ruben/Projects/Cura/cura/ArrangeObjectsJob.py:34
-msgctxt "@info:title"
-msgid "Finding Location"
-msgstr "Etsitään paikkaa"
-
-#: /home/ruben/Projects/Cura/cura/ArrangeObjectsJob.py:89
-#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:83
-msgctxt "@info:status"
-msgid "Unable to find a location within the build volume for all objects"
-msgstr "Kaikille kappaleille ei löydy paikkaa tulostustilavuudessa."
-
-#: /home/ruben/Projects/Cura/cura/ArrangeObjectsJob.py:90
-msgctxt "@info:title"
-msgid "Can't Find Location"
-msgstr "Paikkaa ei löydy"
-
-#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:431
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:113
+#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:437
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:120
msgctxt "@title:window"
msgid "File Already Exists"
msgstr "Tiedosto on jo olemassa"
-#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:432
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:114
+#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:438
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:121
#, python-brace-format
msgctxt "@label Don't translate the XML tag !"
msgid "The file {0} already exists. Are you sure you want to overwrite it?"
msgstr "Tiedosto {0} on jo olemassa. Haluatko varmasti kirjoittaa sen päälle?"
-#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:815
+#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:872
msgctxt "@label"
msgid "Custom"
msgstr "Mukautettu"
-#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:819
+#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:876
msgctxt "@label"
msgid "Custom Material"
msgstr "Mukautettu materiaali"
-#: /home/ruben/Projects/Cura/cura/Settings/ExtrudersModel.py:182
-msgctxt "@menuitem"
-msgid "Global"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/cura/Settings/ExtrudersModel.py:229
+#: /home/ruben/Projects/Cura/cura/Settings/ExtrudersModel.py:205
msgctxt "@menuitem"
msgid "Not overridden"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:117
+#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:124
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."
-#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:118
+#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:125
#: /home/ruben/Projects/Cura/cura/Settings/MaterialManager.py:24
msgctxt "@info:title"
msgid "Incompatible Material"
@@ -1044,67 +1102,89 @@ msgctxt "@action"
msgid "Undo changing the material diameter."
msgstr "Kumoa materiaalin halkaisijan muutokset."
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:144
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:151
#, python-brace-format
msgctxt "@info:status Don't translate the XML tags or !"
msgid "Failed to export profile to {0}: {1}"
msgstr "Profiilin vienti epäonnistui tiedostoon {0}: {1}"
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:151
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:158
#, python-brace-format
msgctxt "@info:status Don't translate the XML tag !"
msgid "Failed to export profile to {0}: Writer plugin reported failure."
msgstr "Profiilin vienti epäonnistui tiedostoon {0}: Kirjoitin-lisäosa ilmoitti virheestä."
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:156
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:163
#, python-brace-format
msgctxt "@info:status Don't translate the XML tag !"
msgid "Exported profile to {0}"
msgstr "Profiili viety tiedostoon {0}"
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:157
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:164
msgctxt "@info:title"
msgid "Export succeeded"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:183
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:205
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:214
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:248
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:190
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:211
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:271
#, python-brace-format
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}"
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:216
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:252
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:230
+#, python-brace-format
+msgctxt "@info:status Don't translate the XML tags or !"
+msgid "This profile {0} contains incorrect data, could not import it."
+msgstr ""
+
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:240
+#, python-brace-format
+msgctxt "@info:status Don't translate the XML tags or !"
+msgid "The machine defined in profile {0} doesn't match with your current machine, could not import it."
+msgstr ""
+
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:274
#, python-brace-format
msgctxt "@info:status"
msgid "Successfully imported profile {0}"
msgstr "Onnistuneesti tuotu profiili {0}"
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:255
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:277
+#, python-brace-format
+msgctxt "@info:status"
+msgid "File {0} does not contain any valid profile."
+msgstr ""
+
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:280
#, python-brace-format
msgctxt "@info:status"
msgid "Profile {0} has an unknown file type or is corrupted."
msgstr "Profiililla {0} on tuntematon tiedostotyyppi tai se on vioittunut."
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:274
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:298
msgctxt "@label"
msgid "Custom profile"
msgstr "Mukautettu profiili"
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:285
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:313
msgctxt "@info:status"
msgid "Profile is missing a quality type."
msgstr "Profiilista puuttuu laatutyyppi."
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:321
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:349
#, python-brace-format
msgctxt "@info:status"
msgid "Could not find a quality type {0} for the current configuration."
msgstr "Laatutyyppiä {0} ei löydy nykyiselle kokoonpanolle."
+#: /home/ruben/Projects/Cura/cura/ObjectsModel.py:46
+#, python-brace-format
+msgctxt "@label"
+msgid "Group #{group_nr}"
+msgstr ""
+
#: /home/ruben/Projects/Cura/cura/BuildVolume.py:100
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."
@@ -1115,142 +1195,167 @@ msgctxt "@info:title"
msgid "Build Volume"
msgstr "Tulostustilavuus"
-#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:34
+#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:25
msgctxt "@info:status"
msgid "Multiplying and placing objects"
msgstr "Kappaleiden kertominen ja sijoittelu"
-#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:35
-#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:83
+#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:26
+#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:78
msgctxt "@info:title"
msgid "Placing Object"
msgstr "Sijoitetaan kappaletta"
-#: /home/ruben/Projects/Cura/cura/CrashHandler.py:80
+#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:78
+#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsJob.py:88
+#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsAllBuildPlatesJob.py:152
+msgctxt "@info:status"
+msgid "Unable to find a location within the build volume for all objects"
+msgstr "Kaikille kappaleille ei löydy paikkaa tulostustilavuudessa."
+
+#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsJob.py:29
+#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsAllBuildPlatesJob.py:64
+msgctxt "@info:status"
+msgid "Finding new location for objects"
+msgstr "Uusien paikkojen etsiminen kappaleille"
+
+#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsJob.py:33
+#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsAllBuildPlatesJob.py:68
+msgctxt "@info:title"
+msgid "Finding Location"
+msgstr "Etsitään paikkaa"
+
+#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsJob.py:89
+#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsAllBuildPlatesJob.py:153
+msgctxt "@info:title"
+msgid "Can't Find Location"
+msgstr "Paikkaa ei löydy"
+
+#: /home/ruben/Projects/Cura/cura/CrashHandler.py:81
msgctxt "@title:window"
msgid "Crash Report"
msgstr "Kaatumisraportti"
-#: /home/ruben/Projects/Cura/cura/CrashHandler.py:93
+#: /home/ruben/Projects/Cura/cura/CrashHandler.py:94
msgctxt "@label crash message"
msgid ""
-"
A fatal exception has occurred. Please send us this Crash Report to fix the problem
\n"
+"
A fatal error has occurred. Please send us this Crash Report to fix the problem
\n"
"
Please use the \"Send report\" button to post a bug report automatically to our servers
"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/CrashHandler.py:141
+#: /home/ruben/Projects/Cura/cura/CrashHandler.py:147
msgctxt "@title:groupbox"
-msgid "Exception traceback"
+msgid "Error traceback"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/CrashHandler.py:208
+#: /home/ruben/Projects/Cura/cura/CrashHandler.py:214
msgctxt "@title:groupbox"
msgid "Logs"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/CrashHandler.py:231
+#: /home/ruben/Projects/Cura/cura/CrashHandler.py:237
msgctxt "@title:groupbox"
msgid "User description"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/CrashHandler.py:246
+#: /home/ruben/Projects/Cura/cura/CrashHandler.py:252
msgctxt "@action:button"
msgid "Send report"
msgstr ""
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:256
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:274
msgctxt "@info:progress"
msgid "Loading machines..."
msgstr "Ladataan laitteita..."
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:661
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:660
msgctxt "@info:progress"
msgid "Setting up scene..."
msgstr "Asetetaan näkymää..."
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:703
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:702
msgctxt "@info:progress"
msgid "Loading interface..."
msgstr "Ladataan käyttöliittymää..."
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:874
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:899
#, 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:1348
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1417
#, 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:1357
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1426
#, 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:1416
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1495
msgctxt "@info:status"
msgid "The selected model was too small to load."
msgstr ""
@@ -1279,12 +1384,11 @@ msgstr "X (leveys)"
#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:119
#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:129
#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:235
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:288
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:300
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:391
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:401
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:413
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:840
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:383
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:394
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:412
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:424
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:849
msgctxt "@label"
msgid "mm"
msgstr "mm"
@@ -1374,68 +1478,67 @@ 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:255
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:254
msgctxt "@label"
msgid "Number of Extruders"
msgstr "Suulakkeiden määrä"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:289
-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:291
-msgctxt "@label"
-msgid "Material diameter"
-msgstr "Materiaalin halkaisija"
-
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:299
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:390
-msgctxt "@label"
-msgid "Nozzle size"
-msgstr "Suuttimen koko"
-
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:317
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:310
msgctxt "@label"
msgid "Start Gcode"
msgstr "Aloita GCode"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:327
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:320
msgctxt "@tooltip"
msgid "Gcode commands to be executed at the very start."
msgstr "GCode-komennot, jotka suoritetaan aivan alussa."
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:336
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:329
msgctxt "@label"
msgid "End Gcode"
msgstr "Lopeta GCode"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:346
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:339
msgctxt "@tooltip"
msgid "Gcode commands to be executed at the very end."
msgstr "GCode-komennot, jotka suoritetaan aivan lopussa."
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:378
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:370
msgctxt "@label"
msgid "Nozzle Settings"
msgstr "Suutinasetukset"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:400
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:382
+msgctxt "@label"
+msgid "Nozzle size"
+msgstr "Suuttimen koko"
+
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:393
+msgctxt "@label"
+msgid "Compatible material diameter"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:395
+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:411
msgctxt "@label"
msgid "Nozzle offset X"
msgstr "Suuttimen X-siirtymä"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:412
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:423
msgctxt "@label"
msgid "Nozzle offset Y"
msgstr "Suuttimen Y-siirtymä"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:433
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:444
msgctxt "@label"
msgid "Extruder Start Gcode"
msgstr "Suulake – aloita Gcode"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:451
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:462
msgctxt "@label"
msgid "Extruder End Gcode"
msgstr "Suulake – lopeta Gcode"
@@ -1448,8 +1551,9 @@ msgstr "Muutosloki"
#: /home/ruben/Projects/Cura/plugins/ChangeLogPlugin/ChangeLog.qml:37
#: /home/ruben/Projects/Cura/plugins/USBPrinting/FirmwareUpdateWindow.qml:107
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/UM3InfoComponents.qml:55
-#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.qml:445
-#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:357
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksMacroTutorial.qml:306
+#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.qml:456
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:492
#: /home/ruben/Projects/Cura/plugins/PluginBrowser/PluginBrowser.qml:80
#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:123
#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:147
@@ -1533,7 +1637,7 @@ msgstr "Muokkaa"
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/DiscoverUM3Action.qml:96
#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:50
#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:95
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:190
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:171
msgctxt "@action:button"
msgid "Remove"
msgstr "Poista"
@@ -1555,14 +1659,14 @@ msgid "Type"
msgstr "Tyyppi"
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/DiscoverUM3Action.qml:233
-msgctxt "@label"
+msgctxt "@label Printer name"
msgid "Ultimaker 3"
-msgstr "Ultimaker 3"
+msgstr ""
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/DiscoverUM3Action.qml:236
-msgctxt "@label"
+msgctxt "@label Printer name"
msgid "Ultimaker 3 Extended"
-msgstr "Ultimaker 3 Extended"
+msgstr ""
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/DiscoverUM3Action.qml:252
msgctxt "@label"
@@ -1606,8 +1710,6 @@ msgid "Enter the IP address or hostname of your printer on the network."
msgstr "Anna verkon tulostimen IP-osoite tai isäntänimi."
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/DiscoverUM3Action.qml:379
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/ConfigDialog.qml:92
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/ExportSTLUI.qml:88
#: /home/ruben/Projects/Cura/plugins/ImageReader/ConfigUI.qml:181
msgctxt "@action:button"
msgid "OK"
@@ -1628,6 +1730,11 @@ msgctxt "@label: arg 1 is group name"
msgid "%1 is not set up to host a group of connected Ultimaker 3 printers"
msgstr "%1 ei ole määritetty yhdistetyn Ultimaker 3 -tulostinryhmän isännäksi"
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/ClusterMonitorItem.qml:55
+msgctxt "@label link to connect manager"
+msgid "Add/Remove printers"
+msgstr ""
+
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/OpenPanelButton.qml:14
msgctxt "@info:tooltip"
msgid "Opens the print jobs page with your default web browser."
@@ -1658,11 +1765,16 @@ msgid "Available"
msgstr "Saatavilla"
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/PrinterInfoBlock.qml:43
-#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:101
+#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:100
msgctxt "@label:MonitorStatus"
msgid "Lost connection with the printer"
msgstr "Yhteys tulostimeen menetetty"
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/PrinterInfoBlock.qml:47
+msgctxt "@label Printer status"
+msgid "Unknown"
+msgstr ""
+
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/PrinterInfoBlock.qml:257
msgctxt "@label:status"
msgid "Disabled"
@@ -1754,138 +1866,250 @@ msgctxt "@action:button"
msgid "Activate Configuration"
msgstr "Aktivoi määritys"
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/ConfigDialog.qml:20
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksWizard.qml:21
msgctxt "@title:window"
-msgid "Cura SolidWorks Plugin Configuration"
-msgstr "Cura SolidWorks -laajennuksen määritys"
+msgid "SolidWorks: Export wizard"
+msgstr ""
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/ConfigDialog.qml:44
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksWizard.qml:45
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:140
msgctxt "@action:label"
-msgid "Default quality of the exported STL:"
-msgstr "Viedyn STL:n oletuslaatu:"
+msgid "Quality:"
+msgstr ""
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/ConfigDialog.qml:79
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksWizard.qml:78
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:179
msgctxt "@option:curaSolidworksStlQuality"
-msgid "Always ask"
-msgstr "Kysy aina"
+msgid "Fine (3D-printing)"
+msgstr ""
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/ConfigDialog.qml:80
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksWizard.qml:79
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:180
msgctxt "@option:curaSolidworksStlQuality"
-msgid "Always use Fine quality"
-msgstr "Käytä aina hienoa laatua"
+msgid "Coarse (3D-printing)"
+msgstr ""
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/ConfigDialog.qml:81
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksWizard.qml:80
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:181
msgctxt "@option:curaSolidworksStlQuality"
-msgid "Always use Coarse quality"
-msgstr "Käytä aina karkeaa laatua"
+msgid "Fine (SolidWorks)"
+msgstr ""
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/ExportSTLUI.qml:20
-msgctxt "@title:window"
-msgid "Import SolidWorks File as STL..."
-msgstr "Tuo SolidWorks-tiedosto STL-muodossa..."
-
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/ExportSTLUI.qml:43
-msgctxt "@info:tooltip"
-msgid "Quality of the Exported STL"
-msgstr "Viedyn STL:n laatu"
-
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/ExportSTLUI.qml:48
-msgctxt "@action:label"
-msgid "Quality"
-msgstr "Laatu"
-
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/ExportSTLUI.qml:62
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksWizard.qml:81
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:182
msgctxt "@option:curaSolidworksStlQuality"
-msgid "Coarse"
-msgstr "Karkea"
+msgid "Coarse (SolidWorks)"
+msgstr ""
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/ExportSTLUI.qml:63
-msgctxt "@option:curaSolidworksStlQuality"
-msgid "Fine"
-msgstr "Hieno"
-
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/ExportSTLUI.qml:78
-#: /home/ruben/Projects/Cura/resources/qml/AskOpenAsProjectOrModelsDialog.qml:82
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksWizard.qml:94
msgctxt "@text:window"
-msgid "Remember my choice"
-msgstr "Muista valintani"
+msgid "Show this dialog again"
+msgstr ""
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:81
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksWizard.qml:104
+msgctxt "@action:button"
+msgid "Continue"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksWizard.qml:116
+msgctxt "@action:button"
+msgid "Abort"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksMacroTutorial.qml:21
+msgctxt "@title:window"
+msgid "How to install Cura SolidWorks macro"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksMacroTutorial.qml:62
+msgctxt "@description:label"
+msgid "Steps:"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksMacroTutorial.qml:140
+msgctxt "@action:button"
+msgid ""
+"Open the directory\n"
+"with macro and icon"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksMacroTutorial.qml:160
+msgctxt "@description:label"
+msgid "Instructions:"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksMacroTutorial.qml:202
+msgctxt "@action:playpause"
+msgid "Play"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksMacroTutorial.qml:206
+msgctxt "@action:playpause"
+msgid "Pause"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksMacroTutorial.qml:268
+msgctxt "@action:button"
+msgid "Previous Step"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksMacroTutorial.qml:283
+msgctxt "@action:button"
+msgid "Done"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksMacroTutorial.qml:287
+msgctxt "@action:button"
+msgid "Next Step"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:21
+msgctxt "@title:window"
+msgid "SolidWorks plugin: Configuration"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:39
+msgctxt "@title:tab"
+msgid "Conversion settings"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:66
+msgctxt "@label"
+msgid "First choice:"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:86
+msgctxt "@text:menu"
+msgid "Latest installed version (Recommended)"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:95
+msgctxt "@text:menu"
+msgid "Default version"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:193
+msgctxt "@label"
+msgid "Show wizard before opening SolidWorks files"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:203
+msgctxt "@label"
+msgid "Automatically rotate opened file into normed orientation"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:210
+msgctxt "@title:tab"
+msgid "Installation(s)"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:284
+msgctxt "@label"
+msgid "COM service found"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:295
+msgctxt "@label"
+msgid "Executable found"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:306
+msgctxt "@label"
+msgid "COM starting"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:317
+msgctxt "@label"
+msgid "Revision number"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:328
+msgctxt "@label"
+msgid "Functions available"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:341
+#: /home/ruben/Projects/Cura/resources/qml/WorkspaceSummaryDialog.qml:264
+msgctxt "@action:button"
+msgid "Save"
+msgstr "Tallenna"
+
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:117
msgctxt "@label"
msgid "Color scheme"
msgstr "Värimalli"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:96
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:132
msgctxt "@label:listbox"
msgid "Material Color"
msgstr "Materiaalin väri"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:100
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:136
msgctxt "@label:listbox"
msgid "Line Type"
msgstr "Linjojen tyyppi"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:104
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:140
msgctxt "@label:listbox"
msgid "Feedrate"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:108
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:144
msgctxt "@label:listbox"
msgid "Layer thickness"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:148
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:185
msgctxt "@label"
msgid "Compatibility Mode"
msgstr "Yhteensopivuustila"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:230
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:264
msgctxt "@label"
msgid "Show Travels"
msgstr "Näytä siirtoliikkeet"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:236
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:270
msgctxt "@label"
msgid "Show Helpers"
msgstr "Näytä avustimet"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:242
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:276
msgctxt "@label"
msgid "Show Shell"
msgstr "Näytä kuori"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:248
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:282
msgctxt "@label"
msgid "Show Infill"
msgstr "Näytä täyttö"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:297
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:330
msgctxt "@label"
msgid "Only Show Top Layers"
msgstr "Näytä vain yläkerrokset"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:306
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:339
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:317
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:350
msgctxt "@label"
msgid "Top / Bottom"
msgstr "Yläosa/alaosa"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:321
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:354
msgctxt "@label"
msgid "Inner Wall"
msgstr "Sisäseinämä"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:378
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:410
msgctxt "@label"
msgid "min"
msgstr ""
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:420
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:452
msgctxt "@label"
msgid "max"
msgstr ""
@@ -1910,7 +2134,7 @@ msgctxt "@label"
msgid "Settings"
msgstr "Asetukset"
-#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.qml:455
+#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.qml:466
msgctxt "@info:tooltip"
msgid "Change active post-processing scripts"
msgstr "Muuta aktiivisia jälkikäsittelykomentosarjoja"
@@ -1985,23 +2209,53 @@ msgctxt "@action:label"
msgid "Smoothing"
msgstr "Tasoitus"
-#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:208
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:38
+msgctxt "@label"
+msgid "Mesh Type"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:69
+msgctxt "@label"
+msgid "Normal model"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:76
+msgctxt "@label"
+msgid "Print as support"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:84
+msgctxt "@label"
+msgid "Don't support overlap with other models"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:92
+msgctxt "@label"
+msgid "Modify settings for overlap with other models"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:100
+msgctxt "@label"
+msgid "Modify settings for infill of other models"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:333
msgctxt "@action:button"
msgid "Select settings"
msgstr "Valitse asetukset"
-#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:248
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:375
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:272
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:402
#: /home/ruben/Projects/Cura/resources/qml/Preferences/SettingVisibilityPage.qml:91
msgctxt "@label:textbox"
msgid "Filter..."
msgstr "Suodatin..."
-#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:296
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:426
msgctxt "@label:checkbox"
msgid "Show all"
msgstr "Näytä kaikki"
@@ -2360,66 +2614,66 @@ 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:88
+#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:87
msgctxt "@label:MonitorStatus"
msgid "Not connected to a printer"
msgstr "Ei yhteyttä tulostimeen"
-#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:90
+#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:89
msgctxt "@label:MonitorStatus"
msgid "Printer does not accept commands"
msgstr "Tulostin ei hyväksy komentoja"
-#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:96
+#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:95
#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:194
msgctxt "@label:MonitorStatus"
msgid "In maintenance. Please check the printer"
msgstr "Huolletaan. Tarkista tulostin"
-#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:103
+#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:102
#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:184
msgctxt "@label:MonitorStatus"
msgid "Printing..."
msgstr "Tulostetaan..."
-#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:106
+#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:105
#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:186
msgctxt "@label:MonitorStatus"
msgid "Paused"
msgstr "Keskeytetty"
-#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:109
+#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:108
#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:188
msgctxt "@label:MonitorStatus"
msgid "Preparing..."
msgstr "Valmistellaan..."
-#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:111
+#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:110
msgctxt "@label:MonitorStatus"
msgid "Please remove the print"
msgstr "Poista tuloste"
-#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:237
+#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:241
msgctxt "@label:"
msgid "Resume"
msgstr "Jatka"
-#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:241
+#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:245
msgctxt "@label:"
msgid "Pause"
msgstr "Keskeytä"
-#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:270
+#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:274
msgctxt "@label:"
msgid "Abort Print"
msgstr "Keskeytä tulostus"
-#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:280
+#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:284
msgctxt "@window:title"
msgid "Abort print"
msgstr "Keskeytä tulostus"
-#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:282
+#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:286
msgctxt "@label"
msgid "Are you sure you want to abort the print?"
msgstr "Haluatko varmasti keskeyttää tulostuksen?"
@@ -2454,19 +2708,19 @@ msgid "Customized"
msgstr "Mukautettu"
#: /home/ruben/Projects/Cura/resources/qml/DiscardOrKeepProfileChangesDialog.qml:157
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:593
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:595
msgctxt "@option:discardOrKeep"
msgid "Always ask me this"
msgstr "Kysy aina"
#: /home/ruben/Projects/Cura/resources/qml/DiscardOrKeepProfileChangesDialog.qml:158
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:594
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:596
msgctxt "@option:discardOrKeep"
msgid "Discard and never ask again"
msgstr "Hylkää äläkä kysy uudelleen"
#: /home/ruben/Projects/Cura/resources/qml/DiscardOrKeepProfileChangesDialog.qml:159
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:595
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:597
msgctxt "@option:discardOrKeep"
msgid "Keep and never ask again"
msgstr "Säilytä äläkä kysy uudelleen"
@@ -2501,72 +2755,72 @@ msgctxt "@label"
msgid "Brand"
msgstr "Merkki"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:92
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:88
msgctxt "@label"
msgid "Material Type"
msgstr "Materiaalin tyyppi"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:105
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:97
msgctxt "@label"
msgid "Color"
msgstr "Väri"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:139
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:141
msgctxt "@label"
msgid "Properties"
msgstr "Ominaisuudet"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:141
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:143
msgctxt "@label"
msgid "Density"
msgstr "Tiheys"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:156
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:158
msgctxt "@label"
msgid "Diameter"
msgstr "Läpimitta"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:185
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:187
msgctxt "@label"
msgid "Filament Cost"
msgstr "Tulostuslangan hinta"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:201
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:203
msgctxt "@label"
msgid "Filament weight"
msgstr "Tulostuslangan paino"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:218
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:220
msgctxt "@label"
msgid "Filament length"
msgstr "Tulostuslangan pituus"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:227
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:229
msgctxt "@label"
msgid "Cost per Meter"
msgstr "Hinta metriä kohden"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:241
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:243
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/MaterialView.qml:248
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:250
msgctxt "@label"
msgid "Unlink Material"
msgstr "Poista materiaalin linkitys"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:259
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:261
msgctxt "@label"
msgid "Description"
msgstr "Kuvaus"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:272
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:274
msgctxt "@label"
msgid "Adhesion Information"
msgstr "Tarttuvuustiedot"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:298
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:300
msgctxt "@label"
msgid "Print settings"
msgstr "Tulostusasetukset"
@@ -2607,7 +2861,7 @@ msgid "Unit"
msgstr "Yksikkö"
#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:14
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:439
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:509
msgctxt "@title:tab"
msgid "General"
msgstr "Yleiset"
@@ -2622,230 +2876,255 @@ msgctxt "@label"
msgid "Language:"
msgstr "Kieli:"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:205
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:207
msgctxt "@label"
msgid "Currency:"
msgstr "Valuutta:"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:219
+#: /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:279
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:281
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:296
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:298
msgctxt "@info:tooltip"
msgid "Slice automatically when changing settings."
msgstr "Viipaloi automaattisesti, kun asetuksia muutetaan."
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:304
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:306
msgctxt "@option:check"
msgid "Slice automatically"
msgstr "Viipaloi automaattisesti"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:318
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:320
msgctxt "@label"
msgid "Viewport behavior"
msgstr "Näyttöikkunan käyttäytyminen"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:326
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:328
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:335
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:337
msgctxt "@option:check"
msgid "Display overhang"
msgstr "Näytä uloke"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:342
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:344
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:347
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:349
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:356
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:358
msgctxt "@info:tooltip"
msgid "Should the default zoom behavior of cura be inverted?"
msgstr "Pitääkö Curan oletusarvoinen zoom-toimintatapa muuttaa päinvastaiseksi?"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:361
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:363
msgctxt "@action:button"
msgid "Invert the direction of camera zoom."
msgstr "Käännä kameran zoomin suunta päinvastaiseksi."
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:370
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:372
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:375
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:377
msgctxt "@action:button"
msgid "Zoom toward mouse direction"
msgstr "Zoomaa hiiren suuntaan"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:384
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:386
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:389
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:391
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:397
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:399
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:402
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:404
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:414
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:416
msgctxt "@info:tooltip"
msgid "Show caution message in gcode reader."
msgstr "Näytä varoitusviesti gcode-lukijassa."
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:423
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:425
msgctxt "@option:check"
msgid "Caution message in gcode reader"
msgstr "Gcode-lukijan varoitusviesti"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:430
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:432
msgctxt "@info:tooltip"
msgid "Should layer be forced into compatibility mode?"
msgstr "Pakotetaanko kerros yhteensopivuustilaan?"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:435
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:437
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:451
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:453
msgctxt "@label"
msgid "Opening and saving files"
msgstr "Tiedostojen avaaminen ja tallentaminen"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:457
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:459
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:462
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:464
msgctxt "@option:check"
msgid "Scale large models"
msgstr "Skaalaa suuret mallit"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:471
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:473
msgctxt "@info:tooltip"
msgid "An model may appear extremely small if its unit is for example in meters rather than millimeters. Should these models be scaled up?"
msgstr "Malli voi vaikuttaa erittäin pieneltä, jos sen koko on ilmoitettu esimerkiksi metreissä eikä millimetreissä. Pitäisikö nämä mallit suurentaa?"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:476
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:478
msgctxt "@option:check"
msgid "Scale extremely small models"
msgstr "Skaalaa erittäin pienet mallit"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:485
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:487
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:490
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:492
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:499
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:501
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:503
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:505
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:512
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:514
msgctxt "@info:tooltip"
msgid "Default behavior when opening a project file"
msgstr "Projektitiedoston avaamisen oletustoimintatapa"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:520
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:522
msgctxt "@window:text"
msgid "Default behavior when opening a project file: "
msgstr "Projektitiedoston avaamisen oletustoimintatapa: "
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:533
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:535
msgctxt "@option:openProject"
msgid "Always ask"
msgstr "Kysy aina"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:534
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:536
msgctxt "@option:openProject"
msgid "Always open as a project"
msgstr "Avaa aina projektina"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:535
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:537
msgctxt "@option:openProject"
msgid "Always import models"
msgstr "Tuo mallit aina"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:571
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:573
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:580
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:582
msgctxt "@label"
msgid "Override Profile"
msgstr "Kumoa profiili"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:629
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:631
msgctxt "@label"
msgid "Privacy"
msgstr "Tietosuoja"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:636
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:638
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:641
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:643
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:651
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:653
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:656
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:658
msgctxt "@option:check"
msgid "Send (anonymous) print information"
msgstr "Lähetä (anonyymit) tulostustiedot"
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:674
+msgctxt "@label"
+msgid "Experimental"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:680
+msgctxt "@info:tooltip"
+msgid "Use multi build plate functionality"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:685
+msgctxt "@option:check"
+msgid "Use multi build plate functionality (restart required)"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:694
+msgctxt "@info:tooltip"
+msgid "Should newly loaded models be arranged on the build plate? Used in conjunction with multi build plate (EXPERIMENTAL)"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:699
+msgctxt "@option:check"
+msgid "Do not arrange objects on load"
+msgstr ""
+
#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:15
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:444
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:514
msgctxt "@title:tab"
msgid "Printers"
msgstr "Tulostimet"
#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:37
#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:51
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:137
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:138
msgctxt "@action:button"
msgid "Activate"
msgstr "Aktivoi"
@@ -2888,7 +3167,7 @@ msgid "Waiting for a printjob"
msgstr "Odotetaan tulostustyötä"
#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:15
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:448
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:518
msgctxt "@title:tab"
msgid "Profiles"
msgstr "Profiilit"
@@ -2914,13 +3193,13 @@ msgid "Duplicate"
msgstr "Jäljennös"
#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:113
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:201
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:182
msgctxt "@action:button"
msgid "Import"
msgstr "Tuo"
#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:119
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:212
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:193
msgctxt "@action:button"
msgid "Export"
msgstr "Vie"
@@ -2986,7 +3265,7 @@ msgid "Export Profile"
msgstr "Profiilin vienti"
#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:15
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:446
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:516
msgctxt "@title:tab"
msgid "Materials"
msgstr "Materiaalit"
@@ -3001,60 +3280,60 @@ msgctxt "@action:label %1 is printer name"
msgid "Printer: %1"
msgstr "Tulostin: %1"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:149
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:150
msgctxt "@action:button"
msgid "Create"
msgstr "Luo"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:168
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:160
msgctxt "@action:button"
msgid "Duplicate"
msgstr "Jäljennös"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:311
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:319
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:298
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:306
msgctxt "@title:window"
msgid "Import Material"
msgstr "Tuo materiaali"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:320
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:307
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/MaterialsPage.qml:324
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:311
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/MaterialsPage.qml:343
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:358
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:329
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:344
msgctxt "@title:window"
msgid "Export Material"
msgstr "Vie materiaali"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:362
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:348
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/MaterialsPage.qml:368
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:354
msgctxt "@info:status Don't translate the XML tag !"
msgid "Successfully exported material to %1"
msgstr "Materiaalin vieminen onnistui kohteeseen %1"
#: /home/ruben/Projects/Cura/resources/qml/AddMachineDialog.qml:18
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:793
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:869
msgctxt "@title:window"
msgid "Add Printer"
msgstr "Lisää tulostin"
-#: /home/ruben/Projects/Cura/resources/qml/AddMachineDialog.qml:185
+#: /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:208
+#: /home/ruben/Projects/Cura/resources/qml/AddMachineDialog.qml:217
msgctxt "@action:button"
msgid "Add Printer"
msgstr "Lisää tulostin"
@@ -3183,12 +3462,7 @@ msgctxt "@label"
msgid "Profile:"
msgstr "Profiili:"
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:66
-msgctxt "@"
-msgid "No Profile Available"
-msgstr ""
-
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:104
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:102
msgctxt "@tooltip"
msgid ""
"Some setting/override values are different from the values stored in the profile.\n"
@@ -3199,37 +3473,37 @@ msgstr ""
"\n"
"Avaa profiilin hallinta napsauttamalla."
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:152
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:150
msgctxt "@label:textbox"
msgid "Search..."
msgstr "Haku…"
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:483
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:482
msgctxt "@action:menu"
msgid "Copy value to all extruders"
msgstr "Kopioi arvo kaikkiin suulakepuristimiin"
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:498
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:497
msgctxt "@action:menu"
msgid "Hide this setting"
msgstr "Piilota tämä asetus"
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:508
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:507
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:512
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:511
msgctxt "@action:menu"
msgid "Keep this setting visible"
msgstr "Pidä tämä asetus näkyvissä"
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:531
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:530
msgctxt "@action:menu"
msgid "Configure setting visiblity..."
msgstr "Määritä asetusten näkyvyys..."
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingCategory.qml:123
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingCategory.qml:250
msgctxt "@label"
msgid ""
"Some hidden settings use values different from their normal calculated value.\n"
@@ -3240,27 +3514,27 @@ msgstr ""
"\n"
"Tee asetuksista näkyviä napsauttamalla."
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:62
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:61
msgctxt "@label Header for list of settings."
msgid "Affects"
msgstr "Koskee seuraavia:"
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:67
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:66
msgctxt "@label Header for list of settings."
msgid "Affected By"
msgstr "Riippuu seuraavista:"
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:157
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:156
msgctxt "@label"
-msgid "This setting is always shared between all extruders. Changing it here will change the value for all extruders"
-msgstr "Tämä asetus koskee aina kaikkia suulakepuristimia. Jos se vaihdetaan tässä, kaikkien suulakepuristimien arvo muuttuu"
+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:160
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:159
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:186
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:190
msgctxt "@label"
msgid ""
"This setting has a value that is different from the profile.\n"
@@ -3271,7 +3545,7 @@ msgstr ""
"\n"
"Palauta profiilin arvo napsauttamalla."
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:284
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:288
msgctxt "@label"
msgid ""
"This setting is normally calculated, but it currently has an absolute value set.\n"
@@ -3282,12 +3556,12 @@ msgstr ""
"\n"
"Palauta laskettu arvo napsauttamalla."
-#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:120
+#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:128
msgctxt "@label:listbox"
msgid "Print Setup"
msgstr "Tulostuksen asennus"
-#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:120
+#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:128
msgctxt "@label:listbox"
msgid ""
"Print Setup disabled\n"
@@ -3296,59 +3570,59 @@ msgstr ""
"Tulostuksen asennus ei käytössä\n"
"G-code-tiedostoja ei voida muokata"
-#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:336
+#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:342
msgctxt "@label Hours and minutes"
msgid "00h 00min"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:354
+#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:359
msgctxt "@tooltip"
-msgid "Time specification
"
+msgid "Time specification"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:429
+#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:441
msgctxt "@label"
msgid "Cost specification"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:434
-#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:445
+#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:446
+#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:455
msgctxt "@label m for meter"
msgid "%1m"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:435
-#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:446
+#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:447
+#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:456
msgctxt "@label g for grams"
msgid "%1g"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:444
+#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:454
msgctxt "@label"
msgid "Total:"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:498
+#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:504
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/resources/qml/Sidebar.qml:503
+#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:509
msgctxt "@label Print estimates: m for meters, g for grams"
msgid "%1m / ~ %2g"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:586
+#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:591
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/Sidebar.qml:591
+#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:596
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/Menus/MaterialMenu.qml:49
+#: /home/ruben/Projects/Cura/resources/qml/Menus/MaterialMenu.qml:50
msgctxt "@title:menuitem %1 is the automatically selected material"
msgid "Automatic: %1"
msgstr "Automaattinen: %1"
@@ -3358,6 +3632,16 @@ msgctxt "@title:menu menubar:toplevel"
msgid "&View"
msgstr "&Näytä"
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ViewMenu.qml:37
+msgctxt "@action:inmenu menubar:view"
+msgid "&Camera position"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ViewMenu.qml:52
+msgctxt "@action:inmenu menubar:view"
+msgid "&Build plate"
+msgstr ""
+
#: /home/ruben/Projects/Cura/resources/qml/Menus/NozzleMenu.qml:40
msgctxt "@title:menuitem %1 is the nozzle currently loaded in the printer"
msgid "Automatic: %1"
@@ -3370,14 +3654,14 @@ msgid_plural "Print Selected Models With:"
msgstr[0] "Tulosta valittu malli asetuksella:"
msgstr[1] "Tulosta valitut mallit asetuksella:"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/ContextMenu.qml:83
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ContextMenu.qml:114
msgctxt "@title:window"
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/Menus/ContextMenu.qml:108
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ContextMenu.qml:139
msgctxt "@label"
msgid "Number of Copies"
msgstr "Kopioiden määrä"
@@ -3393,7 +3677,7 @@ msgid "No printer connected"
msgstr "Ei tulostinta yhdistettynä"
#: /home/ruben/Projects/Cura/resources/qml/PrintMonitor.qml:90
-#: /home/ruben/Projects/Cura/resources/qml/SidebarHeader.qml:138
+#: /home/ruben/Projects/Cura/resources/qml/SidebarHeader.qml:139
msgctxt "@label"
msgid "Extruder"
msgstr "Suulake"
@@ -3503,254 +3787,294 @@ msgctxt "@label"
msgid "Estimated time left"
msgstr "Aikaa jäljellä arviolta"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:72
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:79
msgctxt "@action:inmenu"
msgid "Toggle Fu&ll Screen"
msgstr "Vaihda &koko näyttöön"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:79
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:86
msgctxt "@action:inmenu menubar:edit"
msgid "&Undo"
msgstr "&Kumoa"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:89
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:96
msgctxt "@action:inmenu menubar:edit"
msgid "&Redo"
msgstr "Tee &uudelleen"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:99
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:106
msgctxt "@action:inmenu menubar:file"
msgid "&Quit"
msgstr "&Lopeta"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:107
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:114
msgctxt "@action:inmenu menubar:view"
-msgid "&Reset camera position"
+msgid "&3D View"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:114
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:121
+msgctxt "@action:inmenu menubar:view"
+msgid "&Front View"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:128
+msgctxt "@action:inmenu menubar:view"
+msgid "&Top View"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:135
+msgctxt "@action:inmenu menubar:view"
+msgid "&Left Side View"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:142
+msgctxt "@action:inmenu menubar:view"
+msgid "&Right Side View"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:149
msgctxt "@action:inmenu"
msgid "Configure Cura..."
msgstr "Määritä Curan asetukset..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:121
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:156
msgctxt "@action:inmenu menubar:printer"
msgid "&Add Printer..."
msgstr "L&isää tulostin..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:127
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:162
msgctxt "@action:inmenu menubar:printer"
msgid "Manage Pr&inters..."
msgstr "Tulostinten &hallinta..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:134
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:169
msgctxt "@action:inmenu"
msgid "Manage Materials..."
msgstr "Hallitse materiaaleja..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:142
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:177
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:150
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:185
msgctxt "@action:inmenu menubar:profile"
msgid "&Discard current changes"
msgstr "&Hylkää tehdyt muutokset"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:162
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:197
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:168
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:203
msgctxt "@action:inmenu menubar:profile"
msgid "Manage Profiles..."
msgstr "Profiilien hallinta..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:175
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:210
msgctxt "@action:inmenu menubar:help"
msgid "Show Online &Documentation"
msgstr "Näytä sähköinen &dokumentaatio"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:183
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:218
msgctxt "@action:inmenu menubar:help"
msgid "Report a &Bug"
msgstr "Ilmoita &virheestä"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:191
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:226
msgctxt "@action:inmenu menubar:help"
msgid "&About..."
msgstr "Ti&etoja..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:198
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:233
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:208
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:243
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:217
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:252
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:226
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:261
msgctxt "@action:inmenu"
msgid "Delete Model"
msgstr "Poista malli"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:234
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:269
msgctxt "@action:inmenu"
msgid "Ce&nter Model on Platform"
msgstr "Ke&skitä malli alustalle"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:240
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:275
msgctxt "@action:inmenu menubar:edit"
msgid "&Group Models"
msgstr "&Ryhmittele mallit"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:250
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:295
msgctxt "@action:inmenu menubar:edit"
msgid "Ungroup Models"
msgstr "Poista mallien ryhmitys"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:260
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:305
msgctxt "@action:inmenu menubar:edit"
msgid "&Merge Models"
msgstr "&Yhdistä mallit"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:270
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:315
msgctxt "@action:inmenu"
msgid "&Multiply Model..."
msgstr "&Kerro malli..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:277
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:322
msgctxt "@action:inmenu menubar:edit"
msgid "&Select All Models"
msgstr "&Valitse kaikki mallit"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:287
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:332
msgctxt "@action:inmenu menubar:edit"
msgid "&Clear Build Plate"
msgstr "&Tyhjennä tulostusalusta"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:297
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:342
msgctxt "@action:inmenu menubar:file"
msgid "Re&load All Models"
msgstr "&Lataa kaikki mallit uudelleen"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:306
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:351
+msgctxt "@action:inmenu menubar:edit"
+msgid "Arrange All Models To All Build Plates"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:358
msgctxt "@action:inmenu menubar:edit"
msgid "Arrange All Models"
msgstr "Järjestä kaikki mallit"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:314
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:366
msgctxt "@action:inmenu menubar:edit"
msgid "Arrange Selection"
msgstr "Järjestä valinta"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:321
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:373
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:328
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:380
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:335
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:387
msgctxt "@action:inmenu menubar:file"
msgid "&Open File(s)..."
msgstr "&Avaa tiedosto(t)..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:343
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:395
msgctxt "@action:inmenu menubar:file"
msgid "&New Project..."
msgstr "&Uusi projekti..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:350
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:402
msgctxt "@action:inmenu menubar:help"
msgid "Show Engine &Log..."
msgstr "Näytä moottorin l&oki"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:358
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:410
msgctxt "@action:inmenu menubar:help"
msgid "Show Configuration Folder"
msgstr "Näytä määrityskansio"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:365
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:417
msgctxt "@action:menu"
msgid "Configure setting visibility..."
msgstr "Määritä asetusten näkyvyys..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:372
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:424
msgctxt "@action:menu"
msgid "Browse plugins..."
msgstr "Selaa lisäosia..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:379
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:431
msgctxt "@action:menu"
msgid "Installed plugins..."
msgstr "Asennetut lisäoset..."
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:28
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:438
+msgctxt "@action:inmenu menubar:view"
+msgid "Expand/Collapse Sidebar"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:26
msgctxt "@label:PrintjobStatus"
msgid "Please load a 3D model"
msgstr "Lataa 3D-malli"
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:34
+#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:36
msgctxt "@label:PrintjobStatus"
msgid "Ready to slice"
msgstr "Valmiina viipaloimaan"
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:36
+#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:38
msgctxt "@label:PrintjobStatus"
msgid "Slicing..."
msgstr "Viipaloidaan..."
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:38
+#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:40
msgctxt "@label:PrintjobStatus %1 is target operation"
msgid "Ready to %1"
msgstr "Valmis: %1"
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:40
+#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:42
msgctxt "@label:PrintjobStatus"
msgid "Unable to Slice"
msgstr "Viipalointi ei onnistu"
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:42
+#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:44
msgctxt "@label:PrintjobStatus"
msgid "Slicing unavailable"
msgstr "Viipalointi ei käytettävissä"
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:162
+#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:171
+msgctxt "@info:tooltip"
+msgid "Slice current printjob"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:171
+msgctxt "@info:tooltip"
+msgid "Cancel slicing process"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:183
msgctxt "@label:Printjob"
msgid "Prepare"
msgstr "Valmistele"
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:162
+#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:183
msgctxt "@label:Printjob"
msgid "Cancel"
msgstr "Peruuta"
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:302
+#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:317
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:620
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:696
msgctxt "@title:window"
msgid "Open file(s)"
msgstr "Avaa tiedosto(t)"
@@ -3770,114 +4094,114 @@ msgctxt "@title:window"
msgid "Ultimaker Cura"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:81
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:102
msgctxt "@title:menu menubar:toplevel"
msgid "&File"
msgstr "&Tiedosto"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:98
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:119
msgctxt "@action:inmenu menubar:file"
msgid "&Save Selection to File"
msgstr "&Tallenna valinta tiedostoon"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:107
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:128
msgctxt "@title:menu menubar:file"
msgid "Save &As..."
msgstr "Tallenna &nimellä…"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:118
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:139
msgctxt "@title:menu menubar:file"
-msgid "Save project"
-msgstr "Tallenna projekti"
+msgid "Save &Project..."
+msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:141
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:162
msgctxt "@title:menu menubar:toplevel"
msgid "&Edit"
msgstr "&Muokkaa"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:158
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:179
msgctxt "@title:menu"
msgid "&View"
msgstr "&Näytä"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:163
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:184
msgctxt "@title:menu"
msgid "&Settings"
msgstr "&Asetukset"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:165
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:186
msgctxt "@title:menu menubar:toplevel"
msgid "&Printer"
msgstr "&Tulostin"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:175
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:187
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:196
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:208
msgctxt "@title:menu"
msgid "&Material"
msgstr "&Materiaali"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:176
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:188
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:197
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:209
msgctxt "@title:menu"
msgid "&Profile"
msgstr "&Profiili"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:180
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:201
msgctxt "@action:inmenu"
msgid "Set as Active Extruder"
msgstr "Aseta aktiiviseksi suulakepuristimeksi"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:198
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:219
msgctxt "@title:menu menubar:toplevel"
msgid "E&xtensions"
msgstr "Laa&jennukset"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:232
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:253
msgctxt "@title:menu menubar:toplevel"
msgid "P&lugins"
msgstr "&Lisäosat"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:240
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:261
msgctxt "@title:menu menubar:toplevel"
msgid "P&references"
msgstr "L&isäasetukset"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:248
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:269
msgctxt "@title:menu menubar:toplevel"
msgid "&Help"
msgstr "&Ohje"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:330
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:351
msgctxt "@action:button"
msgid "Open File"
msgstr "Avaa tiedosto"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:442
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:512
msgctxt "@title:tab"
msgid "Settings"
msgstr "Asetukset"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:478
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:554
msgctxt "@title:window"
msgid "New project"
msgstr "Uusi projekti"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:479
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:555
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:721
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:797
msgctxt "@window:title"
msgid "Install Plugin"
msgstr "Asenna laajennus"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:728
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:804
msgctxt "@title:window"
msgid "Open File(s)"
msgstr "Avaa tiedosto(t)"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:731
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:807
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."
@@ -3902,97 +4226,82 @@ 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:264
-msgctxt "@action:button"
-msgid "Save"
-msgstr "Tallenna"
-
-#: /home/ruben/Projects/Cura/resources/qml/Topbar.qml:74
-msgctxt "@title:tab"
-msgid "Prepare"
-msgstr "Valmistele"
-
-#: /home/ruben/Projects/Cura/resources/qml/Topbar.qml:100
-msgctxt "@title:tab"
-msgid "Monitor"
-msgstr "Valvo"
-
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:163
+#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:175
msgctxt "@label"
msgid "Layer Height"
msgstr "Kerroksen korkeus"
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:323
+#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:345
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:340
+#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:362
msgctxt "@label"
msgid "Print Speed"
msgstr "Tulostusnopeus"
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:350
+#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:374
msgctxt "@label"
msgid "Slower"
msgstr "Hitaammin"
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:361
+#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:385
msgctxt "@label"
msgid "Faster"
msgstr "Nopeammin"
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:388
+#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:423
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:413
+#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:446
msgctxt "@label"
msgid "Infill"
msgstr "Täyttö"
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:633
+#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:668
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:645
+#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:680
msgctxt "@label"
msgid "Enable gradual"
msgstr "Ota asteittainen käyttöön"
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:712
+#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:747
msgctxt "@label"
msgid "Generate Support"
msgstr "Muodosta tuki"
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:746
+#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:781
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:764
+#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:799
msgctxt "@label"
msgid "Support Extruder"
msgstr "Tuen suulake"
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:816
+#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:851
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:839
+#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:874
msgctxt "@label"
msgid "Build Plate Adhesion"
msgstr "Alustan tarttuvuus"
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:894
+#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:929
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:934
+#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:969
msgctxt "@label"
msgid "Need help improving your prints? Read the Ultimaker Troubleshooting Guides"
msgstr "Tarvitsetko apua tulosteiden parantamiseen? Lue Ultimakerin vianmääritysoppaat"
@@ -4009,17 +4318,22 @@ msgctxt "@title:window"
msgid "Open project file"
msgstr "Avaa projektitiedosto"
-#: /home/ruben/Projects/Cura/resources/qml/AskOpenAsProjectOrModelsDialog.qml:72
+#: /home/ruben/Projects/Cura/resources/qml/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
+msgctxt "@text:window"
+msgid "Remember my choice"
+msgstr "Muista valintani"
+
+#: /home/ruben/Projects/Cura/resources/qml/AskOpenAsProjectOrModelsDialog.qml:122
msgctxt "@action:button"
msgid "Open as project"
msgstr "Avaa projektina"
-#: /home/ruben/Projects/Cura/resources/qml/AskOpenAsProjectOrModelsDialog.qml:122
+#: /home/ruben/Projects/Cura/resources/qml/AskOpenAsProjectOrModelsDialog.qml:131
msgctxt "@action:button"
msgid "Import models"
msgstr "Tuo mallit"
@@ -4029,21 +4343,36 @@ msgctxt "@title:window"
msgid "Engine Log"
msgstr "Moottorin loki"
-#: /home/ruben/Projects/Cura/resources/qml/SidebarHeader.qml:242
+#: /home/ruben/Projects/Cura/resources/qml/SidebarHeader.qml:245
msgctxt "@label"
msgid "Material"
msgstr "Materiaali"
-#: /home/ruben/Projects/Cura/resources/qml/SidebarHeader.qml:349
+#: /home/ruben/Projects/Cura/resources/qml/SidebarHeader.qml:352
msgctxt "@label"
-msgid "Check compatibility"
+msgid "Check compatibility"
msgstr ""
-#: /home/ruben/Projects/Cura/resources/qml/SidebarHeader.qml:369
+#: /home/ruben/Projects/Cura/resources/qml/SidebarHeader.qml:372
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"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/ObjectsList.qml:227
+msgctxt "@action:button"
+msgid "Arrange to all build plates"
+msgstr ""
+
+#: /home/ruben/Projects/Cura/resources/qml/ObjectsList.qml:247
+msgctxt "@action:button"
+msgid "Arrange current build plate"
+msgstr ""
+
#: MachineSettingsAction/plugin.json
msgctxt "description"
msgid "Provides a way to change machine settings (such as build volume, nozzle size, etc)"
@@ -4134,6 +4463,26 @@ msgctxt "name"
msgid "USB printing"
msgstr "USB-tulostus"
+#: PrepareStage/plugin.json
+msgctxt "description"
+msgid "Provides a prepare stage in Cura."
+msgstr ""
+
+#: PrepareStage/plugin.json
+msgctxt "name"
+msgid "Prepare Stage"
+msgstr ""
+
+#: CuraLiveScriptingPlugin/plugin.json
+msgctxt "description"
+msgid "Provides an edit window for direct script editing."
+msgstr ""
+
+#: CuraLiveScriptingPlugin/plugin.json
+msgctxt "name"
+msgid "Live scripting tool"
+msgstr ""
+
#: RemovableDriveOutputDevice/plugin.json
msgctxt "description"
msgid "Provides removable drive hotplugging and writing support."
@@ -4154,6 +4503,16 @@ msgctxt "name"
msgid "UM3 Network Connection"
msgstr "UM3-verkkoyhteys"
+#: MonitorStage/plugin.json
+msgctxt "description"
+msgid "Provides a monitor stage in Cura."
+msgstr ""
+
+#: MonitorStage/plugin.json
+msgctxt "name"
+msgid "Monitor Stage"
+msgstr ""
+
#: FirmwareUpdateChecker/plugin.json
msgctxt "description"
msgid "Checks for firmware updates."
@@ -4166,8 +4525,8 @@ msgstr "Laiteohjelmiston päivitysten tarkistus"
#: CuraSolidWorksPlugin/plugin.json
msgctxt "description"
-msgid "Gives you the possibility to open certain files via SolidWorks itself. These are then converted and loaded into Cura"
-msgstr "Mahdollistaa tiettyjen tiedostojen avaamisen SolidWorks-ohjelmiston kautta. Tämän jälkeen tiedostot muunnetaan ja ladataan Curaan."
+msgid "Gives you the possibility to open certain files using SolidWorks itself. Conversion is done by this plugin and additional optimizations."
+msgstr ""
#: CuraSolidWorksPlugin/plugin.json
msgctxt "name"
@@ -4234,6 +4593,16 @@ msgctxt "name"
msgid "Legacy Cura Profile Reader"
msgstr "Aikaisempien Cura-profiilien lukija"
+#: CuraBlenderPlugin/plugin.json
+msgctxt "description"
+msgid "Helps to open Blender files directly in Cura."
+msgstr ""
+
+#: CuraBlenderPlugin/plugin.json
+msgctxt "name"
+msgid "Blender Integration (experimental)"
+msgstr ""
+
#: GCodeProfileReader/plugin.json
msgctxt "description"
msgid "Provides support for importing profiles from g-code files."
@@ -4394,6 +4763,16 @@ msgctxt "name"
msgid "Cura Profile Writer"
msgstr "Cura-profiilin kirjoitin"
+#: CuraPrintProfileCreator/plugin.json
+msgctxt "description"
+msgid "Allows material manufacturers to create new material and quality profiles using a drop-in UI."
+msgstr ""
+
+#: CuraPrintProfileCreator/plugin.json
+msgctxt "name"
+msgid "Print Profile Assistant"
+msgstr ""
+
#: 3MFWriter/plugin.json
msgctxt "description"
msgid "Provides support for writing 3MF files."
@@ -4434,6 +4813,98 @@ msgctxt "name"
msgid "Cura Profile Reader"
msgstr "Cura-profiilin lukija"
+#~ msgctxt "@label"
+#~ msgid "Unknown"
+#~ msgstr "Tuntematon"
+
+#~ msgctxt "@info:status"
+#~ msgid "Errors appeared while opening your SolidWorks file! Please check, whether it is possible to open your file in SolidWorks itself without any problems as well!"
+#~ msgstr "SolidWorks-tiedostoa avattaessa ilmeni virheitä! Tarkista, voiko tiedoston avata SolidWorks-ohjelmistossa ilman ongelmia."
+
+#~ msgctxt "@info:status"
+#~ msgid "Error while starting %s!"
+#~ msgstr "%s:n käynnistyksen aikana ilmeni virhe!"
+
+#~ msgctxt "@info"
+#~ msgid "Cura collects anonymised slicing statistics. You can disable this in the preferences."
+#~ msgstr "Cura kerää anonyymejä viipalointiin liittyviä tilastotietoja. Tämän voi poistaa käytöstä asetuksien kautta."
+
+#~ msgctxt "@action:button"
+#~ msgid "Dismiss"
+#~ msgstr "Ohita"
+
+#~ msgctxt "@label"
+#~ msgid "Material diameter"
+#~ msgstr "Materiaalin halkaisija"
+
+#~ msgctxt "@label"
+#~ msgid "Ultimaker 3"
+#~ msgstr "Ultimaker 3"
+
+#~ msgctxt "@label"
+#~ msgid "Ultimaker 3 Extended"
+#~ msgstr "Ultimaker 3 Extended"
+
+#~ msgctxt "@title:window"
+#~ msgid "Cura SolidWorks Plugin Configuration"
+#~ msgstr "Cura SolidWorks -laajennuksen määritys"
+
+#~ msgctxt "@action:label"
+#~ msgid "Default quality of the exported STL:"
+#~ msgstr "Viedyn STL:n oletuslaatu:"
+
+#~ msgctxt "@option:curaSolidworksStlQuality"
+#~ msgid "Always ask"
+#~ msgstr "Kysy aina"
+
+#~ msgctxt "@option:curaSolidworksStlQuality"
+#~ msgid "Always use Fine quality"
+#~ msgstr "Käytä aina hienoa laatua"
+
+#~ msgctxt "@option:curaSolidworksStlQuality"
+#~ msgid "Always use Coarse quality"
+#~ msgstr "Käytä aina karkeaa laatua"
+
+#~ msgctxt "@title:window"
+#~ msgid "Import SolidWorks File as STL..."
+#~ msgstr "Tuo SolidWorks-tiedosto STL-muodossa..."
+
+#~ msgctxt "@info:tooltip"
+#~ msgid "Quality of the Exported STL"
+#~ msgstr "Viedyn STL:n laatu"
+
+#~ msgctxt "@action:label"
+#~ msgid "Quality"
+#~ msgstr "Laatu"
+
+#~ msgctxt "@option:curaSolidworksStlQuality"
+#~ msgid "Coarse"
+#~ msgstr "Karkea"
+
+#~ msgctxt "@option:curaSolidworksStlQuality"
+#~ msgid "Fine"
+#~ msgstr "Hieno"
+
+#~ msgctxt "@label"
+#~ msgid "This setting is always shared between all extruders. Changing it here will change the value for all extruders"
+#~ msgstr "Tämä asetus koskee aina kaikkia suulakepuristimia. Jos se vaihdetaan tässä, kaikkien suulakepuristimien arvo muuttuu"
+
+#~ msgctxt "@title:menu menubar:file"
+#~ msgid "Save project"
+#~ msgstr "Tallenna projekti"
+
+#~ msgctxt "@title:tab"
+#~ msgid "Prepare"
+#~ msgstr "Valmistele"
+
+#~ msgctxt "@title:tab"
+#~ msgid "Monitor"
+#~ msgstr "Valvo"
+
+#~ msgctxt "description"
+#~ msgid "Gives you the possibility to open certain files via SolidWorks itself. These are then converted and loaded into Cura"
+#~ msgstr "Mahdollistaa tiettyjen tiedostojen avaamisen SolidWorks-ohjelmiston kautta. Tämän jälkeen tiedostot muunnetaan ja ladataan Curaan."
+
#~ msgctxt "@label:status"
#~ msgid "Blocked"
#~ msgstr "Tukossa"
@@ -4454,10 +4925,6 @@ msgstr "Cura-profiilin lukija"
#~ msgid "To ensure that your {machine_name} is equipped with the latest features it is recommended to update the firmware regularly. This can be done on the {machine_name} (when connected to the network) or via USB."
#~ msgstr "On suositeltavaa päivittää laiteohjelmisto säännöllisesti, jotta voidaan varmistaa, että laitteessa {machine_name} on viimeisimmät ominaisuudet. Tämä voidaan tehdä laitteessa {machine_name} (verkkoon yhdistettynä) tai USB:n kautta."
-#~ msgctxt "@item:inlistbox"
-#~ msgid "Layer view"
-#~ msgstr "Kerrosnäkymä"
-
#~ msgctxt "@info:title"
#~ msgid "Layer View"
#~ msgstr "Kerrosnäkymä"
diff --git a/resources/i18n/fi_FI/fdmextruder.def.json.po b/resources/i18n/fi_FI/fdmextruder.def.json.po
index a76ee285e0..ea50325417 100644
--- a/resources/i18n/fi_FI/fdmextruder.def.json.po
+++ b/resources/i18n/fi_FI/fdmextruder.def.json.po
@@ -6,8 +6,8 @@
msgid ""
msgstr ""
"Project-Id-Version: Cura 3.0\n"
-"Report-Msgid-Bugs-To: http://github.com/ultimaker/uranium\n"
-"POT-Creation-Date: 2017-11-21 16:58+0000\n"
+"Report-Msgid-Bugs-To: r.dulek@ultimaker.com\n"
+"POT-Creation-Date: 2017-08-02 16:53+0000\n"
"PO-Revision-Date: 2017-08-11 14:31+0200\n"
"Last-Translator: Bothof \n"
"Language-Team: Finnish\n"
diff --git a/resources/i18n/fi_FI/fdmprinter.def.json.po b/resources/i18n/fi_FI/fdmprinter.def.json.po
index 23ed6b0da4..678d6afcec 100644
--- a/resources/i18n/fi_FI/fdmprinter.def.json.po
+++ b/resources/i18n/fi_FI/fdmprinter.def.json.po
@@ -6,8 +6,8 @@
msgid ""
msgstr ""
"Project-Id-Version: Cura 3.0\n"
-"Report-Msgid-Bugs-To: http://github.com/ultimaker/uranium\n"
-"POT-Creation-Date: 2017-11-21 16:58+0000\n"
+"Report-Msgid-Bugs-To: r.dulek@ultimaker.com\n"
+"POT-Creation-Date: 2017-08-02 16:53+0000\n"
"PO-Revision-Date: 2017-09-27 12:27+0200\n"
"Last-Translator: Bothof \n"
"Language-Team: Finnish\n"
@@ -349,6 +349,16 @@ msgctxt "machine_gcode_flavor option Repetier"
msgid "Repetier"
msgstr "Repetier"
+#: fdmprinter.def.json
+msgctxt "machine_firmware_retract label"
+msgid "Firmware Retraction"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "machine_firmware_retract description"
+msgid "Whether to use firmware retract commands (G10/G11) instead of using the E property in G1 commands to retract the material."
+msgstr ""
+
#: fdmprinter.def.json
msgctxt "machine_disallowed_areas label"
msgid "Disallowed areas"
@@ -609,31 +619,6 @@ msgctxt "layer_height_0 description"
msgid "The height of the initial layer in mm. A thicker initial layer makes adhesion to the build plate easier."
msgstr "Alkukerroksen korkeus milleinä. Paksumpi alkukerros helpottaa alustaan kiinnittymistä."
-#: fdmprinter.def.json
-msgctxt "slicing_tolerance label"
-msgid "Slicing Tolerance"
-msgstr ""
-
-#: fdmprinter.def.json
-msgctxt "slicing_tolerance description"
-msgid "How to slice layers with diagonal surfaces. The areas of a layer can be generated based on where the middle of the layer intersects the surface (Middle). Alternatively each layer can have the areas which fall inside of the volume throughout the height of the layer (Exclusive) or a layer has the areas which fall inside anywhere within the layer (Inclusive). Exclusive retains the most details, Inclusive makes for the best fit and Middle takes the least time to process."
-msgstr ""
-
-#: fdmprinter.def.json
-msgctxt "slicing_tolerance option middle"
-msgid "Middle"
-msgstr ""
-
-#: fdmprinter.def.json
-msgctxt "slicing_tolerance option exclusive"
-msgid "Exclusive"
-msgstr ""
-
-#: fdmprinter.def.json
-msgctxt "slicing_tolerance option inclusive"
-msgid "Inclusive"
-msgstr ""
-
#: fdmprinter.def.json
msgctxt "line_width label"
msgid "Line Width"
@@ -674,16 +659,6 @@ msgctxt "wall_line_width_x description"
msgid "Width of a single wall line for all wall lines except the outermost one."
msgstr "Yhden seinämälinjan leveys. Koskee kaikkia muita paitsi ulommaista seinämää."
-#: fdmprinter.def.json
-msgctxt "roofing_line_width label"
-msgid "Top Surface Skin Line Width"
-msgstr "Yläpinnan pintakalvon linjan leveys"
-
-#: fdmprinter.def.json
-msgctxt "roofing_line_width description"
-msgid "Width of a single line of the areas at the top of the print."
-msgstr "Tulosteen yläosan alueiden yhden linjan leveys."
-
#: fdmprinter.def.json
msgctxt "skin_line_width label"
msgid "Top/Bottom Line Width"
@@ -864,41 +839,6 @@ msgctxt "roofing_layer_count description"
msgid "The number of top most skin layers. Usually only one top most layer is sufficient to generate higher quality top surfaces."
msgstr "Ylimpien pintakalvokerrosten määrä. Yleensä vain yksi ylin kerros riittää tuottamaan korkeampilaatuisia yläpintoja."
-#: fdmprinter.def.json
-msgctxt "roofing_pattern label"
-msgid "Top Surface Skin Pattern"
-msgstr "Yläpinnan pintakalvokuvio"
-
-#: fdmprinter.def.json
-msgctxt "roofing_pattern description"
-msgid "The pattern of the top most layers."
-msgstr "Ylimpien kerrosten kuvio."
-
-#: fdmprinter.def.json
-msgctxt "roofing_pattern option lines"
-msgid "Lines"
-msgstr "Linjat"
-
-#: fdmprinter.def.json
-msgctxt "roofing_pattern option concentric"
-msgid "Concentric"
-msgstr "Samankeskinen"
-
-#: fdmprinter.def.json
-msgctxt "roofing_pattern option zigzag"
-msgid "Zig Zag"
-msgstr "Siksak"
-
-#: fdmprinter.def.json
-msgctxt "roofing_angles label"
-msgid "Top Surface Skin Line Directions"
-msgstr "Yläpinnan pintakalvon linjojen suunnat"
-
-#: fdmprinter.def.json
-msgctxt "roofing_angles description"
-msgid "A list of integer line directions to use when the top surface skin layers use the lines or zig zag pattern. 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 traditional default angles (45 and 135 degrees)."
-msgstr "Luettelo käytettävistä linjojen kokonaislukusuunnista, kun yläpinnan pintakalvokerroksilla käytetään linja- tai siksak-kuviota. Tämän luettelon elementtejä käytetään järjestyksessä kerrosten edetessä, ja kun luettelon loppu saavutetaan, aloitetaan taas alusta. Luettelon kohteet on erotettu pilkuilla, ja koko luettelo on hakasulkeiden sisällä. Oletusarvo on tyhjä luettelo, jolloin käytetään perinteisiä oletuskulmia (45 ja 135 astetta)."
-
#: fdmprinter.def.json
msgctxt "top_bottom_extruder_nr label"
msgid "Top/Bottom Extruder"
@@ -1029,6 +969,16 @@ msgctxt "wall_0_inset description"
msgid "Inset applied to the path of the outer wall. If the outer wall is smaller than the nozzle, and printed after the inner walls, use this offset to get the hole in the nozzle to overlap with the inner walls instead of the outside of the model."
msgstr "Ulkoseinämän reitille asetettu liitos. Jos ulkoseinämä on pienempi kuin suutin ja se tulostetaan sisäseinämien jälkeen, tällä siirtymällä saadaan suuttimen reikä limittymään sisäseinämiin mallin ulkopuolen sijaan."
+#: fdmprinter.def.json
+msgctxt "optimize_wall_printing_order label"
+msgid "Optimize Wall Printing Order"
+msgstr "Optimoi seinämien tulostusjärjestys"
+
+#: fdmprinter.def.json
+msgctxt "optimize_wall_printing_order description"
+msgid "Optimize the order in which walls are printed so as to reduce the number of retractions and the distance travelled. Most parts will benefit from this being enabled but some may actually take longer so please compare the print time estimates with and without optimization."
+msgstr "Optimoi seinämien tulostusjärjestys takaisinvetojen ja kuljetun etäisyyden vähentämiseksi. Useimmat osat hyötyvät tämän asetuksen käytöstä, mutta joissakin saattaa kestää kauemmin, joten vertaa tulostusajan arvioita optimointia käytettäessä ja ilman sitä."
+
#: fdmprinter.def.json
msgctxt "outer_inset_first label"
msgid "Outer Before Inner Walls"
@@ -1099,6 +1049,16 @@ msgctxt "fill_perimeter_gaps option everywhere"
msgid "Everywhere"
msgstr "Kaikkialla"
+#: fdmprinter.def.json
+msgctxt "filter_out_tiny_gaps label"
+msgid "Filter Out Tiny Gaps"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "filter_out_tiny_gaps description"
+msgid "Filter out tiny gaps to reduce blobs on outside of model."
+msgstr ""
+
#: fdmprinter.def.json
msgctxt "fill_outline_gaps label"
msgid "Print Thin Walls"
@@ -1481,7 +1441,7 @@ msgstr ""
#: fdmprinter.def.json
msgctxt "infill_offset_x description"
-msgid "The infill pattern is offset this distance along the X axis."
+msgid "The infill pattern is moved this distance along the X axis."
msgstr ""
#: fdmprinter.def.json
@@ -1491,7 +1451,7 @@ msgstr ""
#: fdmprinter.def.json
msgctxt "infill_offset_y description"
-msgid "The infill pattern is offset this distance along the Y axis."
+msgid "The infill pattern is moved this distance along the Y axis."
msgstr ""
#: fdmprinter.def.json
@@ -1511,8 +1471,8 @@ msgstr "Täytön limityksen prosentti"
#: fdmprinter.def.json
msgctxt "infill_overlap description"
-msgid "The amount of overlap between the infill and the walls. A slight overlap allows the walls to connect firmly to the infill."
-msgstr "Limityksen määrä täytön ja seinämien välillä. Pienellä limityksellä seinämät liittyvät tukevasti täyttöön."
+msgid "The amount of overlap between the infill and the walls as a percentage of the infill line width. A slight overlap allows the walls to connect firmly to the infill."
+msgstr ""
#: fdmprinter.def.json
msgctxt "infill_overlap_mm label"
@@ -1531,8 +1491,8 @@ 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 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 "Limityksen määrä pintakalvon ja seinämien välillä linjaleveyden prosenttina. Pienellä limityksellä seinämät liittyvät tukevasti pintakalvoon. Tämä on pintakalvon linjojen ja sisimmän seinämän keskimääräisten linjaleveyksien prosenttiluku."
+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 ""
#: fdmprinter.def.json
msgctxt "skin_overlap_mm label"
@@ -1694,16 +1654,6 @@ msgctxt "material description"
msgid "Material"
msgstr "Materiaali"
-#: fdmprinter.def.json
-msgctxt "material_flow_dependent_temperature label"
-msgid "Auto Temperature"
-msgstr "Automaattinen lämpötila"
-
-#: fdmprinter.def.json
-msgctxt "material_flow_dependent_temperature description"
-msgid "Change the temperature for each layer automatically with the average flow speed of that layer."
-msgstr "Muuta kunkin kerroksen lämpötilaa automaattisesti kyseisen kerroksen keskimääräisen virtausnopeuden mukaan."
-
#: fdmprinter.def.json
msgctxt "default_material_print_temperature label"
msgid "Default Printing Temperature"
@@ -1754,16 +1704,6 @@ msgctxt "material_final_print_temperature description"
msgid "The temperature to which to already start cooling down just before the end of printing."
msgstr "Lämpötila, johon jäähdytetään jo ennen tulostuksen loppumista."
-#: fdmprinter.def.json
-msgctxt "material_flow_temp_graph label"
-msgid "Flow Temperature Graph"
-msgstr "Virtauksen lämpötilakaavio"
-
-#: fdmprinter.def.json
-msgctxt "material_flow_temp_graph description"
-msgid "Data linking material flow (in mm3 per second) to temperature (degrees Celsius)."
-msgstr "Tiedot, jotka yhdistävät materiaalivirran (mm3 sekunnissa) lämpötilaan (celsiusastetta)."
-
#: fdmprinter.def.json
msgctxt "material_extrusion_cool_down_speed label"
msgid "Extrusion Cool Down Speed Modifier"
@@ -1781,8 +1721,8 @@ msgstr "Alustan lämpötila"
#: fdmprinter.def.json
msgctxt "material_bed_temperature description"
-msgid "The temperature used for the heated build plate. If this is 0, the bed will not heat up for this print."
-msgstr "Lämmitettävän alustan lämpötila. Jos tämä on 0, pöytä ei lämpene tätä tulostusta varten."
+msgid "The temperature used for the heated build plate. If this is 0, the bed temperature will not be adjusted."
+msgstr ""
#: fdmprinter.def.json
msgctxt "material_bed_temperature_layer_0 label"
@@ -3454,6 +3394,16 @@ msgctxt "support_tower_roof_angle description"
msgid "The angle of a rooftop of a tower. A higher value results in pointed tower roofs, a lower value results in flattened tower roofs."
msgstr "Tornin katon kulma. Korkeampi arvo johtaa teräväkärkisiin tornien kattoihin, matalampi arvo litteämpiin tornien kattoihin."
+#: fdmprinter.def.json
+msgctxt "support_mesh_drop_down label"
+msgid "Drop Down Support Mesh"
+msgstr "Tukiverkon pudottaminen alaspäin"
+
+#: fdmprinter.def.json
+msgctxt "support_mesh_drop_down description"
+msgid "Make support everywhere below the support mesh, so that there's no overhang in the support mesh."
+msgstr "Muodosta tukea kaikkialle tukiverkon alla, niin ettei tukiverkossa ole ulokkeita."
+
#: fdmprinter.def.json
msgctxt "platform_adhesion label"
msgid "Build Plate Adhesion"
@@ -4086,16 +4036,6 @@ msgctxt "meshfix_keep_open_polygons description"
msgid "Normally Cura tries to stitch up small holes in the mesh and remove parts of a layer with big holes. Enabling this option keeps those parts which cannot be stitched. This option should be used as a last resort option when everything else fails to produce proper GCode."
msgstr "Normaalisti Cura yrittää silmukoida umpeen pieniä reikiä verkosta ja poistaa kerroksesta osat, joissa on isoja reikiä. Tämän vaihtoehdon käyttöönotto pitää ne osat, joita ei voida silmukoida. Tätä tulisi pitää viimeisenä vaihtoehtona, kun millään muulla ei saada aikaan kunnollista GCodea."
-#: fdmprinter.def.json
-msgctxt "meshfix_maximum_resolution label"
-msgid "Maximum Resolution"
-msgstr ""
-
-#: fdmprinter.def.json
-msgctxt "meshfix_maximum_resolution description"
-msgid "The minimum size of a line segment after slicing. If you increase this, the mesh will have a lower resolution. This may allow the printer to keep up with the speed it has to process g-code and will increase slice speed by removing details of the mesh that it can't process anyway."
-msgstr ""
-
#: fdmprinter.def.json
msgctxt "multiple_mesh_overlap label"
msgid "Merged Meshes Overlap"
@@ -4246,16 +4186,6 @@ msgctxt "support_mesh description"
msgid "Use this mesh to specify support areas. This can be used to generate support structure."
msgstr "Käytä tätä verkkoa tukialueiden valintaan. Sen avulla voidaan luoda tukirakenne."
-#: fdmprinter.def.json
-msgctxt "support_mesh_drop_down label"
-msgid "Drop Down Support Mesh"
-msgstr "Tukiverkon pudottaminen alaspäin"
-
-#: fdmprinter.def.json
-msgctxt "support_mesh_drop_down description"
-msgid "Make support everywhere below the support mesh, so that there's no overhang in the support mesh."
-msgstr "Muodosta tukea kaikkialle tukiverkon alla, niin ettei tukiverkossa ole ulokkeita."
-
#: fdmprinter.def.json
msgctxt "anti_overhang_mesh label"
msgid "Anti Overhang Mesh"
@@ -4332,14 +4262,194 @@ msgid "experimental!"
msgstr "kokeellinen!"
#: fdmprinter.def.json
-msgctxt "optimize_wall_printing_order label"
-msgid "Optimize Wall Printing Order"
-msgstr "Optimoi seinämien tulostusjärjestys"
+msgctxt "support_tree_enable label"
+msgid "Tree Support"
+msgstr ""
#: fdmprinter.def.json
-msgctxt "optimize_wall_printing_order description"
-msgid "Optimize the order in which walls are printed so as to reduce the number of retractions and the distance travelled. Most parts will benefit from this being enabled but some may actually take longer so please compare the print time estimates with and without optimization."
-msgstr "Optimoi seinämien tulostusjärjestys takaisinvetojen ja kuljetun etäisyyden vähentämiseksi. Useimmat osat hyötyvät tämän asetuksen käytöstä, mutta joissakin saattaa kestää kauemmin, joten vertaa tulostusajan arvioita optimointia käytettäessä ja ilman sitä."
+msgctxt "support_tree_enable description"
+msgid "Generate a tree-like support with branches that support your print. This may reduce material usage and print time, but greatly increases slicing time."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "support_tree_angle label"
+msgid "Tree Support Branch Angle"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "support_tree_angle description"
+msgid "The angle of the branches. Use a lower angle to make them more vertical and more stable. Use a higher angle to be able to have more reach."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "support_tree_branch_distance label"
+msgid "Tree Support Branch Distance"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "support_tree_branch_distance description"
+msgid "How far apart the branches need to be when they touch the model. Making this distance small will cause the tree support to touch the model at more points, causing better overhang but making support harder to remove."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "support_tree_branch_diameter label"
+msgid "Tree Support Branch Diameter"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "support_tree_branch_diameter description"
+msgid "The diameter of the thinnest branches of tree support. Thicker branches are more sturdy. Branches towards the base will be thicker than this."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "support_tree_branch_diameter_angle label"
+msgid "Tree Support Branch Diameter Angle"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "support_tree_branch_diameter_angle description"
+msgid "The angle of the branches' diameter as they gradually become thicker towards the bottom. An angle of 0 will cause the branches to have uniform thickness over their length. A bit of an angle can increase stability of the tree support."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "support_tree_collision_resolution label"
+msgid "Tree Support Collision Resolution"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "support_tree_collision_resolution description"
+msgid "Resolution to compute collisions with to avoid hitting the model. Setting this lower will produce more accurate trees that fail less often, but increases slicing time dramatically."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "support_tree_wall_thickness label"
+msgid "Tree Support Wall Thickness"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "support_tree_wall_thickness description"
+msgid "The thickness of the walls of the branches of tree support. Thicker walls take longer to print but don't fall over as easily."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "support_tree_wall_count label"
+msgid "Tree Support Wall Line Count"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "support_tree_wall_count description"
+msgid "The number of walls of the branches of tree support. Thicker walls take longer to print but don't fall over as easily."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "slicing_tolerance label"
+msgid "Slicing Tolerance"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "slicing_tolerance description"
+msgid "How to slice layers with diagonal surfaces. The areas of a layer can be generated based on where the middle of the layer intersects the surface (Middle). Alternatively each layer can have the areas which fall inside of the volume throughout the height of the layer (Exclusive) or a layer has the areas which fall inside anywhere within the layer (Inclusive). Exclusive retains the most details, Inclusive makes for the best fit and Middle takes the least time to process."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "slicing_tolerance option middle"
+msgid "Middle"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "slicing_tolerance option exclusive"
+msgid "Exclusive"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "slicing_tolerance option inclusive"
+msgid "Inclusive"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "roofing_line_width label"
+msgid "Top Surface Skin Line Width"
+msgstr "Yläpinnan pintakalvon linjan leveys"
+
+#: fdmprinter.def.json
+msgctxt "roofing_line_width description"
+msgid "Width of a single line of the areas at the top of the print."
+msgstr "Tulosteen yläosan alueiden yhden linjan leveys."
+
+#: fdmprinter.def.json
+msgctxt "roofing_pattern label"
+msgid "Top Surface Skin Pattern"
+msgstr "Yläpinnan pintakalvokuvio"
+
+#: fdmprinter.def.json
+msgctxt "roofing_pattern description"
+msgid "The pattern of the top most layers."
+msgstr "Ylimpien kerrosten kuvio."
+
+#: fdmprinter.def.json
+msgctxt "roofing_pattern option lines"
+msgid "Lines"
+msgstr "Linjat"
+
+#: fdmprinter.def.json
+msgctxt "roofing_pattern option concentric"
+msgid "Concentric"
+msgstr "Samankeskinen"
+
+#: fdmprinter.def.json
+msgctxt "roofing_pattern option zigzag"
+msgid "Zig Zag"
+msgstr "Siksak"
+
+#: fdmprinter.def.json
+msgctxt "roofing_angles label"
+msgid "Top Surface Skin Line Directions"
+msgstr "Yläpinnan pintakalvon linjojen suunnat"
+
+#: fdmprinter.def.json
+msgctxt "roofing_angles description"
+msgid "A list of integer line directions to use when the top surface skin layers use the lines or zig zag pattern. 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 traditional default angles (45 and 135 degrees)."
+msgstr "Luettelo käytettävistä linjojen kokonaislukusuunnista, kun yläpinnan pintakalvokerroksilla käytetään linja- tai siksak-kuviota. Tämän luettelon elementtejä käytetään järjestyksessä kerrosten edetessä, ja kun luettelon loppu saavutetaan, aloitetaan taas alusta. Luettelon kohteet on erotettu pilkuilla, ja koko luettelo on hakasulkeiden sisällä. Oletusarvo on tyhjä luettelo, jolloin käytetään perinteisiä oletuskulmia (45 ja 135 astetta)."
+
+#: fdmprinter.def.json
+msgctxt "infill_enable_travel_optimization label"
+msgid "Infill Travel Optimization"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "infill_enable_travel_optimization description"
+msgid "When enabled, the order in which the infill lines are printed is optimized to reduce the distance travelled. The reduction in travel time achieved very much depends on the model being sliced, infill pattern, density, etc. Note that, for some models that have many small areas of infill, the time to slice the model may be greatly increased."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "material_flow_dependent_temperature label"
+msgid "Auto Temperature"
+msgstr "Automaattinen lämpötila"
+
+#: fdmprinter.def.json
+msgctxt "material_flow_dependent_temperature description"
+msgid "Change the temperature for each layer automatically with the average flow speed of that layer."
+msgstr "Muuta kunkin kerroksen lämpötilaa automaattisesti kyseisen kerroksen keskimääräisen virtausnopeuden mukaan."
+
+#: fdmprinter.def.json
+msgctxt "material_flow_temp_graph label"
+msgid "Flow Temperature Graph"
+msgstr "Virtauksen lämpötilakaavio"
+
+#: fdmprinter.def.json
+msgctxt "material_flow_temp_graph description"
+msgid "Data linking material flow (in mm3 per second) to temperature (degrees Celsius)."
+msgstr "Tiedot, jotka yhdistävät materiaalivirran (mm3 sekunnissa) lämpötilaan (celsiusastetta)."
+
+#: fdmprinter.def.json
+msgctxt "meshfix_maximum_resolution label"
+msgid "Maximum Resolution"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "meshfix_maximum_resolution description"
+msgid "The minimum size of a line segment after slicing. If you increase this, the mesh will have a lower resolution. This may allow the printer to keep up with the speed it has to process g-code and will increase slice speed by removing details of the mesh that it can't process anyway."
+msgstr ""
#: fdmprinter.def.json
msgctxt "support_skip_some_zags label"
@@ -4940,6 +5050,46 @@ msgctxt "wireframe_nozzle_clearance description"
msgid "Distance between the nozzle and horizontally downward lines. Larger clearance results in diagonally downward lines with a less steep angle, which in turn results in less upward connections with the next layer. Only applies to Wire Printing."
msgstr "Suuttimen ja vaakasuoraan laskevien linjojen välinen etäisyys. Suurempi väli aiheuttaa vähemmän jyrkän kulman diagonaalisesti laskeviin linjoihin, mikä puolestaan johtaa harvempiin yläliitoksiin seuraavan kerroksen kanssa. Koskee vain rautalankamallin tulostusta."
+#: fdmprinter.def.json
+msgctxt "adaptive_layer_height_enabled label"
+msgid "Use adaptive layers"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "adaptive_layer_height_enabled description"
+msgid "Adaptive layers computes the layer heights depending on the shape of the model."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "adaptive_layer_height_variation label"
+msgid "Adaptive layers maximum variation"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "adaptive_layer_height_variation description"
+msgid "The maximum allowed height different from the base layer height in mm."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "adaptive_layer_height_variation_step label"
+msgid "Adaptive layers variation step size"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "adaptive_layer_height_variation_step description"
+msgid "The difference in height of the next layer height compared to the previous one."
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "adaptive_layer_height_threshold label"
+msgid "Adaptive layers threshold"
+msgstr ""
+
+#: fdmprinter.def.json
+msgctxt "adaptive_layer_height_threshold description"
+msgid "Threshold whether to use a smaller layer or not. This number is compared to the tan of the steepest slope in a layer."
+msgstr ""
+
#: fdmprinter.def.json
msgctxt "command_line_settings label"
msgid "Command Line Settings"
@@ -5000,6 +5150,18 @@ 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 "infill_overlap description"
+#~ msgid "The amount of overlap between the infill and the walls. A slight overlap allows the walls to connect firmly to the infill."
+#~ msgstr "Limityksen määrä täytön ja seinämien välillä. Pienellä limityksellä seinämät liittyvät tukevasti täyttöön."
+
+#~ msgctxt "skin_overlap description"
+#~ msgid "The amount of overlap between the skin and the walls as a percentage of the 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 "Limityksen määrä pintakalvon ja seinämien välillä linjaleveyden prosenttina. Pienellä limityksellä seinämät liittyvät tukevasti pintakalvoon. Tämä on pintakalvon linjojen ja sisimmän seinämän keskimääräisten linjaleveyksien prosenttiluku."
+
+#~ msgctxt "material_bed_temperature description"
+#~ msgid "The temperature used for the heated build plate. If this is 0, the bed will not heat up for this print."
+#~ msgstr "Lämmitettävän alustan lämpötila. Jos tämä on 0, pöytä ei lämpene tätä tulostusta varten."
+
#~ msgctxt "wall_x_extruder_nr label"
#~ msgid "Inner Walls Extruder"
#~ msgstr "Sisäseinämien suulake"
diff --git a/resources/i18n/fr_FR/cura.po b/resources/i18n/fr_FR/cura.po
index 4db845190f..ee4e175f8a 100644
--- a/resources/i18n/fr_FR/cura.po
+++ b/resources/i18n/fr_FR/cura.po
@@ -1,22 +1,24 @@
# Cura
-# Copyright (C) 2017 Ultimaker
+# Copyright (C) 2018 Ultimaker
# This file is distributed under the same license as the Cura package.
-# Ruben Dulek , 2017.
-#
+# Ruben Dulek , 2018.
+#
msgid ""
msgstr ""
-"Project-Id-Version: Cura 3.0\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2017-11-21 16:58+0100\n"
-"PO-Revision-Date: 2017-11-30 13:05+0100\n"
+"Project-Id-Version: Cura 3.2\n"
+"Report-Msgid-Bugs-To: r.dulek@ultimaker.com\n"
+"POT-Creation-Date: 2018-01-29 09:48+0000\n"
+"PO-Revision-Date: 2018-02-13 17:26+0100\n"
"Last-Translator: Bothof \n"
"Language-Team: 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"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.py:29
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.py:26
msgctxt "@action"
msgid "Machine Settings"
msgstr "Paramètres de la machine"
@@ -53,12 +55,11 @@ msgstr "Connexion avec Doodle3D Connecter..."
#: /home/ruben/Projects/Cura/plugins/Doodle3D-cura-plugin/Doodle3D/D3DCloudPrintOutputDevicePlugin.py:87
#: /home/ruben/Projects/Cura/plugins/Doodle3D-cura-plugin/Doodle3D/D3DCloudPrintOutputDevicePlugin.py:155
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:874
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:646
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:875
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:659
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/DiscoverUM3Action.qml:370
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/PrintWindow.qml:78
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/ConfigDialog.qml:104
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/ExportSTLUI.qml:99
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:355
#: /home/ruben/Projects/Cura/plugins/ImageReader/ConfigUI.qml:188
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:376
#: /home/ruben/Projects/Cura/plugins/PluginBrowser/PluginBrowser.qml:139
@@ -98,7 +99,7 @@ msgctxt "@info:tooltip"
msgid "Open the Doodle3D Connect web interface"
msgstr "Ouvrir l'interface web Doodle3D Connecter"
-#: /home/ruben/Projects/Cura/plugins/ChangeLogPlugin/ChangeLog.py:34
+#: /home/ruben/Projects/Cura/plugins/ChangeLogPlugin/ChangeLog.py:33
msgctxt "@item:inmenu"
msgid "Show Changelog"
msgstr "Afficher le récapitulatif des changements"
@@ -106,85 +107,90 @@ msgstr "Afficher le récapitulatif des changements"
#: /home/ruben/Projects/Cura/plugins/ProfileFlattener/ProfileFlattener.py:20
msgctxt "@item:inmenu"
msgid "Flatten active settings"
-msgstr "Aplatir les paramètres actifs"
+msgstr "Réduire les paramètres actifs"
#: /home/ruben/Projects/Cura/plugins/ProfileFlattener/ProfileFlattener.py:32
msgctxt "@info:status"
msgid "Profile has been flattened & activated."
-msgstr "Le profil a été aplati et activé."
+msgstr "Le profil a été réduit et activé."
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:26
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:27
msgctxt "@item:inmenu"
msgid "USB printing"
msgstr "Impression par USB"
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:27
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:28
msgctxt "@action:button Preceded by 'Ready to'."
msgid "Print via USB"
msgstr "Imprimer via USB"
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:28
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:29
msgctxt "@info:tooltip"
msgid "Print via USB"
msgstr "Imprimer via USB"
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:30
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:31
msgctxt "@info:status"
msgid "Connected via USB"
msgstr "Connecté via USB"
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:154
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:183
msgctxt "@info:status"
msgid "Unable to start a new job because the printer is busy or not connected."
msgstr "Impossible de démarrer une nouvelle tâche car l'imprimante est occupée ou n'est pas connectée."
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:154
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:183
msgctxt "@info:title"
msgid "Printer Unavailable"
msgstr "Imprimante indisponible"
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:457
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:485
msgctxt "@info:status"
msgid "This printer does not support USB printing because it uses UltiGCode flavor."
-msgstr "L'imprimante ne prend pas en charge l'impression par USB car elle utilise UltiGCode parfum."
+msgstr "L'imprimante ne prend pas en charge l'impression par USB car elle utilise UltiGCode."
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:457
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:485
msgctxt "@info:title"
msgid "USB Printing"
msgstr "Impression par USB"
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:461
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:489
msgctxt "@info:status"
msgid "Unable to start a new job because the printer does not support usb printing."
msgstr "Impossible de démarrer une nouvelle tâche car l'imprimante ne prend pas en charge l'impression par USB."
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:461
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDeviceManager.py:108
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:489
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDeviceManager.py:103
#: /home/ruben/Projects/Cura/plugins/RemovableDriveOutputDevice/RemovableDriveOutputDevice.py:146
#: /home/ruben/Projects/Cura/plugins/RemovableDriveOutputDevice/RemovableDriveOutputDevice.py:158
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:945
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1349
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1417
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:946
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1418
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1496
msgctxt "@info:title"
msgid "Warning"
msgstr "Avertissement"
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDeviceManager.py:108
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDeviceManager.py:103
msgctxt "@info"
msgid "Unable to update firmware because there are no printers connected."
msgstr "Impossible de mettre à jour le firmware car il n'y a aucune imprimante connectée."
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDeviceManager.py:122
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDeviceManager.py:117
#, python-format
msgctxt "@info"
msgid "Could not find firmware required for the printer at %s."
msgstr "Impossible de trouver le firmware requis pour l'imprimante sur %s."
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDeviceManager.py:122
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDeviceManager.py:117
msgctxt "@info:title"
msgid "Printer Firmware"
msgstr "Firmware de l'imprimante"
+#: /home/ruben/Projects/Cura/plugins/PrepareStage/__init__.py:12
+msgctxt "@item:inmenu"
+msgid "Prepare"
+msgstr "Préparer"
+
#: /home/ruben/Projects/Cura/plugins/RemovableDriveOutputDevice/RemovableDriveOutputDevice.py:23
msgctxt "@action:button Preceded by 'Ready to'."
msgid "Save to Removable Drive"
@@ -205,7 +211,7 @@ msgstr "Enregistrement sur le lecteur amovible {0}"
#: /home/ruben/Projects/Cura/plugins/RemovableDriveOutputDevice/RemovableDriveOutputDevice.py:89
msgctxt "@info:title"
msgid "Saving"
-msgstr "Enregistrement..."
+msgstr "Enregistrement"
#: /home/ruben/Projects/Cura/plugins/RemovableDriveOutputDevice/RemovableDriveOutputDevice.py:99
#: /home/ruben/Projects/Cura/plugins/RemovableDriveOutputDevice/RemovableDriveOutputDevice.py:102
@@ -228,11 +234,11 @@ 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:132
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:692
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:700
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:146
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:693
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:701
#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:153
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1358
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:160
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1427
msgctxt "@info:title"
msgid "Error"
msgstr "Erreur"
@@ -263,7 +269,7 @@ msgstr "Ejecter le lecteur amovible {0}"
#, python-brace-format
msgctxt "@info:status"
msgid "Ejected {0}. You can now safely remove the drive."
-msgstr "Lecteur {0} éjecté. Vous pouvez maintenant le retirer en tout sécurité."
+msgstr "Lecteur {0} éjecté. Vous pouvez maintenant le retirer en toute sécurité."
#: /home/ruben/Projects/Cura/plugins/RemovableDriveOutputDevice/RemovableDriveOutputDevice.py:156
msgctxt "@info:title"
@@ -282,7 +288,7 @@ msgid "Removable Drive"
msgstr "Lecteur amovible"
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:109
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:53
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:51
msgctxt "@action:button Preceded by 'Ready to'."
msgid "Print over network"
msgstr "Imprimer sur le réseau"
@@ -368,22 +374,22 @@ msgstr "Connecté sur le réseau. Pas d'accès pour commander l'imprimante."
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:410
msgctxt "@info:status"
msgid "Access request was denied on the printer."
-msgstr "La demande d'accès a été refusée sur l'imprimante."
+msgstr "La demande d'accès à l'imprimante a été refusée."
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:413
msgctxt "@info:status"
msgid "Access request failed due to a timeout."
-msgstr "Échec de la demande d'accès à cause de la durée limite."
+msgstr "Durée d'attente dépassée. Échec de la demande d'accès."
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:478
msgctxt "@info:status"
msgid "The connection with the network was lost."
-msgstr "La connexion avec le réseau a été perdue."
+msgstr "Interruption de connexion au le réseau."
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:501
msgctxt "@info:status"
msgid "The connection with the printer was lost. Check your printer to see if it is connected."
-msgstr "La connexion avec l'imprimante a été perdue. Vérifiez que votre imprimante est connectée."
+msgstr "La connexion avec l'imprimante est interrompue. Vérifiez que votre imprimante est connectée."
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:666
#, python-format
@@ -396,113 +402,113 @@ msgctxt "@info:title"
msgid "Printer Status"
msgstr "Statut de l'imprimante"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:691
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:692
#, python-brace-format
msgctxt "@info:status"
msgid "Unable to start a new print job. No Printcore loaded in slot {0}"
msgstr "Impossible de démarrer une nouvelle tâche d'impression. Pas de PrintCore inséré dans la fente {0}."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:699
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:700
#, python-brace-format
msgctxt "@info:status"
msgid "Unable to start a new print job. No material loaded in slot {0}"
msgstr "Impossible de démarrer une nouvelle tâche d'impression car l'imprimante est occupée. Pas de matériau chargé dans la fente {0}."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:709
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:710
#, python-brace-format
msgctxt "@label"
msgid "Not enough material for spool {0}."
-msgstr "Pas suffisamment de matériau pour bobine {0}."
+msgstr "Pas suffisamment de matériau pour la bobine {0}."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:719
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:720
#, python-brace-format
msgctxt "@label"
msgid "Different PrintCore (Cura: {0}, Printer: {1}) selected for extruder {2}"
-msgstr "PrintCore différent (Cura : {0}, Imprimante : {1}) sélectionné pour l'extrudeuse {2}"
+msgstr "PrintCore différent (Cura : {0}, Imprimante : {1}) sélectionné pour l'extrudeur {2}"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:733
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:734
#, 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}"
+msgstr "Matériau différent (Cura : {0}, Imprimante : {1}) sélectionné pour l'extrudeur {2}"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:741
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:742
#, python-brace-format
msgctxt "@label"
msgid "PrintCore {0} is not properly calibrated. XY calibration needs to be performed on the printer."
msgstr "Le PrintCore {0} n'est pas correctement calibré. Le calibrage XY doit être effectué sur l'imprimante."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:746
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:747
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/NetworkPrinterOutputDevice.py:747
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:748
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."
+msgstr "Problème de compatibilité entre la configuration ou la calibration de l'imprimante et Cura. Pour un résultat optimal, découpez toujours les PrintCores et matériaux insérés dans votre imprimante."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:753
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:754
msgctxt "@window:title"
msgid "Mismatched configuration"
msgstr "Configuration différente"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:864
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:262
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:865
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:258
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/NetworkPrinterOutputDevice.py:873
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:874
msgctxt "@info:status"
msgid "Sending data to printer"
msgstr "Envoi des données à l'imprimante"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:873
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:874
msgctxt "@info:title"
msgid "Sending Data"
-msgstr "Envoi des données..."
+msgstr "Envoi des données"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:944
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:945
msgctxt "@info:status"
msgid "Unable to send data to printer. Is another job still active?"
msgstr "Impossible d'envoyer les données à l'imprimante. Une autre tâche est-elle toujours active ?"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:1085
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:1087
#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:196
msgctxt "@label:MonitorStatus"
msgid "Aborting print..."
msgstr "Abandon de l'impression..."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:1091
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:1093
msgctxt "@label:MonitorStatus"
msgid "Print aborted. Please check the printer"
msgstr "Abandon de l'impression. Vérifiez l'imprimante"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:1097
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:1099
msgctxt "@label:MonitorStatus"
msgid "Pausing print..."
msgstr "Mise en pause de l'impression..."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:1099
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:1101
msgctxt "@label:MonitorStatus"
msgid "Resuming print..."
msgstr "Reprise de l'impression..."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:1289
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:1291
msgctxt "@window:title"
msgid "Sync with your printer"
msgstr "Synchroniser avec votre imprimante"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:1291
-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/NetworkPrinterOutputDevice.py:1293
msgctxt "@label"
+msgid "Would you like to use your current printer configuration in Cura?"
+msgstr "Voulez-vous utiliser votre configuration actuelle d'imprimante dans Cura ?"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:1295
+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."
+msgstr "Les PrintCores et / ou les matériaux sur votre imprimante sont différents de ceux de votre projet actuel. Pour un résultat optimal, découpez toujours les PrintCores et matériaux insérés dans votre imprimante."
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:112
msgid "This printer is not set up to host a group of connected Ultimaker 3 printers."
@@ -517,164 +523,252 @@ msgstr "L'imprimante n'est pas configurée pour héberger un groupe de {count} i
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:114
#, python-brace-format
msgid "{printer_name} has finished printing '{job_name}'. Please collect the print and confirm clearing the build plate."
-msgstr "{printer_name} a terminé d'imprimer '{job_name}'. Veuillez enlever l'impression et confirmer avoir débarrassé le plateau."
+msgstr "{printer_name} a terminé d'imprimer '{job_name}'. Veuillez enlever l'impression et confirmer avoir nettoyé le plateau."
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:115
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:520
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:533
#, python-brace-format
msgid "{printer_name} is reserved to print '{job_name}'. Please change the printer's configuration to match the job, for it to start printing."
msgstr "{printer_name} est réservé pour imprimer '{job_name}'. Veuillez modifier la configuration de l'imprimante pour qu'elle corresponde à la tâche et commence l'impression."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:278
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:277
msgctxt "@info:status"
msgid "Unable to send new print job: this 3D printer is not (yet) set up to host a group of connected Ultimaker 3 printers."
msgstr "Impossible d'envoyer une nouvelle tâche d'impression : cette imprimante 3D n'est pas (encore) configurée pour héberger un groupe d'imprimantes connectées Ultimaker 3."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:410
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:423
#, python-brace-format
msgctxt "@info:status"
msgid "Unable to send print job to group {cluster_name}."
msgstr "Impossible d'envoyer la tâche d'impression vers le groupe {cluster_name}."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:418
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:431
#, python-brace-format
msgctxt "@info:status"
msgid "Sent {file_name} to group {cluster_name}."
msgstr "{file_name} envoyé vers le groupe {cluster_name}."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:423
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:436
msgctxt "@action:button"
msgid "Show print jobs"
msgstr "Afficher les tâches d'impression"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:424
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:437
msgctxt "@info:tooltip"
msgid "Opens the print jobs interface in your browser."
msgstr "Ouvre l'interface d'impression des tâches dans votre navigateur."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:489
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:502
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/DiscoverUM3Action.qml:239
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/PrinterInfoBlock.qml:47
-msgctxt "@label"
+msgctxt "@label Printer name"
msgid "Unknown"
msgstr "Inconnu"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:492
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:505
#, 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/NetworkClusterPrinterOutputDevice.py:494
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:497
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:507
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:510
msgctxt "@info:status"
msgid "Print finished"
msgstr "Impression terminée"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:522
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:525
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:535
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:538
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/PrinterInfoBlock.qml:282
msgctxt "@label:status"
msgid "Action required"
msgstr "Action requise"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:643
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:656
#, python-brace-format
msgctxt "@info:progress"
msgid "Sending {file_name} to group {cluster_name}"
msgstr "Envoi de {file_name} vers le groupe {cluster_name}..."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/DiscoverUM3Action.py:19
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/DiscoverUM3Action.py:17
msgctxt "@action"
msgid "Connect via Network"
msgstr "Connecter via le réseau"
-#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py:64
+#: /home/ruben/Projects/Cura/plugins/MonitorStage/__init__.py:12
+msgctxt "@item:inmenu"
+msgid "Monitor"
+msgstr "Surveiller"
+
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py:66
#, 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."
+msgstr "De nouvelles fonctionnalités sont disponibles pour votre {machine_name} ! Il est recommandé de mettre à jour le firmware de votre imprimante."
-#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py:65
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py:67
#, 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:66
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py:68
msgctxt "@action:button"
msgid "How to update"
msgstr "Comment effectuer la mise à jour"
-#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py:77
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py:79
msgctxt "@info"
msgid "Could not access update information."
msgstr "Impossible d'accéder aux informations de mise à jour."
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksReader.py:199
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksReader.py:579
msgctxt "@info:status"
-msgid "Errors appeared while opening your SolidWorks file! Please check, whether it is possible to open your file in SolidWorks itself without any problems as well!"
-msgstr "Des erreurs sont apparues lors de l'ouverture de votre fichier SolidWorks ! Veuillez vérifier s'il est possible d'ouvrir votre fichier dans SolidWorks sans que cela ne cause de problèmes."
+msgid "SolidWorks reported errors, while opening your file. We recommend to solve these issues inside SolidWorks itself."
+msgstr "SolidWorks a signalé des erreurs lors de l'ouverture de votre fichier. Nous vous recommandons de résoudre ces problèmes dans SolidWorks lui-même."
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/__init__.py:31
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksReader.py:591
+msgctxt "@info:status"
+msgid ""
+"Found no models inside your drawing. Could you please check it's content again and make sure one part or assembly is inside?\n"
+"\n"
+" Thanks!."
+msgstr ""
+"Aucun modèle n'a été trouvé à l'intérieur de votre dessin. Pouvez-vous vérifier son contenu de nouveau et vous assurer qu'une pièce ou un assemblage est présent ?\n"
+"\n"
+" Merci !"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksReader.py:595
+msgctxt "@info:status"
+msgid ""
+"Found more then one part or assembly inside your drawing. We currently only support drawings with exactly one part or assembly inside.\n"
+"\n"
+"Sorry!"
+msgstr ""
+"Plus d'une pièce ou d'un ensemble de pièces ont été trouvés dans votre dessin. Nous ne prenons actuellement en charge que les dessins comptant exactement une pièce ou un ensemble de pièces.\n"
+"\n"
+"Désolé !"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/__init__.py:25
msgctxt "@item:inlistbox"
msgid "SolidWorks part file"
msgstr "Fichier de composant SolidWorks"
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/__init__.py:35
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/__init__.py:29
msgctxt "@item:inlistbox"
msgid "SolidWorks assembly file"
msgstr "Fichier d'assemblage SolidWorks"
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/ConfigDialog.py:21
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/__init__.py:33
+msgctxt "@item:inlistbox"
+msgid "SolidWorks drawing file"
+msgstr "Fichier de dessin SolidWorks"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/__init__.py:48
+msgctxt "@info:status"
+msgid ""
+"Dear customer,\n"
+"We could not find a valid installation of SolidWorks on your system. That means that either SolidWorks is not installed or you don't own an valid license. Please make sure that running SolidWorks itself works without issues and/or contact your ICT.\n"
+"\n"
+"With kind regards\n"
+" - Thomas Karl Pietrowski"
+msgstr ""
+"Cher client,\n"
+"Nous n'avons pas pu trouver une installation valide de SolidWorks sur votre système. Cela signifie soit que SolidWorks n'est pas installé, soit que vous ne possédez pas de licence valide. Veuillez vous assurer que l'exécution de SolidWorks lui-même fonctionne sans problèmes et / ou contactez votre service IT.\n"
+"\n"
+"Cordialement,\n"
+" - Thomas Karl Pietrowski"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/__init__.py:57
+msgctxt "@info:status"
+msgid ""
+"Dear customer,\n"
+"You are currently running this plugin on an operating system other than Windows. This plugin will only work on Windows with SolidWorks installed, including an valid license. Please install this plugin on a Windows machine with SolidWorks installed.\n"
+"\n"
+"With kind regards\n"
+" - Thomas Karl Pietrowski"
+msgstr ""
+"Cher client,\n"
+"Vous exécutez actuellement ce plug-in sur un système d'exploitation autre que Windows. Ce plug-in fonctionne uniquement sous Windows et lorsque SolidWorks est installé avec une licence valide. Veuillez installer ce plug-in sur un poste Windows où SolidWorks est installé.\n"
+"\n"
+"Cordialement,\n"
+" - Thomas Karl Pietrowski"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksDialogHandler.py:70
msgid "Configure"
msgstr "Configurer"
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/CommonComReader.py:135
-#, python-format
-msgctxt "@info:status"
-msgid "Error while starting %s!"
-msgstr "Erreur lors du lancement de %s !"
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksDialogHandler.py:71
+msgid "Installation guide for SolidWorks macro"
+msgstr "Guide d'installation SolidWorks macro"
#: /home/ruben/Projects/Cura/plugins/SimulationView/__init__.py:14
msgctxt "@item:inlistbox"
-msgid "Simulation view"
-msgstr "Vue simulation"
+msgid "Layer view"
+msgstr "Vue en couches"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.py:100
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.py:103
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:101
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.py:104
msgctxt "@info:title"
msgid "Simulation View"
msgstr "Vue simulation"
-#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.py:26
+#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.py:25
msgid "Modify G-Code"
msgstr "Modifier le G-Code"
#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/SliceInfo.py:43
msgctxt "@info"
-msgid "Cura collects anonymised slicing statistics. You can disable this in the preferences."
-msgstr "Cura collecte des statistiques anonymes sur le découpage. Vous pouvez désactiver cette fonctionnalité dans les préférences."
+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..."
+msgstr "Collecte de données"
#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/SliceInfo.py:48
msgctxt "@action:button"
-msgid "Dismiss"
-msgstr "Ignorer"
+msgid "Allow"
+msgstr "Autoriser"
+
+#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/SliceInfo.py:49
+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/SliceInfoPlugin/SliceInfo.py:50
+msgctxt "@action:button"
+msgid "Disable"
+msgstr "Désactiver"
+
+#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/SliceInfo.py:51
+msgctxt "@action:tooltip"
+msgid "Don't allow Cura to send anonymized usage statistics. You can enable it again in the preferences."
+msgstr "Ne pas autoriser Cura à envoyer des statistiques d'utilisation anonymes. Vous pouvez modifier ce paramètre dans les préférences."
#: /home/ruben/Projects/Cura/plugins/LegacyProfileReader/__init__.py:14
msgctxt "@item:inlistbox"
msgid "Cura 15.04 profiles"
msgstr "Profils Cura 15.04"
+#: /home/ruben/Projects/Cura/plugins/CuraBlenderPlugin/__init__.py:15
+msgctxt "@item:inlistbox"
+msgid "Blender file"
+msgstr "Fichier Blender"
+
+#: /home/ruben/Projects/Cura/plugins/CuraBlenderPlugin/CadIntegrationUtils/CommonReader.py:199
+msgctxt "@info:status"
+msgid ""
+"Could not export using \"{}\" quality!\n"
+"Felt back to \"{}\"."
+msgstr ""
+"Impossible d'exporter avec la qualité \"{}\" !\n"
+"Qualité redéfinie sur \"{}\"."
+
#: /home/ruben/Projects/Cura/plugins/GCodeProfileReader/__init__.py:14
#: /home/ruben/Projects/Cura/plugins/GCodeReader/__init__.py:14
msgctxt "@item:inlistbox"
@@ -706,49 +800,49 @@ msgctxt "@item:inlistbox"
msgid "GIF Image"
msgstr "Image GIF"
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:269
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:299
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:269
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:297
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:319
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:299
#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:327
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:336
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:349
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:357
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:366
msgctxt "@info:title"
msgid "Unable to slice"
msgstr "Impossible de découper"
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:296
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:326
#, 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:318
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:348
#, 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:326
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:356
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:335
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:365
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."
#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py:50
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py:239
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py:242
msgctxt "@info:status"
msgid "Processing Layers"
msgstr "Traitement des couches"
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py:239
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py:242
msgctxt "@info:title"
msgid "Information"
msgstr "Informations"
@@ -785,14 +879,14 @@ msgstr "Échec de la copie des fichiers plug-ins Siemens NX. Veuillez vérifier
msgid "Failed to install Siemens NX plugin. Could not set environment variable UGII_USER_DIR for Siemens NX."
msgstr "Échec de l'installation du plug-in Siemens NX. Impossible de définir la variable d'environnement UGII_USER_DIR pour Siemens NX."
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.py:167
-#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:585
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.py:165
+#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:590
msgctxt "@title:tab"
msgid "Recommended"
msgstr "Recommandé"
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.py:169
-#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:590
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.py:167
+#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:595
msgctxt "@title:tab"
msgid "Custom"
msgstr "Personnalisé"
@@ -803,24 +897,24 @@ msgctxt "@item:inlistbox"
msgid "3MF File"
msgstr "Fichier 3MF"
-#: /home/ruben/Projects/Cura/plugins/3MFReader/ThreeMFWorkspaceReader.py:126
-#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:1142
+#: /home/ruben/Projects/Cura/plugins/3MFReader/ThreeMFWorkspaceReader.py:159
+#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:1185
msgctxt "@label"
msgid "Nozzle"
msgstr "Buse"
-#: /home/ruben/Projects/Cura/plugins/PluginBrowser/PluginBrowser.py:164
+#: /home/ruben/Projects/Cura/plugins/PluginBrowser/PluginBrowser.py:152
#, python-brace-format
msgctxt "@info:status"
msgid "Failed to get plugin ID from {0}"
msgstr "Échec de l'obtention de l'identifiant du plug-in au départ de {0}"
-#: /home/ruben/Projects/Cura/plugins/PluginBrowser/PluginBrowser.py:165
+#: /home/ruben/Projects/Cura/plugins/PluginBrowser/PluginBrowser.py:153
msgctxt "@info:tile"
msgid "Warning"
msgstr "Avertissement"
-#: /home/ruben/Projects/Cura/plugins/PluginBrowser/PluginBrowser.py:203
+#: /home/ruben/Projects/Cura/plugins/PluginBrowser/PluginBrowser.py:191
msgctxt "@window:title"
msgid "Plugin browser"
msgstr "Navigateur de plug-ins"
@@ -835,18 +929,18 @@ msgctxt "@item:inlistbox"
msgid "G File"
msgstr "Fichier G"
-#: /home/ruben/Projects/Cura/plugins/GCodeReader/GCodeReader.py:314
+#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:321
msgctxt "@info:status"
msgid "Parsing G-code"
msgstr "Analyse du G-Code"
-#: /home/ruben/Projects/Cura/plugins/GCodeReader/GCodeReader.py:316
-#: /home/ruben/Projects/Cura/plugins/GCodeReader/GCodeReader.py:426
+#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:323
+#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:464
msgctxt "@info:title"
msgid "G-code Details"
msgstr "Détails G-Code"
-#: /home/ruben/Projects/Cura/plugins/GCodeReader/GCodeReader.py:424
+#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:462
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."
@@ -857,6 +951,16 @@ msgctxt "@item:inlistbox"
msgid "Cura Profile"
msgstr "Profil Cura"
+#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/__init__.py:12
+msgctxt "@item:inmenu"
+msgid "Profile Assistant"
+msgstr "Assistant de profil"
+
+#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/__init__.py:17
+msgctxt "@item:inlistbox"
+msgid "Profile Assistant"
+msgstr "Assistant de profil"
+
#: /home/ruben/Projects/Cura/plugins/3MFWriter/__init__.py:30
msgctxt "@item:inlistbox"
msgid "3MF file"
@@ -881,149 +985,123 @@ msgstr "Mise à niveau du firmware"
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.py:14
msgctxt "@action"
msgid "Checkup"
-msgstr "Check-up"
+msgstr "Vérification"
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/BedLevelMachineAction.py:15
msgctxt "@action"
msgid "Level build plate"
-msgstr "Nivellement du plateau"
+msgstr "Paramétrage du plateau de fabrication"
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:89
+#: /home/ruben/Projects/Cura/cura/PrintInformation.py:98
msgctxt "@tooltip"
msgid "Outer Wall"
msgstr "Paroi externe"
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:90
+#: /home/ruben/Projects/Cura/cura/PrintInformation.py:99
msgctxt "@tooltip"
msgid "Inner Walls"
msgstr "Parois internes"
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:91
+#: /home/ruben/Projects/Cura/cura/PrintInformation.py:100
msgctxt "@tooltip"
msgid "Skin"
msgstr "Couche extérieure"
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:92
+#: /home/ruben/Projects/Cura/cura/PrintInformation.py:101
msgctxt "@tooltip"
msgid "Infill"
msgstr "Remplissage"
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:93
+#: /home/ruben/Projects/Cura/cura/PrintInformation.py:102
msgctxt "@tooltip"
msgid "Support Infill"
msgstr "Remplissage du support"
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:94
+#: /home/ruben/Projects/Cura/cura/PrintInformation.py:103
msgctxt "@tooltip"
msgid "Support Interface"
msgstr "Interface du support"
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:95
+#: /home/ruben/Projects/Cura/cura/PrintInformation.py:104
msgctxt "@tooltip"
msgid "Support"
msgstr "Support"
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:96
+#: /home/ruben/Projects/Cura/cura/PrintInformation.py:105
msgctxt "@tooltip"
msgid "Skirt"
-msgstr "Jupe"
+msgstr "Contourner"
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:97
+#: /home/ruben/Projects/Cura/cura/PrintInformation.py:106
msgctxt "@tooltip"
msgid "Travel"
msgstr "Déplacement"
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:98
+#: /home/ruben/Projects/Cura/cura/PrintInformation.py:107
msgctxt "@tooltip"
msgid "Retractions"
msgstr "Rétractions"
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:99
+#: /home/ruben/Projects/Cura/cura/PrintInformation.py:108
msgctxt "@tooltip"
msgid "Other"
msgstr "Autre"
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:199
+#: /home/ruben/Projects/Cura/cura/PrintInformation.py:231
msgctxt "@label unknown material"
msgid "Unknown"
msgstr "Inconnu"
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:284
+#: /home/ruben/Projects/Cura/cura/PrintInformation.py:318
#, python-brace-format
msgctxt "@label"
msgid "Pre-sliced file {0}"
msgstr "Fichier {0} prédécoupé"
-#: /home/ruben/Projects/Cura/cura/PrinterOutputDevice.py:469
+#: /home/ruben/Projects/Cura/cura/PrinterOutputDevice.py:440
msgctxt "@item:material"
msgid "No material loaded"
msgstr "Pas de matériau chargé"
-#: /home/ruben/Projects/Cura/cura/PrinterOutputDevice.py:476
+#: /home/ruben/Projects/Cura/cura/PrinterOutputDevice.py:447
msgctxt "@item:material"
msgid "Unknown material"
msgstr "Matériau inconnu"
-#: /home/ruben/Projects/Cura/cura/ArrangeObjectsJob.py:30
-msgctxt "@info:status"
-msgid "Finding new location for objects"
-msgstr "Recherche d'un nouvel emplacement pour les objets"
-
-#: /home/ruben/Projects/Cura/cura/ArrangeObjectsJob.py:34
-msgctxt "@info:title"
-msgid "Finding Location"
-msgstr "Recherche d'emplacement..."
-
-#: /home/ruben/Projects/Cura/cura/ArrangeObjectsJob.py:89
-#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:83
-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/ArrangeObjectsJob.py:90
-msgctxt "@info:title"
-msgid "Can't Find Location"
-msgstr "Impossible de trouver un emplacement"
-
-#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:431
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:113
+#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:437
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:120
msgctxt "@title:window"
msgid "File Already Exists"
msgstr "Le fichier existe déjà"
-#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:432
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:114
+#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:438
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:121
#, python-brace-format
msgctxt "@label Don't translate the XML tag !"
msgid "The file {0} already exists. Are you sure you want to overwrite it?"
msgstr "Le fichier {0} existe déjà. Êtes-vous sûr de vouloir le remplacer ?"
-#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:815
+#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:872
msgctxt "@label"
msgid "Custom"
msgstr "Personnalisé"
-#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:819
+#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:876
msgctxt "@label"
msgid "Custom Material"
msgstr "Matériau personnalisé"
-#: /home/ruben/Projects/Cura/cura/Settings/ExtrudersModel.py:182
-msgctxt "@menuitem"
-msgid "Global"
-msgstr "Global"
-
-#: /home/ruben/Projects/Cura/cura/Settings/ExtrudersModel.py:229
+#: /home/ruben/Projects/Cura/cura/Settings/ExtrudersModel.py:205
msgctxt "@menuitem"
msgid "Not overridden"
-msgstr "Pas écrasé"
+msgstr "Pas pris en compte"
-#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:117
+#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:124
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."
-#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:118
+#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:125
#: /home/ruben/Projects/Cura/cura/Settings/MaterialManager.py:24
msgctxt "@info:title"
msgid "Incompatible Material"
@@ -1044,67 +1122,89 @@ msgctxt "@action"
msgid "Undo changing the material diameter."
msgstr "Annuler la modification du diamètre du matériau."
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:144
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:151
#, 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:151
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:158
#, 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:156
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:163
#, 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:157
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:164
msgctxt "@info:title"
msgid "Export succeeded"
msgstr "L'exportation a réussi"
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:183
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:205
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:214
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:248
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:190
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:211
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:271
#, 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}"
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:216
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:252
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:230
+#, python-brace-format
+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."
+
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:240
+#, python-brace-format
+msgctxt "@info:status Don't translate the XML tags or !"
+msgid "The machine defined in profile {0} doesn't match with your current machine, could not import it."
+msgstr "La machine définie dans le profil {0} ne correspond pas à votre machine actuelle ; échec de l'importation."
+
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:274
#, 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:255
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:277
+#, 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:280
#, 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:274
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:298
msgctxt "@label"
msgid "Custom profile"
msgstr "Personnaliser le profil"
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:285
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:313
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:321
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:349
#, 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:46
+#, python-brace-format
+msgctxt "@label"
+msgid "Group #{group_nr}"
+msgstr "Groupe nº {group_nr}"
+
#: /home/ruben/Projects/Cura/cura/BuildVolume.py:100
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."
@@ -1115,142 +1215,170 @@ msgctxt "@info:title"
msgid "Build Volume"
msgstr "Volume d'impression"
-#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:34
+#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:25
msgctxt "@info:status"
msgid "Multiplying and placing objects"
msgstr "Multiplication et placement d'objets"
-#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:35
-#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:83
+#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:26
+#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:78
msgctxt "@info:title"
msgid "Placing Object"
-msgstr "Placement de l'objet..."
+msgstr "Placement de l'objet"
-#: /home/ruben/Projects/Cura/cura/CrashHandler.py:80
+#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:78
+#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsJob.py:88
+#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsAllBuildPlatesJob.py:152
+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:29
+#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsAllBuildPlatesJob.py:64
+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:33
+#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsAllBuildPlatesJob.py:68
+msgctxt "@info:title"
+msgid "Finding Location"
+msgstr "Recherche d'emplacement..."
+
+#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsJob.py:89
+#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsAllBuildPlatesJob.py:153
+msgctxt "@info:title"
+msgid "Can't Find Location"
+msgstr "Impossible de trouver un emplacement"
+
+#: /home/ruben/Projects/Cura/cura/CrashHandler.py:81
msgctxt "@title:window"
msgid "Crash Report"
msgstr "Rapport d'incident"
-#: /home/ruben/Projects/Cura/cura/CrashHandler.py:93
+#: /home/ruben/Projects/Cura/cura/CrashHandler.py:94
msgctxt "@label crash message"
msgid ""
-"
A fatal exception has occurred. Please send us this Crash Report to fix the problem
\n"
+"
A fatal error has occurred. Please send us this Crash Report to fix the problem
\n"
"
Please use the \"Send report\" button to post a bug report automatically to our servers
\n"
" "
-msgstr "
Une exception fatale s'est produite. Veuillez nous envoyer ce Rapport d'incident pour résoudre le problème
\n
Veuillez utiliser le bouton « Envoyer rapport » pour publier automatiquement un rapport d'erreur sur nos serveurs
\n "
+msgstr ""
+"
Une erreur fatale s'est produite. Veuillez nous envoyer ce Rapport d'incident pour résoudre le problème
\n"
+"
Veuillez utiliser le bouton « Envoyer rapport » pour publier automatiquement un rapport d'erreur sur nos serveurs
"
-#: /home/ruben/Projects/Cura/cura/CrashHandler.py:141
+#: /home/ruben/Projects/Cura/cura/CrashHandler.py:147
msgctxt "@title:groupbox"
-msgid "Exception traceback"
-msgstr "Retraçage de l'exception"
+msgid "Error traceback"
+msgstr "Retraçage de l'erreur"
-#: /home/ruben/Projects/Cura/cura/CrashHandler.py:208
+#: /home/ruben/Projects/Cura/cura/CrashHandler.py:214
msgctxt "@title:groupbox"
msgid "Logs"
-msgstr "Journaux"
+msgstr "Registres"
-#: /home/ruben/Projects/Cura/cura/CrashHandler.py:231
+#: /home/ruben/Projects/Cura/cura/CrashHandler.py:237
msgctxt "@title:groupbox"
msgid "User description"
msgstr "Description de l'utilisateur"
-#: /home/ruben/Projects/Cura/cura/CrashHandler.py:246
+#: /home/ruben/Projects/Cura/cura/CrashHandler.py:252
msgctxt "@action:button"
msgid "Send report"
msgstr "Envoyer rapport"
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:256
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:274
msgctxt "@info:progress"
msgid "Loading machines..."
msgstr "Chargement des machines..."
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:661
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:660
msgctxt "@info:progress"
msgid "Setting up scene..."
-msgstr "Préparation de la scène..."
+msgstr "Préparation de la tâche..."
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:703
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:702
msgctxt "@info:progress"
msgid "Loading interface..."
msgstr "Chargement de l'interface..."
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:874
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:899
#, 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:1348
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1417
#, 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:1357
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1426
#, 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:1416
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1495
msgctxt "@info:status"
msgid "The selected model was too small to load."
msgstr "Le modèle sélectionné était trop petit pour être chargé."
@@ -1279,12 +1407,11 @@ msgstr "X (Largeur)"
#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:119
#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:129
#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:235
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:288
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:300
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:391
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:401
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:413
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:840
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:383
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:394
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:412
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:424
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:849
msgctxt "@label"
msgid "mm"
msgstr "mm"
@@ -1374,71 +1501,70 @@ 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:255
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:254
msgctxt "@label"
msgid "Number of Extruders"
-msgstr "Nombre d'extrudeuses"
+msgstr "Nombre d'extrudeurs"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:289
-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:291
-msgctxt "@label"
-msgid "Material diameter"
-msgstr "Diamètre du matériau"
-
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:299
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:390
-msgctxt "@label"
-msgid "Nozzle size"
-msgstr "Taille de la buse"
-
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:317
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:310
msgctxt "@label"
msgid "Start Gcode"
msgstr "Début Gcode"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:327
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:320
msgctxt "@tooltip"
msgid "Gcode commands to be executed at the very start."
msgstr "Commandes Gcode à exécuter au tout début."
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:336
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:329
msgctxt "@label"
msgid "End Gcode"
msgstr "Fin Gcode"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:346
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:339
msgctxt "@tooltip"
msgid "Gcode commands to be executed at the very end."
msgstr "Commandes Gcode à exécuter tout à la fin."
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:378
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:370
msgctxt "@label"
msgid "Nozzle Settings"
msgstr "Paramètres de la buse"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:400
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:382
+msgctxt "@label"
+msgid "Nozzle size"
+msgstr "Taille de la buse"
+
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:393
+msgctxt "@label"
+msgid "Compatible material diameter"
+msgstr "Diamètre du matériau compatible"
+
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:395
+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:411
msgctxt "@label"
msgid "Nozzle offset X"
msgstr "Décalage buse X"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:412
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:423
msgctxt "@label"
msgid "Nozzle offset Y"
msgstr "Décalage buse Y"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:433
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:444
msgctxt "@label"
msgid "Extruder Start Gcode"
-msgstr "Extrudeuse Gcode de démarrage"
+msgstr "Extrudeur Gcode de démarrage"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:451
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:462
msgctxt "@label"
msgid "Extruder End Gcode"
-msgstr "Extrudeuse Gcode de fin"
+msgstr "Extrudeur Gcode de fin"
#: /home/ruben/Projects/Cura/plugins/ChangeLogPlugin/ChangeLog.qml:18
msgctxt "@label"
@@ -1448,8 +1574,9 @@ msgstr "Récapitulatif des changements"
#: /home/ruben/Projects/Cura/plugins/ChangeLogPlugin/ChangeLog.qml:37
#: /home/ruben/Projects/Cura/plugins/USBPrinting/FirmwareUpdateWindow.qml:107
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/UM3InfoComponents.qml:55
-#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.qml:445
-#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:357
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksMacroTutorial.qml:306
+#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.qml:456
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:492
#: /home/ruben/Projects/Cura/plugins/PluginBrowser/PluginBrowser.qml:80
#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:123
#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:147
@@ -1514,7 +1641,10 @@ 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\nSélectionnez votre imprimante dans la liste ci-dessous :"
+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 :"
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/DiscoverUM3Action.qml:75
#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:44
@@ -1530,7 +1660,7 @@ msgstr "Modifier"
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/DiscoverUM3Action.qml:96
#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:50
#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:95
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:190
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:171
msgctxt "@action:button"
msgid "Remove"
msgstr "Supprimer"
@@ -1552,14 +1682,14 @@ msgid "Type"
msgstr "Type"
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/DiscoverUM3Action.qml:233
-msgctxt "@label"
+msgctxt "@label Printer name"
msgid "Ultimaker 3"
-msgstr "Ultimaker 3"
+msgstr "Ultimaker 3"
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/DiscoverUM3Action.qml:236
-msgctxt "@label"
+msgctxt "@label Printer name"
msgid "Ultimaker 3 Extended"
-msgstr "Ultimaker 3 Extended"
+msgstr "Ultimaker 3 Extended"
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/DiscoverUM3Action.qml:252
msgctxt "@label"
@@ -1603,8 +1733,6 @@ 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/DiscoverUM3Action.qml:379
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/ConfigDialog.qml:92
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/ExportSTLUI.qml:88
#: /home/ruben/Projects/Cura/plugins/ImageReader/ConfigUI.qml:181
msgctxt "@action:button"
msgid "OK"
@@ -1623,7 +1751,12 @@ msgstr "Imprimer"
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/ClusterMonitorItem.qml:36
msgctxt "@label: arg 1 is group name"
msgid "%1 is not set up to host a group of connected Ultimaker 3 printers"
-msgstr "%1 n'est pas configurée pour héberger un groupe d'imprimantes connectées Ultimaker 3."
+msgstr "%1 n'est pas configurée pour héberger un groupe d'imprimantes connectées Ultimaker 3"
+
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/ClusterMonitorItem.qml:55
+msgctxt "@label link to connect manager"
+msgid "Add/Remove printers"
+msgstr "Ajouter / supprimer une imprimante"
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/OpenPanelButton.qml:14
msgctxt "@info:tooltip"
@@ -1641,7 +1774,7 @@ msgstr "Afficher les tâches d'impression"
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/PrinterInfoBlock.qml:408
msgctxt "@label"
msgid "Preparing to print"
-msgstr "Préparation de l'impression..."
+msgstr "Préparation de l'impression"
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/PrinterInfoBlock.qml:39
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/PrinterInfoBlock.qml:271
@@ -1655,11 +1788,16 @@ msgid "Available"
msgstr "Disponible"
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/PrinterInfoBlock.qml:43
-#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:101
+#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:100
msgctxt "@label:MonitorStatus"
msgid "Lost connection with the printer"
msgstr "Connexion avec l'imprimante perdue"
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/PrinterInfoBlock.qml:47
+msgctxt "@label Printer status"
+msgid "Unknown"
+msgstr "Inconnu"
+
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/PrinterInfoBlock.qml:257
msgctxt "@label:status"
msgid "Disabled"
@@ -1751,141 +1889,255 @@ msgctxt "@action:button"
msgid "Activate Configuration"
msgstr "Activer la configuration"
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/ConfigDialog.qml:20
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksWizard.qml:21
msgctxt "@title:window"
-msgid "Cura SolidWorks Plugin Configuration"
-msgstr "Configuration du plug-in Cura SolidWorks"
+msgid "SolidWorks: Export wizard"
+msgstr "SolidWorks : assistant d'exportation"
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/ConfigDialog.qml:44
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksWizard.qml:45
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:140
msgctxt "@action:label"
-msgid "Default quality of the exported STL:"
-msgstr "Qualité par défaut du STL exporté :"
+msgid "Quality:"
+msgstr "Qualité :"
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/ConfigDialog.qml:79
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksWizard.qml:78
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:179
msgctxt "@option:curaSolidworksStlQuality"
-msgid "Always ask"
-msgstr "Toujours demander"
+msgid "Fine (3D-printing)"
+msgstr "Fine (impression 3D)"
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/ConfigDialog.qml:80
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksWizard.qml:79
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:180
msgctxt "@option:curaSolidworksStlQuality"
-msgid "Always use Fine quality"
-msgstr "Toujours utiliser la qualité Fine"
+msgid "Coarse (3D-printing)"
+msgstr "Grossière (impression 3D)"
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/ConfigDialog.qml:81
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksWizard.qml:80
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:181
msgctxt "@option:curaSolidworksStlQuality"
-msgid "Always use Coarse quality"
-msgstr "Toujours utiliser la qualité grossière"
+msgid "Fine (SolidWorks)"
+msgstr "Fine (SolidWorks)"
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/ExportSTLUI.qml:20
-msgctxt "@title:window"
-msgid "Import SolidWorks File as STL..."
-msgstr "Importer le fichier SolidWorks comme STL..."
-
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/ExportSTLUI.qml:43
-msgctxt "@info:tooltip"
-msgid "Quality of the Exported STL"
-msgstr "Qualité du STL exporté"
-
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/ExportSTLUI.qml:48
-msgctxt "@action:label"
-msgid "Quality"
-msgstr "Qualité"
-
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/ExportSTLUI.qml:62
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksWizard.qml:81
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:182
msgctxt "@option:curaSolidworksStlQuality"
-msgid "Coarse"
-msgstr "Grossière"
+msgid "Coarse (SolidWorks)"
+msgstr "Grossière (SolidWorks)"
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/ExportSTLUI.qml:63
-msgctxt "@option:curaSolidworksStlQuality"
-msgid "Fine"
-msgstr "Fine"
-
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/ExportSTLUI.qml:78
-#: /home/ruben/Projects/Cura/resources/qml/AskOpenAsProjectOrModelsDialog.qml:82
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksWizard.qml:94
msgctxt "@text:window"
-msgid "Remember my choice"
-msgstr "Se souvenir de mon choix"
+msgid "Show this dialog again"
+msgstr "Afficher de nouveau cette boîte de dialogue"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:81
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksWizard.qml:104
+msgctxt "@action:button"
+msgid "Continue"
+msgstr "Continuer"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksWizard.qml:116
+msgctxt "@action:button"
+msgid "Abort"
+msgstr "Abandonner"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksMacroTutorial.qml:21
+msgctxt "@title:window"
+msgid "How to install Cura SolidWorks macro"
+msgstr "Modalités d’installation de Cura SolidWorks macro"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksMacroTutorial.qml:62
+msgctxt "@description:label"
+msgid "Steps:"
+msgstr "Procédure :"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksMacroTutorial.qml:140
+msgctxt "@action:button"
+msgid ""
+"Open the directory\n"
+"with macro and icon"
+msgstr ""
+"Ouvrez le répertoire\n"
+"contenant la macro et l'icône"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksMacroTutorial.qml:160
+msgctxt "@description:label"
+msgid "Instructions:"
+msgstr "Instructions :"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksMacroTutorial.qml:202
+msgctxt "@action:playpause"
+msgid "Play"
+msgstr "Jouer"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksMacroTutorial.qml:206
+msgctxt "@action:playpause"
+msgid "Pause"
+msgstr "Pause"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksMacroTutorial.qml:268
+msgctxt "@action:button"
+msgid "Previous Step"
+msgstr "Étape précédente"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksMacroTutorial.qml:283
+msgctxt "@action:button"
+msgid "Done"
+msgstr "Terminé"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksMacroTutorial.qml:287
+msgctxt "@action:button"
+msgid "Next Step"
+msgstr "Étape suivante"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:21
+msgctxt "@title:window"
+msgid "SolidWorks plugin: Configuration"
+msgstr "Plug-in SolidWorks : configuration"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:39
+msgctxt "@title:tab"
+msgid "Conversion settings"
+msgstr "Paramètres de conversion"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:66
+msgctxt "@label"
+msgid "First choice:"
+msgstr "Premier choix :"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:86
+msgctxt "@text:menu"
+msgid "Latest installed version (Recommended)"
+msgstr "Dernière version installée (recommandé)"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:95
+msgctxt "@text:menu"
+msgid "Default version"
+msgstr "Version par défaut"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:193
+msgctxt "@label"
+msgid "Show wizard before opening SolidWorks files"
+msgstr "Afficher l'Assistant avant d'ouvrir les fichiers SolidWorks"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:203
+msgctxt "@label"
+msgid "Automatically rotate opened file into normed orientation"
+msgstr "Rotation automatique du fichier ouvert en orientation normalisée"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:210
+msgctxt "@title:tab"
+msgid "Installation(s)"
+msgstr "Installation(s)"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:284
+msgctxt "@label"
+msgid "COM service found"
+msgstr "Service COM trouvé"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:295
+msgctxt "@label"
+msgid "Executable found"
+msgstr "Fichier exécutable trouvé"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:306
+msgctxt "@label"
+msgid "COM starting"
+msgstr "Lancement de COM"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:317
+msgctxt "@label"
+msgid "Revision number"
+msgstr "Numéro de révision"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:328
+msgctxt "@label"
+msgid "Functions available"
+msgstr "Fonctions disponibles"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:341
+#: /home/ruben/Projects/Cura/resources/qml/WorkspaceSummaryDialog.qml:264
+msgctxt "@action:button"
+msgid "Save"
+msgstr "Enregistrer"
+
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:117
msgctxt "@label"
msgid "Color scheme"
msgstr "Modèle de couleurs"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:96
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:132
msgctxt "@label:listbox"
msgid "Material Color"
msgstr "Couleur du matériau"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:100
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:136
msgctxt "@label:listbox"
msgid "Line Type"
msgstr "Type de ligne"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:104
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:140
msgctxt "@label:listbox"
msgid "Feedrate"
msgstr "Taux d'alimentation"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:108
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:144
msgctxt "@label:listbox"
msgid "Layer thickness"
msgstr "Épaisseur de la couche"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:148
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:185
msgctxt "@label"
msgid "Compatibility Mode"
msgstr "Mode de compatibilité"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:230
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:264
msgctxt "@label"
msgid "Show Travels"
msgstr "Afficher les déplacements"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:236
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:270
msgctxt "@label"
msgid "Show Helpers"
msgstr "Afficher les aides"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:242
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:276
msgctxt "@label"
msgid "Show Shell"
msgstr "Afficher la coque"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:248
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:282
msgctxt "@label"
msgid "Show Infill"
msgstr "Afficher le remplissage"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:297
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:330
msgctxt "@label"
msgid "Only Show Top Layers"
msgstr "Afficher uniquement les couches supérieures"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:306
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:339
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:317
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:350
msgctxt "@label"
msgid "Top / Bottom"
msgstr "Haut / bas"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:321
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:354
msgctxt "@label"
msgid "Inner Wall"
msgstr "Paroi interne"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:378
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:410
msgctxt "@label"
msgid "min"
-msgstr "min."
+msgstr "min"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:420
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:452
msgctxt "@label"
msgid "max"
-msgstr "max."
+msgstr "max"
#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.qml:18
msgctxt "@title:window"
@@ -1907,7 +2159,7 @@ msgctxt "@label"
msgid "Settings"
msgstr "Paramètres"
-#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.qml:455
+#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.qml:466
msgctxt "@info:tooltip"
msgid "Change active post-processing scripts"
msgstr "Modifier les scripts de post-traitement actifs"
@@ -1982,23 +2234,53 @@ msgctxt "@action:label"
msgid "Smoothing"
msgstr "Lissage"
-#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:208
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:38
+msgctxt "@label"
+msgid "Mesh Type"
+msgstr "Type de maille"
+
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:69
+msgctxt "@label"
+msgid "Normal model"
+msgstr "Modèle normal"
+
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:76
+msgctxt "@label"
+msgid "Print as support"
+msgstr "Imprimer comme support"
+
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:84
+msgctxt "@label"
+msgid "Don't support overlap with other models"
+msgstr "Ne pas prendre en charge le chevauchement avec d'autres modèles"
+
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:92
+msgctxt "@label"
+msgid "Modify settings for overlap with other models"
+msgstr "Modifier les paramètres de chevauchement avec d'autres modèles"
+
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:100
+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:333
msgctxt "@action:button"
msgid "Select settings"
msgstr "Sélectionner les paramètres"
-#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:248
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:375
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:272
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:402
#: /home/ruben/Projects/Cura/resources/qml/Preferences/SettingVisibilityPage.qml:91
msgctxt "@label:textbox"
msgid "Filter..."
msgstr "Filtrer..."
-#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:296
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:426
msgctxt "@label:checkbox"
msgid "Show all"
msgstr "Afficher tout"
@@ -2022,7 +2304,7 @@ msgstr "Créer"
#: /home/ruben/Projects/Cura/resources/qml/WorkspaceSummaryDialog.qml:72
msgctxt "@action:title"
msgid "Summary - Cura Project"
-msgstr "Résumé - Projet Cura"
+msgstr "Sommaire - Projet Cura"
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:92
#: /home/ruben/Projects/Cura/resources/qml/WorkspaceSummaryDialog.qml:90
@@ -2033,7 +2315,7 @@ msgstr "Paramètres de l'imprimante"
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:108
msgctxt "@info:tooltip"
msgid "How should the conflict in the machine be resolved?"
-msgstr "Comment le conflit de la machine doit-il être résolu ?"
+msgstr "Comment le problème de la machine doit-il être résolu ?"
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:128
#: /home/ruben/Projects/Cura/resources/qml/WorkspaceSummaryDialog.qml:99
@@ -2059,7 +2341,7 @@ msgstr "Paramètres de profil"
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:181
msgctxt "@info:tooltip"
msgid "How should the conflict in the profile be resolved?"
-msgstr "Comment le conflit du profil doit-il être résolu ?"
+msgstr "Comment le problème du profil doit-il être résolu ?"
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:216
#: /home/ruben/Projects/Cura/resources/qml/WorkspaceSummaryDialog.qml:174
@@ -2095,7 +2377,7 @@ msgstr "Paramètres du matériau"
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:269
msgctxt "@info:tooltip"
msgid "How should the conflict in the material be resolved?"
-msgstr "Comment le conflit du matériau doit-il être résolu ?"
+msgstr "Comment le problème du matériau doit-il être résolu ?"
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:312
#: /home/ruben/Projects/Cura/resources/qml/WorkspaceSummaryDialog.qml:209
@@ -2158,7 +2440,7 @@ msgstr "Télécharger"
#: /home/ruben/Projects/Cura/plugins/PluginBrowser/PluginBrowser.qml:199
msgctxt "@title:window"
msgid "Plugin License Agreement"
-msgstr "Plug-in d'accord de licence"
+msgstr "Plug-in de l'accord de licence"
#: /home/ruben/Projects/Cura/plugins/PluginBrowser/PluginBrowser.qml:220
msgctxt "@label"
@@ -2166,7 +2448,10 @@ msgid ""
"This plugin contains a license.\n"
"You need to accept this license to install this plugin.\n"
"Do you agree with the terms below?"
-msgstr "Ce plug-in contient une licence.\nVous devez approuver cette licence pour installer ce plug-in.\nAcceptez-vous les clauses ci-dessous ?"
+msgstr ""
+"Ce plug-in contient une licence.\n"
+"Vous devez approuver cette licence pour installer ce plug-in.\n"
+"Acceptez-vous les clauses ci-dessous ?"
#: /home/ruben/Projects/Cura/plugins/PluginBrowser/PluginBrowser.qml:242
msgctxt "@action:button"
@@ -2355,68 +2640,68 @@ 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."
+msgstr "Tout est en ordre ! Vous avez terminé votre vérification."
-#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:88
+#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:87
msgctxt "@label:MonitorStatus"
msgid "Not connected to a printer"
msgstr "Non connecté à une imprimante"
-#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:90
+#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:89
msgctxt "@label:MonitorStatus"
msgid "Printer does not accept commands"
msgstr "L'imprimante n'accepte pas les commandes"
-#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:96
+#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:95
#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:194
msgctxt "@label:MonitorStatus"
msgid "In maintenance. Please check the printer"
-msgstr "En maintenance. Vérifiez l'imprimante"
+msgstr "En maintenance. Veuillez vérifier l'imprimante"
-#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:103
+#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:102
#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:184
msgctxt "@label:MonitorStatus"
msgid "Printing..."
msgstr "Impression..."
-#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:106
+#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:105
#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:186
msgctxt "@label:MonitorStatus"
msgid "Paused"
msgstr "En pause"
-#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:109
+#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:108
#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:188
msgctxt "@label:MonitorStatus"
msgid "Preparing..."
msgstr "Préparation..."
-#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:111
+#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:110
msgctxt "@label:MonitorStatus"
msgid "Please remove the print"
-msgstr "Supprimez l'imprimante"
+msgstr "Veuillez supprimer l'imprimante"
-#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:237
+#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:241
msgctxt "@label:"
msgid "Resume"
msgstr "Reprendre"
-#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:241
+#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:245
msgctxt "@label:"
msgid "Pause"
msgstr "Pause"
-#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:270
+#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:274
msgctxt "@label:"
msgid "Abort Print"
msgstr "Abandonner l'impression"
-#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:280
+#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:284
msgctxt "@window:title"
msgid "Abort print"
msgstr "Abandonner l'impression"
-#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:282
+#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:286
msgctxt "@label"
msgid "Are you sure you want to abort the print?"
msgstr "Êtes-vous sûr(e) de vouloir abandonner l'impression ?"
@@ -2431,7 +2716,9 @@ 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.\nSouhaitez-vous conserver ces changements, ou les annuler ?"
+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"
@@ -2449,19 +2736,19 @@ msgid "Customized"
msgstr "Personnalisé"
#: /home/ruben/Projects/Cura/resources/qml/DiscardOrKeepProfileChangesDialog.qml:157
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:593
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:595
msgctxt "@option:discardOrKeep"
msgid "Always ask me this"
msgstr "Toujours me demander"
#: /home/ruben/Projects/Cura/resources/qml/DiscardOrKeepProfileChangesDialog.qml:158
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:594
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:596
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
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:595
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:597
msgctxt "@option:discardOrKeep"
msgid "Keep and never ask again"
msgstr "Conserver et ne plus me demander"
@@ -2496,72 +2783,72 @@ msgctxt "@label"
msgid "Brand"
msgstr "Marque"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:92
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:88
msgctxt "@label"
msgid "Material Type"
msgstr "Type de matériau"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:105
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:97
msgctxt "@label"
msgid "Color"
msgstr "Couleur"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:139
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:141
msgctxt "@label"
msgid "Properties"
msgstr "Propriétés"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:141
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:143
msgctxt "@label"
msgid "Density"
msgstr "Densité"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:156
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:158
msgctxt "@label"
msgid "Diameter"
msgstr "Diamètre"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:185
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:187
msgctxt "@label"
msgid "Filament Cost"
msgstr "Coût du filament"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:201
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:203
msgctxt "@label"
msgid "Filament weight"
msgstr "Poids du filament"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:218
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:220
msgctxt "@label"
msgid "Filament length"
msgstr "Longueur du filament"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:227
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:229
msgctxt "@label"
msgid "Cost per Meter"
msgstr "Coût au mètre"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:241
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:243
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/MaterialView.qml:248
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:250
msgctxt "@label"
msgid "Unlink Material"
msgstr "Délier le matériau"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:259
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:261
msgctxt "@label"
msgid "Description"
msgstr "Description"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:272
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:274
msgctxt "@label"
msgid "Adhesion Information"
msgstr "Informations d'adhérence"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:298
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:300
msgctxt "@label"
msgid "Print settings"
msgstr "Paramètres d'impression"
@@ -2602,7 +2889,7 @@ msgid "Unit"
msgstr "Unité"
#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:14
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:439
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:509
msgctxt "@title:tab"
msgid "General"
msgstr "Général"
@@ -2617,230 +2904,255 @@ msgctxt "@label"
msgid "Language:"
msgstr "Langue :"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:205
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:207
msgctxt "@label"
msgid "Currency:"
msgstr "Devise :"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:219
+#: /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:279
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:281
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:296
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:298
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:304
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:306
msgctxt "@option:check"
msgid "Slice automatically"
msgstr "Découper automatiquement"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:318
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:320
msgctxt "@label"
msgid "Viewport behavior"
msgstr "Comportement Viewport"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:326
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:328
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:335
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:337
msgctxt "@option:check"
msgid "Display overhang"
msgstr "Mettre en surbrillance les porte-à-faux"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:342
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:344
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:347
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:349
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:356
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:358
msgctxt "@info:tooltip"
msgid "Should the default zoom behavior of cura be inverted?"
msgstr "Le comportement de zoom par défaut de Cura doit-il être inversé ?"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:361
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:363
msgctxt "@action:button"
msgid "Invert the direction of camera zoom."
msgstr "Inverser la direction du zoom de la caméra."
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:370
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:372
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:375
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:377
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:384
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:386
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:389
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:391
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:397
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:399
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:402
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:404
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:414
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:416
msgctxt "@info:tooltip"
msgid "Show caution message in gcode reader."
msgstr "Afficher le message d'avertissement dans le lecteur gcode."
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:423
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:425
msgctxt "@option:check"
msgid "Caution message in gcode reader"
msgstr "Message d'avertissement dans lecteur gcode."
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:430
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:432
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:435
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:437
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:451
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:453
msgctxt "@label"
msgid "Opening and saving files"
msgstr "Ouvrir et enregistrer des fichiers"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:457
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:459
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:462
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:464
msgctxt "@option:check"
msgid "Scale large models"
msgstr "Réduire la taille des modèles trop grands"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:471
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:473
msgctxt "@info:tooltip"
msgid "An model may appear extremely small if its unit is for example in meters rather than millimeters. Should these models be scaled up?"
msgstr "Un modèle peut apparaître en tout petit si son unité est par exemple en mètres plutôt qu'en millimètres. Ces modèles doivent-ils être agrandis ?"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:476
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:478
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:485
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:487
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:490
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:492
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:499
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:501
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:503
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:505
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:512
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:514
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:520
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:522
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:533
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:535
msgctxt "@option:openProject"
msgid "Always ask"
msgstr "Toujours demander"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:534
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:536
msgctxt "@option:openProject"
msgid "Always open as a project"
msgstr "Toujours ouvrir comme projet"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:535
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:537
msgctxt "@option:openProject"
msgid "Always import models"
msgstr "Toujours importer les modèles"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:571
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:573
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:580
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:582
msgctxt "@label"
msgid "Override Profile"
msgstr "Écraser le profil"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:629
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:631
msgctxt "@label"
msgid "Privacy"
msgstr "Confidentialité"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:636
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:638
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:641
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:643
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:651
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:653
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:656
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:658
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:674
+msgctxt "@label"
+msgid "Experimental"
+msgstr "Expérimental"
+
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:680
+msgctxt "@info:tooltip"
+msgid "Use multi build plate functionality"
+msgstr "Utiliser la fonctionnalité multi-plateau"
+
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:685
+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/GeneralPage.qml:694
+msgctxt "@info:tooltip"
+msgid "Should newly loaded models be arranged on the build plate? Used in conjunction with multi build plate (EXPERIMENTAL)"
+msgstr "Les modèles nouvellement chargés doivent-ils être disposés sur le plateau ? Utilisé en conjonction avec le multi-plateau (EXPÉRIMENTAL)"
+
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:699
+msgctxt "@option:check"
+msgid "Do not arrange objects on load"
+msgstr "Ne pas réorganiser les objets lors du chargement"
+
#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:15
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:444
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:514
msgctxt "@title:tab"
msgid "Printers"
msgstr "Imprimantes"
#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:37
#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:51
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:137
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:138
msgctxt "@action:button"
msgid "Activate"
msgstr "Activer"
@@ -2883,7 +3195,7 @@ msgid "Waiting for a printjob"
msgstr "En attente d'une tâche d'impression"
#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:15
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:448
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:518
msgctxt "@title:tab"
msgid "Profiles"
msgstr "Profils"
@@ -2909,13 +3221,13 @@ msgid "Duplicate"
msgstr "Dupliquer"
#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:113
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:201
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:182
msgctxt "@action:button"
msgid "Import"
msgstr "Importer"
#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:119
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:212
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:193
msgctxt "@action:button"
msgid "Export"
msgstr "Exporter"
@@ -2981,7 +3293,7 @@ msgid "Export Profile"
msgstr "Exporter un profil"
#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:15
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:446
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:516
msgctxt "@title:tab"
msgid "Materials"
msgstr "Matériaux"
@@ -2996,60 +3308,60 @@ msgctxt "@action:label %1 is printer name"
msgid "Printer: %1"
msgstr "Imprimante : %1"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:149
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:150
msgctxt "@action:button"
msgid "Create"
msgstr "Créer"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:168
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:160
msgctxt "@action:button"
msgid "Duplicate"
msgstr "Dupliquer"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:311
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:319
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:298
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:306
msgctxt "@title:window"
msgid "Import Material"
msgstr "Importer un matériau"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:320
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:307
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/MaterialsPage.qml:324
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:311
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/MaterialsPage.qml:343
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:358
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:329
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:344
msgctxt "@title:window"
msgid "Export Material"
msgstr "Exporter un matériau"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:362
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:348
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/MaterialsPage.qml:368
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:354
msgctxt "@info:status Don't translate the XML tag !"
msgid "Successfully exported material to %1"
msgstr "Matériau exporté avec succès vers %1"
#: /home/ruben/Projects/Cura/resources/qml/AddMachineDialog.qml:18
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:793
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:869
msgctxt "@title:window"
msgid "Add Printer"
msgstr "Ajouter une imprimante"
-#: /home/ruben/Projects/Cura/resources/qml/AddMachineDialog.qml:185
+#: /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:208
+#: /home/ruben/Projects/Cura/resources/qml/AddMachineDialog.qml:217
msgctxt "@action:button"
msgid "Add Printer"
msgstr "Ajouter une imprimante"
@@ -3074,7 +3386,9 @@ 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.\nCura est fier d'utiliser les projets open source suivants :"
+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"
@@ -3094,7 +3408,7 @@ msgstr "Générateur GCode"
#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:121
msgctxt "@label"
msgid "Interprocess communication library"
-msgstr "Bibliothèque de communication interprocess"
+msgstr "Bibliothèque de communication inter-process"
#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:123
msgctxt "@label"
@@ -3176,158 +3490,167 @@ msgctxt "@label"
msgid "Profile:"
msgstr "Profil :"
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:66
-msgctxt "@"
-msgid "No Profile Available"
-msgstr "Aucun profil disponible"
-
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:104
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:102
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\nCliquez pour ouvrir le gestionnaire de profils."
+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:152
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:150
msgctxt "@label:textbox"
msgid "Search..."
msgstr "Rechercher..."
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:483
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:482
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:498
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:497
msgctxt "@action:menu"
msgid "Hide this setting"
msgstr "Masquer ce paramètre"
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:508
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:507
msgctxt "@action:menu"
msgid "Don't show this setting"
msgstr "Masquer ce paramètre"
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:512
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:511
msgctxt "@action:menu"
msgid "Keep this setting visible"
msgstr "Afficher ce paramètre"
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:531
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:530
msgctxt "@action:menu"
msgid "Configure setting visiblity..."
msgstr "Configurer la visibilité des paramètres..."
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingCategory.qml:123
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingCategory.qml:250
msgctxt "@label"
msgid ""
"Some hidden settings use values different from their normal calculated value.\n"
"\n"
"Click to make these settings visible."
-msgstr "Certains paramètres masqués utilisent des valeurs différentes de leur valeur normalement calculée.\n\nCliquez pour rendre ces paramètres visibles."
+msgstr ""
+"Certains paramètres masqués utilisent des valeurs différentes de leur valeur normalement calculée.\n"
+"\n"
+"Cliquez pour rendre ces paramètres visibles."
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:62
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:61
msgctxt "@label Header for list of settings."
msgid "Affects"
msgstr "Touche"
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:67
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:66
msgctxt "@label Header for list of settings."
msgid "Affected By"
msgstr "Touché par"
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:157
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:156
msgctxt "@label"
-msgid "This setting is always shared between all extruders. Changing it here will change the value for all extruders"
+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 tous les extrudeurs. Le modifier ici entraînera la modification de la valeur pour tous les extrudeurs."
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:160
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:159
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:186
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:190
msgctxt "@label"
msgid ""
"This setting has a value that is different from the profile.\n"
"\n"
"Click to restore the value of the profile."
-msgstr "Ce paramètre possède une valeur qui est différente du profil.\n\nCliquez pour restaurer la valeur du profil."
+msgstr ""
+"Ce paramètre possède une valeur qui est différente du profil.\n"
+"\n"
+"Cliquez pour restaurer la valeur du profil."
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:284
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:288
msgctxt "@label"
msgid ""
"This setting is normally calculated, but it currently has an absolute value set.\n"
"\n"
"Click to restore the calculated value."
-msgstr "Ce paramètre est normalement calculé mais il possède actuellement une valeur absolue définie.\n\nCliquez pour restaurer la valeur calculée."
+msgstr ""
+"Ce paramètre est normalement calculé mais il possède actuellement une valeur absolue définie.\n"
+"\n"
+"Cliquez pour restaurer la valeur calculée."
-#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:120
+#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:128
msgctxt "@label:listbox"
msgid "Print Setup"
msgstr "Configuration de l'impression"
-#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:120
+#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:128
msgctxt "@label:listbox"
msgid ""
"Print Setup disabled\n"
"G-code files cannot be modified"
-msgstr "Configuration de l'impression désactivée\nLes fichiers G-Code ne peuvent pas être modifiés"
+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/Sidebar.qml:336
+#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:342
msgctxt "@label Hours and minutes"
msgid "00h 00min"
msgstr "00h 00min"
-#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:354
+#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:359
msgctxt "@tooltip"
-msgid "Time specification
"
-msgstr "Spécification de temps
"
+msgid "Time specification"
+msgstr "Spécification de temps"
-#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:429
+#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:441
msgctxt "@label"
msgid "Cost specification"
msgstr "Spécification de coût"
-#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:434
-#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:445
+#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:446
+#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:455
msgctxt "@label m for meter"
msgid "%1m"
msgstr "%1m"
-#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:435
-#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:446
+#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:447
+#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:456
msgctxt "@label g for grams"
msgid "%1g"
msgstr "%1g"
-#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:444
+#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:454
msgctxt "@label"
msgid "Total:"
msgstr "Total :"
-#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:498
+#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:504
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/resources/qml/Sidebar.qml:503
+#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:509
msgctxt "@label Print estimates: m for meters, g for grams"
msgid "%1m / ~ %2g"
msgstr "%1m / ~ %2g"
-#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:586
+#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:591
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/Sidebar.qml:591
+#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:596
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/Menus/MaterialMenu.qml:49
+#: /home/ruben/Projects/Cura/resources/qml/Menus/MaterialMenu.qml:50
msgctxt "@title:menuitem %1 is the automatically selected material"
msgid "Automatic: %1"
msgstr "Automatique : %1"
@@ -3337,6 +3660,16 @@ msgctxt "@title:menu menubar:toplevel"
msgid "&View"
msgstr "&Visualisation"
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ViewMenu.qml:37
+msgctxt "@action:inmenu menubar:view"
+msgid "&Camera position"
+msgstr "Position de la &caméra"
+
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ViewMenu.qml:52
+msgctxt "@action:inmenu menubar:view"
+msgid "&Build plate"
+msgstr "&Plateau"
+
#: /home/ruben/Projects/Cura/resources/qml/Menus/NozzleMenu.qml:40
msgctxt "@title:menuitem %1 is the nozzle currently loaded in the printer"
msgid "Automatic: %1"
@@ -3349,14 +3682,14 @@ msgid_plural "Print Selected Models With:"
msgstr[0] "Imprimer le modèle sélectionné avec :"
msgstr[1] "Imprimer les modèles sélectionnés avec :"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/ContextMenu.qml:83
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ContextMenu.qml:114
msgctxt "@title:window"
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/Menus/ContextMenu.qml:108
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ContextMenu.qml:139
msgctxt "@label"
msgid "Number of Copies"
msgstr "Nombre de copies"
@@ -3372,10 +3705,10 @@ msgid "No printer connected"
msgstr "Aucune imprimante n'est connectée"
#: /home/ruben/Projects/Cura/resources/qml/PrintMonitor.qml:90
-#: /home/ruben/Projects/Cura/resources/qml/SidebarHeader.qml:138
+#: /home/ruben/Projects/Cura/resources/qml/SidebarHeader.qml:139
msgctxt "@label"
msgid "Extruder"
-msgstr "Extrudeuse"
+msgstr "Extrudeur"
#: /home/ruben/Projects/Cura/resources/qml/PrintMonitor.qml:120
msgctxt "@tooltip"
@@ -3482,254 +3815,294 @@ msgctxt "@label"
msgid "Estimated time left"
msgstr "Durée restante estimée"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:72
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:79
msgctxt "@action:inmenu"
msgid "Toggle Fu&ll Screen"
msgstr "Passer en P&lein écran"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:79
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:86
msgctxt "@action:inmenu menubar:edit"
msgid "&Undo"
msgstr "&Annuler"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:89
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:96
msgctxt "@action:inmenu menubar:edit"
msgid "&Redo"
msgstr "&Rétablir"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:99
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:106
msgctxt "@action:inmenu menubar:file"
msgid "&Quit"
msgstr "&Quitter"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:107
-msgctxt "@action:inmenu menubar:view"
-msgid "&Reset camera position"
-msgstr "&Réinitialiser la position de la caméra"
-
#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:114
+msgctxt "@action:inmenu menubar:view"
+msgid "&3D View"
+msgstr "Vue &3D"
+
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:121
+msgctxt "@action:inmenu menubar:view"
+msgid "&Front View"
+msgstr "Vue de &face"
+
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:128
+msgctxt "@action:inmenu menubar:view"
+msgid "&Top View"
+msgstr "Vue du dess&us"
+
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:135
+msgctxt "@action:inmenu menubar:view"
+msgid "&Left Side View"
+msgstr "Vue latérale &gauche"
+
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:142
+msgctxt "@action:inmenu menubar:view"
+msgid "&Right Side View"
+msgstr "Vue latérale &droite"
+
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:149
msgctxt "@action:inmenu"
msgid "Configure Cura..."
msgstr "Configurer Cura..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:121
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:156
msgctxt "@action:inmenu menubar:printer"
msgid "&Add Printer..."
msgstr "&Ajouter une imprimante..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:127
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:162
msgctxt "@action:inmenu menubar:printer"
msgid "Manage Pr&inters..."
msgstr "Gérer les &imprimantes..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:134
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:169
msgctxt "@action:inmenu"
msgid "Manage Materials..."
msgstr "Gérer les matériaux..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:142
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:177
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:150
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:185
msgctxt "@action:inmenu menubar:profile"
msgid "&Discard current changes"
msgstr "&Ignorer les modifications actuelles"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:162
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:197
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:168
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:203
msgctxt "@action:inmenu menubar:profile"
msgid "Manage Profiles..."
msgstr "Gérer les profils..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:175
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:210
msgctxt "@action:inmenu menubar:help"
msgid "Show Online &Documentation"
msgstr "Afficher la &documentation en ligne"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:183
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:218
msgctxt "@action:inmenu menubar:help"
msgid "Report a &Bug"
msgstr "Notifier un &bug"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:191
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:226
msgctxt "@action:inmenu menubar:help"
msgid "&About..."
msgstr "&À propos de..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:198
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:233
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:208
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:243
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:217
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:252
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:226
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:261
msgctxt "@action:inmenu"
msgid "Delete Model"
msgstr "Supprimer le modèle"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:234
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:269
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:240
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:275
msgctxt "@action:inmenu menubar:edit"
msgid "&Group Models"
msgstr "&Grouper les modèles"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:250
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:295
msgctxt "@action:inmenu menubar:edit"
msgid "Ungroup Models"
msgstr "Dégrouper les modèles"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:260
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:305
msgctxt "@action:inmenu menubar:edit"
msgid "&Merge Models"
msgstr "&Fusionner les modèles"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:270
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:315
msgctxt "@action:inmenu"
msgid "&Multiply Model..."
msgstr "&Multiplier le modèle..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:277
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:322
msgctxt "@action:inmenu menubar:edit"
msgid "&Select All Models"
msgstr "&Sélectionner tous les modèles"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:287
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:332
msgctxt "@action:inmenu menubar:edit"
msgid "&Clear Build Plate"
msgstr "&Supprimer les objets du plateau"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:297
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:342
msgctxt "@action:inmenu menubar:file"
msgid "Re&load All Models"
msgstr "Rechar&ger tous les modèles"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:306
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:351
+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:358
msgctxt "@action:inmenu menubar:edit"
msgid "Arrange All Models"
msgstr "Réorganiser tous les modèles"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:314
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:366
msgctxt "@action:inmenu menubar:edit"
msgid "Arrange Selection"
msgstr "Réorganiser la sélection"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:321
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:373
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:328
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:380
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:335
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:387
msgctxt "@action:inmenu menubar:file"
msgid "&Open File(s)..."
msgstr "&Ouvrir le(s) fichier(s)..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:343
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:395
msgctxt "@action:inmenu menubar:file"
msgid "&New Project..."
msgstr "&Nouveau projet..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:350
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:402
msgctxt "@action:inmenu menubar:help"
msgid "Show Engine &Log..."
msgstr "Afficher le &journal du moteur..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:358
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:410
msgctxt "@action:inmenu menubar:help"
msgid "Show Configuration Folder"
msgstr "Afficher le dossier de configuration"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:365
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:417
msgctxt "@action:menu"
msgid "Configure setting visibility..."
msgstr "Configurer la visibilité des paramètres..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:372
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:424
msgctxt "@action:menu"
msgid "Browse plugins..."
msgstr "Parcourir les plug-ins..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:379
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:431
msgctxt "@action:menu"
msgid "Installed plugins..."
msgstr "Plug-ins installés..."
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:28
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:438
+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:26
msgctxt "@label:PrintjobStatus"
msgid "Please load a 3D model"
msgstr "Veuillez charger un modèle 3D"
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:34
+#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:36
msgctxt "@label:PrintjobStatus"
msgid "Ready to slice"
msgstr "Prêt à découper"
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:36
+#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:38
msgctxt "@label:PrintjobStatus"
msgid "Slicing..."
msgstr "Découpe en cours..."
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:38
+#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:40
msgctxt "@label:PrintjobStatus %1 is target operation"
msgid "Ready to %1"
msgstr "Prêt à %1"
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:40
+#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:42
msgctxt "@label:PrintjobStatus"
msgid "Unable to Slice"
msgstr "Impossible de découper"
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:42
+#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:44
msgctxt "@label:PrintjobStatus"
msgid "Slicing unavailable"
msgstr "Découpe indisponible"
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:162
+#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:171
+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:171
+msgctxt "@info:tooltip"
+msgid "Cancel slicing process"
+msgstr "Annuler le processus de découpe"
+
+#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:183
msgctxt "@label:Printjob"
msgid "Prepare"
msgstr "Préparer"
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:162
+#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:183
msgctxt "@label:Printjob"
msgid "Cancel"
msgstr "Annuler"
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:302
+#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:317
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:620
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:696
msgctxt "@title:window"
msgid "Open file(s)"
msgstr "Ouvrir le(s) fichier(s)"
@@ -3749,114 +4122,114 @@ msgctxt "@title:window"
msgid "Ultimaker Cura"
msgstr "Ultimaker Cura"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:81
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:102
msgctxt "@title:menu menubar:toplevel"
msgid "&File"
msgstr "&Fichier"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:98
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:119
msgctxt "@action:inmenu menubar:file"
msgid "&Save Selection to File"
msgstr "Enregi&strer la sélection dans un fichier"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:107
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:128
msgctxt "@title:menu menubar:file"
msgid "Save &As..."
msgstr "Enregistrer &sous..."
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:118
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:139
msgctxt "@title:menu menubar:file"
-msgid "Save project"
-msgstr "Enregistrer le projet"
+msgid "Save &Project..."
+msgstr "Enregistrer le &projet..."
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:141
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:162
msgctxt "@title:menu menubar:toplevel"
msgid "&Edit"
msgstr "&Modifier"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:158
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:179
msgctxt "@title:menu"
msgid "&View"
msgstr "&Visualisation"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:163
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:184
msgctxt "@title:menu"
msgid "&Settings"
msgstr "&Paramètres"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:165
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:186
msgctxt "@title:menu menubar:toplevel"
msgid "&Printer"
msgstr "Im&primante"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:175
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:187
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:196
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:208
msgctxt "@title:menu"
msgid "&Material"
msgstr "&Matériau"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:176
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:188
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:197
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:209
msgctxt "@title:menu"
msgid "&Profile"
msgstr "&Profil"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:180
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:201
msgctxt "@action:inmenu"
msgid "Set as Active Extruder"
msgstr "Définir comme extrudeur actif"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:198
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:219
msgctxt "@title:menu menubar:toplevel"
msgid "E&xtensions"
msgstr "E&xtensions"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:232
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:253
msgctxt "@title:menu menubar:toplevel"
msgid "P&lugins"
msgstr "&Plug-ins"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:240
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:261
msgctxt "@title:menu menubar:toplevel"
msgid "P&references"
msgstr "P&références"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:248
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:269
msgctxt "@title:menu menubar:toplevel"
msgid "&Help"
msgstr "&Aide"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:330
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:351
msgctxt "@action:button"
msgid "Open File"
msgstr "Ouvrir un fichier"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:442
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:512
msgctxt "@title:tab"
msgid "Settings"
msgstr "Paramètres"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:478
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:554
msgctxt "@title:window"
msgid "New project"
msgstr "Nouveau projet"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:479
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:555
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."
+msgstr "Êtes-vous sûr(e) de vouloir commencer 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:721
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:797
msgctxt "@window:title"
msgid "Install Plugin"
msgstr "Installer plug-in"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:728
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:804
msgctxt "@title:window"
msgid "Open File(s)"
msgstr "Ouvrir le(s) fichier(s)"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:731
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:807
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."
@@ -3869,7 +4242,7 @@ msgstr "Enregistrer le projet"
#: /home/ruben/Projects/Cura/resources/qml/WorkspaceSummaryDialog.qml:136
msgctxt "@action:label"
msgid "Extruder %1"
-msgstr "Extrudeuse %1"
+msgstr "Extrudeur %1"
#: /home/ruben/Projects/Cura/resources/qml/WorkspaceSummaryDialog.qml:146
msgctxt "@action:label"
@@ -3881,97 +4254,82 @@ 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:264
-msgctxt "@action:button"
-msgid "Save"
-msgstr "Enregistrer"
-
-#: /home/ruben/Projects/Cura/resources/qml/Topbar.qml:74
-msgctxt "@title:tab"
-msgid "Prepare"
-msgstr "Préparer"
-
-#: /home/ruben/Projects/Cura/resources/qml/Topbar.qml:100
-msgctxt "@title:tab"
-msgid "Monitor"
-msgstr "Surveiller"
-
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:163
+#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:175
msgctxt "@label"
msgid "Layer Height"
msgstr "Hauteur de la couche"
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:323
+#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:345
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:340
+#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:362
msgctxt "@label"
msgid "Print Speed"
msgstr "Vitesse d’impression"
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:350
+#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:374
msgctxt "@label"
msgid "Slower"
msgstr "Ralentir"
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:361
+#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:385
msgctxt "@label"
msgid "Faster"
msgstr "Accélérer"
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:388
+#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:423
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:413
+#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:446
msgctxt "@label"
msgid "Infill"
msgstr "Remplissage"
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:633
+#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:668
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:645
+#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:680
msgctxt "@label"
msgid "Enable gradual"
msgstr "Permettre le remplissage graduel"
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:712
+#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:747
msgctxt "@label"
msgid "Generate Support"
msgstr "Générer les supports"
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:746
+#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:781
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."
+msgstr "Générer des supports pour soutenir les parties du modèle qui possèdent des porte-à-faux. Sans ces supports, ces parties s'effondreront durant l'impression."
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:764
+#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:799
msgctxt "@label"
msgid "Support Extruder"
-msgstr "Extrudeuse de soutien"
+msgstr "Extrudeur pour matériau support"
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:816
+#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:851
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:839
+#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:874
msgctxt "@label"
msgid "Build Plate Adhesion"
msgstr "Adhérence au plateau"
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:894
+#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:929
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."
+msgstr "Activez l'impression du Brim ou Raft. Cela ajoutera une zone plate autour de ou sous votre objet qui est facile à retirer par la suite."
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:934
+#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:969
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"
@@ -3988,17 +4346,22 @@ msgctxt "@title:window"
msgid "Open project file"
msgstr "Ouvrir un fichier de projet"
-#: /home/ruben/Projects/Cura/resources/qml/AskOpenAsProjectOrModelsDialog.qml:72
+#: /home/ruben/Projects/Cura/resources/qml/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
+msgctxt "@text:window"
+msgid "Remember my choice"
+msgstr "Se souvenir de mon choix"
+
+#: /home/ruben/Projects/Cura/resources/qml/AskOpenAsProjectOrModelsDialog.qml:122
msgctxt "@action:button"
msgid "Open as project"
msgstr "Ouvrir comme projet"
-#: /home/ruben/Projects/Cura/resources/qml/AskOpenAsProjectOrModelsDialog.qml:122
+#: /home/ruben/Projects/Cura/resources/qml/AskOpenAsProjectOrModelsDialog.qml:131
msgctxt "@action:button"
msgid "Import models"
msgstr "Importer les modèles"
@@ -4008,21 +4371,36 @@ msgctxt "@title:window"
msgid "Engine Log"
msgstr "Journal du moteur"
-#: /home/ruben/Projects/Cura/resources/qml/SidebarHeader.qml:242
+#: /home/ruben/Projects/Cura/resources/qml/SidebarHeader.qml:245
msgctxt "@label"
msgid "Material"
msgstr "Matériau"
-#: /home/ruben/Projects/Cura/resources/qml/SidebarHeader.qml:349
+#: /home/ruben/Projects/Cura/resources/qml/SidebarHeader.qml:352
msgctxt "@label"
-msgid "Check compatibility"
-msgstr "Vérifier la compatibilité"
+msgid "Check compatibility"
+msgstr "Vérifier la compatibilité"
-#: /home/ruben/Projects/Cura/resources/qml/SidebarHeader.qml:369
+#: /home/ruben/Projects/Cura/resources/qml/SidebarHeader.qml:372
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/ObjectsList.qml:211
+msgctxt "@option:check"
+msgid "See only current build plate"
+msgstr "Afficher uniquement le plateau actuel"
+
+#: /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/ObjectsList.qml:247
+msgctxt "@action:button"
+msgid "Arrange current build plate"
+msgstr "Réorganiser le plateau actuel"
+
#: MachineSettingsAction/plugin.json
msgctxt "description"
msgid "Provides a way to change machine settings (such as build volume, nozzle size, etc)"
@@ -4113,6 +4491,26 @@ msgctxt "name"
msgid "USB printing"
msgstr "Impression par USB"
+#: PrepareStage/plugin.json
+msgctxt "description"
+msgid "Provides a prepare stage in Cura."
+msgstr "Fournit une étape de préparation dans Cura."
+
+#: PrepareStage/plugin.json
+msgctxt "name"
+msgid "Prepare Stage"
+msgstr "Étape de préparation"
+
+#: CuraLiveScriptingPlugin/plugin.json
+msgctxt "description"
+msgid "Provides an edit window for direct script editing."
+msgstr "Fournit une fenêtre d'édition pour l'édition directe de script."
+
+#: CuraLiveScriptingPlugin/plugin.json
+msgctxt "name"
+msgid "Live scripting tool"
+msgstr "Outil de scripting en direct"
+
#: RemovableDriveOutputDevice/plugin.json
msgctxt "description"
msgid "Provides removable drive hotplugging and writing support."
@@ -4133,6 +4531,16 @@ msgctxt "name"
msgid "UM3 Network Connection"
msgstr "Connexion au réseau UM3"
+#: MonitorStage/plugin.json
+msgctxt "description"
+msgid "Provides a monitor stage in Cura."
+msgstr "Fournit une étape de surveillance dans Cura."
+
+#: MonitorStage/plugin.json
+msgctxt "name"
+msgid "Monitor Stage"
+msgstr "Étape de surveillance"
+
#: FirmwareUpdateChecker/plugin.json
msgctxt "description"
msgid "Checks for firmware updates."
@@ -4141,12 +4549,12 @@ msgstr "Vérifie les mises à jour du firmware."
#: FirmwareUpdateChecker/plugin.json
msgctxt "name"
msgid "Firmware Update Checker"
-msgstr "Vérificateur des mises à jour du firmware"
+msgstr "Vérification des mises à jour du firmware"
#: CuraSolidWorksPlugin/plugin.json
msgctxt "description"
-msgid "Gives you the possibility to open certain files via SolidWorks itself. These are then converted and loaded into Cura"
-msgstr "Donne la possibilité d'ouvrir certains fichiers via SolidWorks. Ces fichiers sont ensuite convertis et chargés dans Cura."
+msgid "Gives you the possibility to open certain files using SolidWorks itself. Conversion is done by this plugin and additional optimizations."
+msgstr "Donne la possibilité d'ouvrir certains fichiers via SolidWorks. La conversion est ensuite effectuée par ce plug-in et des optimisations supplémentaires."
#: CuraSolidWorksPlugin/plugin.json
msgctxt "name"
@@ -4201,7 +4609,7 @@ msgstr "Offre la possibilité de lire et d'écrire des profils matériels basés
#: XmlMaterialProfile/plugin.json
msgctxt "name"
msgid "Material Profiles"
-msgstr "Profils matériels"
+msgstr "Profils matériaux"
#: LegacyProfileReader/plugin.json
msgctxt "description"
@@ -4213,6 +4621,16 @@ msgctxt "name"
msgid "Legacy Cura Profile Reader"
msgstr "Lecteur de profil Cura antérieur"
+#: CuraBlenderPlugin/plugin.json
+msgctxt "description"
+msgid "Helps to open Blender files directly in Cura."
+msgstr "Aide à ouvrir les fichiers Blender directement dans Cura."
+
+#: CuraBlenderPlugin/plugin.json
+msgctxt "name"
+msgid "Blender Integration (experimental)"
+msgstr "Intégration Blender (expérimental)"
+
#: GCodeProfileReader/plugin.json
msgctxt "description"
msgid "Provides support for importing profiles from g-code files."
@@ -4321,7 +4739,7 @@ msgstr "Vous aide à installer un bouton « exporter vers Cura » dans Siemens
#: cura-siemensnx-plugin/plugin.json
msgctxt "name"
msgid "Siemens NX Integration"
-msgstr "Siemens NX Integration"
+msgstr "Intégration Siemens NX"
#: 3MFReader/plugin.json
msgctxt "description"
@@ -4373,6 +4791,16 @@ msgctxt "name"
msgid "Cura Profile Writer"
msgstr "Générateur de profil Cura"
+#: CuraPrintProfileCreator/plugin.json
+msgctxt "description"
+msgid "Allows material manufacturers to create new material and quality profiles using a drop-in UI."
+msgstr "Permet aux fabricants de matériaux de créer de nouveaux matériaux et profils de qualité à l'aide d'une interface utilisateur ad hoc."
+
+#: CuraPrintProfileCreator/plugin.json
+msgctxt "name"
+msgid "Print Profile Assistant"
+msgstr "Assistant de profil d'impression"
+
#: 3MFWriter/plugin.json
msgctxt "description"
msgid "Provides support for writing 3MF files."
@@ -4386,17 +4814,17 @@ msgstr "Générateur 3MF"
#: UserAgreementPlugin/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"
+msgstr "Demander à l'utilisateur une fois s'il est d'accord avec les termes de notre licence"
#: UserAgreementPlugin/plugin.json
msgctxt "name"
msgid "UserAgreement"
-msgstr "UserAgreement"
+msgstr "Accord de l'utilisateur"
#: UltimakerMachineActions/plugin.json
msgctxt "description"
msgid "Provides machine actions for Ultimaker machines (such as bed leveling wizard, selecting upgrades, etc)"
-msgstr "Fournit les actions de la machine pour les machines Ultimaker (telles que l'assistant de calibration du plateau, sélection des mises à niveau, etc.)"
+msgstr "Fournit les actions de la machine pour les machines Ultimaker (tels que l'assistant de calibration du plateau, sélection des mises à niveau, etc.)"
#: UltimakerMachineActions/plugin.json
msgctxt "name"
@@ -4413,6 +4841,156 @@ msgctxt "name"
msgid "Cura Profile Reader"
msgstr "Lecteur de profil Cura"
+#~ msgctxt "@label"
+#~ msgid "Unknown"
+#~ msgstr "Inconnu"
+
+#~ msgctxt "@info:status"
+#~ msgid "Errors appeared while opening your SolidWorks file! Please check, whether it is possible to open your file in SolidWorks itself without any problems as well!"
+#~ msgstr "Des erreurs sont apparues lors de l'ouverture de votre fichier SolidWorks ! Veuillez vérifier s'il est possible d'ouvrir votre fichier dans SolidWorks sans que cela ne cause de problèmes."
+
+#~ msgctxt "@info:status"
+#~ msgid "Error while starting %s!"
+#~ msgstr "Erreur lors du lancement de %s !"
+
+#~ msgctxt "@item:inlistbox"
+#~ msgid "Simulation view"
+#~ msgstr "Vue simulation"
+
+#~ msgctxt "@info"
+#~ msgid "Cura collects anonymised slicing statistics. You can disable this in the preferences."
+#~ msgstr "Cura collecte des statistiques anonymes sur le découpage. Vous pouvez désactiver cette fonctionnalité dans les préférences."
+
+#~ msgctxt "@action:button"
+#~ msgid "Dismiss"
+#~ msgstr "Ignorer"
+
+#~ msgctxt "@menuitem"
+#~ msgid "Global"
+#~ msgstr "Global"
+
+#~ msgctxt "@label crash message"
+#~ msgid ""
+#~ "
A fatal exception has occurred. Please send us this Crash Report to fix the problem
\n"
+#~ "
Please use the \"Send report\" button to post a bug report automatically to our servers
\n"
+#~ " "
+#~ msgstr ""
+#~ "
Une exception fatale s'est produite. Veuillez nous envoyer ce Rapport d'incident pour résoudre le problème
\n"
+#~ "
Veuillez utiliser le bouton « Envoyer rapport » pour publier automatiquement un rapport d'erreur sur nos serveurs
\n"
+#~ " "
+
+#~ msgctxt "@label Cura version"
+#~ msgid "Cura version: {version} "
+#~ msgstr "Version Cura : {version} "
+
+#~ msgctxt "@label Platform"
+#~ msgid "Platform: {platform} "
+#~ msgstr "Plateforme : {platform} "
+
+#~ msgctxt "@label Qt version"
+#~ msgid "Qt version: {qt} "
+#~ msgstr "Version Qt : {qt} "
+
+#~ msgctxt "@label PyQt version"
+#~ msgid "PyQt version: {pyqt} "
+#~ msgstr "Version PyQt : {pyqt} "
+
+#~ msgctxt "@label OpenGL"
+#~ msgid "OpenGL: {opengl} "
+#~ msgstr "OpenGL : {opengl} "
+
+#~ msgctxt "@title:groupbox"
+#~ msgid "Exception traceback"
+#~ msgstr "Retraçage de l'exception"
+
+#~ msgctxt "@label"
+#~ msgid "Material diameter"
+#~ msgstr "Diamètre du matériau"
+
+#~ msgctxt "@label"
+#~ msgid "Ultimaker 3"
+#~ msgstr "Ultimaker 3"
+
+#~ msgctxt "@label"
+#~ msgid "Ultimaker 3 Extended"
+#~ msgstr "Ultimaker 3 Extended"
+
+#~ msgctxt "@title:window"
+#~ msgid "Cura SolidWorks Plugin Configuration"
+#~ msgstr "Configuration du plug-in Cura SolidWorks"
+
+#~ msgctxt "@action:label"
+#~ msgid "Default quality of the exported STL:"
+#~ msgstr "Qualité par défaut du STL exporté :"
+
+#~ msgctxt "@option:curaSolidworksStlQuality"
+#~ msgid "Always ask"
+#~ msgstr "Toujours demander"
+
+#~ msgctxt "@option:curaSolidworksStlQuality"
+#~ msgid "Always use Fine quality"
+#~ msgstr "Toujours utiliser la qualité Fine"
+
+#~ msgctxt "@option:curaSolidworksStlQuality"
+#~ msgid "Always use Coarse quality"
+#~ msgstr "Toujours utiliser la qualité grossière"
+
+#~ msgctxt "@title:window"
+#~ msgid "Import SolidWorks File as STL..."
+#~ msgstr "Importer le fichier SolidWorks comme STL..."
+
+#~ msgctxt "@info:tooltip"
+#~ msgid "Quality of the Exported STL"
+#~ msgstr "Qualité du STL exporté"
+
+#~ msgctxt "@action:label"
+#~ msgid "Quality"
+#~ msgstr "Qualité"
+
+#~ msgctxt "@option:curaSolidworksStlQuality"
+#~ msgid "Coarse"
+#~ msgstr "Grossière"
+
+#~ msgctxt "@option:curaSolidworksStlQuality"
+#~ msgid "Fine"
+#~ msgstr "Fine"
+
+#~ msgctxt "@"
+#~ msgid "No Profile Available"
+#~ msgstr "Aucun profil disponible"
+
+#~ 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 tous les extrudeurs. Le modifier ici entraînera la modification de la valeur pour tous les extrudeurs."
+
+#~ msgctxt "@tooltip"
+#~ msgid "Time specification
"
+#~ msgstr "Spécification de temps
"
+
+#~ msgctxt "@action:inmenu menubar:view"
+#~ msgid "&Reset camera position"
+#~ msgstr "&Réinitialiser la position de la caméra"
+
+#~ msgctxt "@title:menu menubar:file"
+#~ msgid "Save project"
+#~ msgstr "Enregistrer le projet"
+
+#~ msgctxt "@title:tab"
+#~ msgid "Prepare"
+#~ msgstr "Préparer"
+
+#~ msgctxt "@title:tab"
+#~ msgid "Monitor"
+#~ msgstr "Surveiller"
+
+#~ msgctxt "@label"
+#~ msgid "Check compatibility"
+#~ msgstr "Vérifier la compatibilité"
+
+#~ msgctxt "description"
+#~ msgid "Gives you the possibility to open certain files via SolidWorks itself. These are then converted and loaded into Cura"
+#~ msgstr "Donne la possibilité d'ouvrir certains fichiers via SolidWorks. Ces fichiers sont ensuite convertis et chargés dans Cura."
+
#~ msgctxt "@label:status"
#~ msgid "Blocked"
#~ msgstr "Bloqué"
@@ -4433,13 +5011,9 @@ msgstr "Lecteur de profil Cura"
#~ msgid "To ensure that your {machine_name} is equipped with the latest features it is recommended to update the firmware regularly. This can be done on the {machine_name} (when connected to the network) or via USB."
#~ msgstr "Pour s'assurer que votre {machine_name} est pourvue des dernières fonctionnalités, il est recommandé de mettre régulièrement à jour le firmware. Cela peut se faire sur la {machine_name} (lorsque connectée au réseau) ou via USB."
-msgctxt "@item:inlistbox"
-msgid "Layer view"
-msgstr "Vue en couches"
-
-msgctxt "@info:title"
-msgid "Layer View"
-msgstr "Vue en couches"
+#~ msgctxt "@info:title"
+#~ msgid "Layer View"
+#~ msgstr "Vue en couches"
#~ msgctxt "@menuitem"
#~ msgid "Browse plugins"
@@ -4541,9 +5115,9 @@ msgstr "Vue en couches"
#~ msgid "Provides the Layer view."
#~ msgstr "Permet la vue en couches."
-msgctxt "name"
-msgid "Layer View"
-msgstr "Vue en couches"
+#~ msgctxt "name"
+#~ msgid "Layer View"
+#~ msgstr "Vue en couches"
#~ msgctxt "@item:inlistbox"
#~ msgid "X-Ray"
@@ -4864,9 +5438,9 @@ msgstr "Vue en couches"
#~ msgid "Provides support for importing profiles from g-code files."
#~ msgstr "Fournit la prise en charge de l'importation de profils à partir de fichiers g-code."
-msgctxt "@label"
-msgid "Layer View"
-msgstr "Vue en couches"
+#~ msgctxt "@label"
+#~ msgid "Layer View"
+#~ msgstr "Vue en couches"
#~ msgctxt "@info:whatsthis"
#~ msgid "Provides the Layer view."
diff --git a/resources/i18n/fr_FR/fdmextruder.def.json.po b/resources/i18n/fr_FR/fdmextruder.def.json.po
index fdec72de32..ead5e0a87b 100644
--- a/resources/i18n/fr_FR/fdmextruder.def.json.po
+++ b/resources/i18n/fr_FR/fdmextruder.def.json.po
@@ -2,12 +2,12 @@
# Copyright (C) 2017 Ultimaker
# This file is distributed under the same license as the Cura package.
# Ruben Dulek , 2017.
-#
+#
msgid ""
msgstr ""
"Project-Id-Version: Cura 3.0\n"
-"Report-Msgid-Bugs-To: http://github.com/ultimaker/uranium\n"
-"POT-Creation-Date: 2017-11-21 16:58+0000\n"
+"Report-Msgid-Bugs-To: r.dulek@ultimaker.com\n"
+"POT-Creation-Date: 2017-08-02 16:53+0000\n"
"PO-Revision-Date: 2017-11-30 13:05+0100\n"
"Last-Translator: Bothof \n"
"Language-Team: French\n"
diff --git a/resources/i18n/fr_FR/fdmprinter.def.json.po b/resources/i18n/fr_FR/fdmprinter.def.json.po
index 0e768253dc..35731b8312 100644
--- a/resources/i18n/fr_FR/fdmprinter.def.json.po
+++ b/resources/i18n/fr_FR/fdmprinter.def.json.po
@@ -1,20 +1,21 @@
-# Cura JSON setting files
-# Copyright (C) 2017 Ultimaker
+# Cura
+# Copyright (C) 2018 Ultimaker
# This file is distributed under the same license as the Cura package.
-# Ruben Dulek , 2017.
-#
+# Ruben Dulek , 2018.
+#
msgid ""
msgstr ""
-"Project-Id-Version: Cura 3.0\n"
-"Report-Msgid-Bugs-To: http://github.com/ultimaker/uranium\n"
-"POT-Creation-Date: 2017-11-21 16:58+0000\n"
-"PO-Revision-Date: 2017-11-30 13:05+0100\n"
+"Project-Id-Version: Cura 3.2\n"
+"Report-Msgid-Bugs-To: r.dulek@ultimaker.com\n"
+"POT-Creation-Date: 2018-01-29 09:48+0000\n"
+"PO-Revision-Date: 2018-02-13 15:31+0100\n"
"Last-Translator: Bothof \n"
"Language-Team: 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"
#: fdmprinter.def.json
msgctxt "machine_settings label"
@@ -56,7 +57,9 @@ msgctxt "machine_start_gcode description"
msgid ""
"Gcode commands to be executed at the very start - separated by \n"
"."
-msgstr "Commandes Gcode à exécuter au tout début, séparées par \n."
+msgstr ""
+"Commandes Gcode à exécuter au tout début, séparées par \n"
+"."
#: fdmprinter.def.json
msgctxt "machine_end_gcode label"
@@ -68,17 +71,19 @@ msgctxt "machine_end_gcode description"
msgid ""
"Gcode commands to be executed at the very end - separated by \n"
"."
-msgstr "Commandes Gcode à exécuter à la toute fin, séparées par \n."
+msgstr ""
+"Commandes Gcode à exécuter à la toute fin, séparées par \n"
+"."
#: fdmprinter.def.json
msgctxt "material_guid label"
msgid "Material GUID"
-msgstr "GUID matériau"
+msgstr "Identification GUID du matériau"
#: fdmprinter.def.json
msgctxt "material_guid description"
msgid "GUID of the material. This is set automatically. "
-msgstr "GUID du matériau. Cela est configuré automatiquement. "
+msgstr "Identification GUID du matériau. Cela est configuré automatiquement. "
#: fdmprinter.def.json
msgctxt "material_bed_temp_wait label"
@@ -148,7 +153,7 @@ msgstr "Forme du plateau"
#: fdmprinter.def.json
msgctxt "machine_shape description"
msgid "The shape of the build plate without taking unprintable areas into account."
-msgstr "La forme du plateau sans prendre les zones non imprimables en compte."
+msgstr "La forme du plateau sans prendre en compte les zones non imprimables."
#: fdmprinter.def.json
msgctxt "machine_shape option rectangular"
@@ -173,12 +178,12 @@ msgstr "La hauteur (sens Z) de la zone imprimable."
#: fdmprinter.def.json
msgctxt "machine_heated_bed label"
msgid "Has Heated Build Plate"
-msgstr "A un plateau chauffé"
+msgstr "A un plateau chauffant"
#: fdmprinter.def.json
msgctxt "machine_heated_bed description"
msgid "Whether the machine has a heated build plate present."
-msgstr "Si la machine a un plateau chauffé présent."
+msgstr "Si la machine a un plateau chauffant existant."
#: fdmprinter.def.json
msgctxt "machine_center_is_zero label"
@@ -198,7 +203,7 @@ msgstr "Nombre d'extrudeuses"
#: fdmprinter.def.json
msgctxt "machine_extruder_count description"
msgid "Number of extruder trains. An extruder train is the combination of a feeder, bowden tube, and nozzle."
-msgstr "Nombre de trains d'extrudeuse. Un train d'extrudeuse est la combinaison d'un chargeur, d'un tube bowden et d'une buse."
+msgstr "Nombre de systèmes d'extrusion. Un système d'extrusion est la combinaison d'un feeder, d'un tube bowden et d'une buse."
#: fdmprinter.def.json
msgctxt "machine_nozzle_tip_outer_diameter label"
@@ -238,7 +243,7 @@ msgstr "Longueur de la zone chauffée"
#: fdmprinter.def.json
msgctxt "machine_heat_zone_length description"
msgid "The distance from the tip of the nozzle in which heat from the nozzle is transferred to the filament."
-msgstr "Distance depuis la pointe du bec d'impression sur laquelle la chaleur du bec d'impression est transférée au filament."
+msgstr "Distance depuis la pointe de la buse sur laquelle la chaleur de la buse est transférée au filament."
#: fdmprinter.def.json
msgctxt "machine_filament_park_distance label"
@@ -248,7 +253,7 @@ msgstr "Distance de stationnement du filament"
#: fdmprinter.def.json
msgctxt "machine_filament_park_distance description"
msgid "The distance from the tip of the nozzle where to park the filament when an extruder is no longer used."
-msgstr "Distance depuis la pointe du bec sur laquelle stationner le filament lorsqu'une extrudeuse n'est plus utilisée."
+msgstr "Distance depuis la pointe de la buse sur laquelle stationne le filament lorsqu'une extrudeuse n'est plus utilisée."
#: fdmprinter.def.json
msgctxt "machine_nozzle_temp_enabled label"
@@ -263,7 +268,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"
-msgstr "Vitesse de chauffage"
+msgstr "Vitesse de chauffe"
#: fdmprinter.def.json
msgctxt "machine_nozzle_heat_up_speed description"
@@ -283,7 +288,7 @@ msgstr "La vitesse (°C/s) à laquelle la buse refroidit, sur une moyenne de la
#: fdmprinter.def.json
msgctxt "machine_min_cool_heat_time_window label"
msgid "Minimal Time Standby Temperature"
-msgstr "Durée minimale température de veille"
+msgstr "Température minimale de veille"
#: fdmprinter.def.json
msgctxt "machine_min_cool_heat_time_window description"
@@ -345,6 +350,16 @@ msgctxt "machine_gcode_flavor option Repetier"
msgid "Repetier"
msgstr "Repetier"
+#: fdmprinter.def.json
+msgctxt "machine_firmware_retract label"
+msgid "Firmware Retraction"
+msgstr "Rétraction du firmware"
+
+#: fdmprinter.def.json
+msgctxt "machine_firmware_retract description"
+msgid "Whether to use firmware retract commands (G10/G11) instead of using the E property in G1 commands to retract the material."
+msgstr "S'il faut utiliser les commandes de rétraction du firmware (G10 / G11) au lieu d'utiliser la propriété E dans les commandes G1 pour rétracter le matériau."
+
#: fdmprinter.def.json
msgctxt "machine_disallowed_areas label"
msgid "Disallowed areas"
@@ -358,12 +373,12 @@ msgstr "Une liste de polygones comportant les zones dans lesquelles la tête d'i
#: fdmprinter.def.json
msgctxt "nozzle_disallowed_areas label"
msgid "Nozzle Disallowed Areas"
-msgstr "Zones interdites au bec d'impression"
+msgstr "Zones interdites à la buse"
#: fdmprinter.def.json
msgctxt "nozzle_disallowed_areas description"
msgid "A list of polygons with areas the nozzle is not allowed to enter."
-msgstr "Une liste de polygones comportant les zones dans lesquelles le bec n'a pas le droit de pénétrer."
+msgstr "Une liste de polygones comportant les zones dans lesquelles la buse n'a pas le droit de pénétrer."
#: fdmprinter.def.json
msgctxt "machine_head_polygon label"
@@ -373,7 +388,7 @@ msgstr "Polygone de la tête de machine"
#: fdmprinter.def.json
msgctxt "machine_head_polygon description"
msgid "A 2D silhouette of the print head (fan caps excluded)."
-msgstr "Une silhouette 2D de la tête d'impression (sans les capuchons du ventilateur)."
+msgstr "Une silhouette 2D de la tête d'impression (sans les carter du ventilateur)."
#: fdmprinter.def.json
msgctxt "machine_head_with_fans_polygon label"
@@ -383,7 +398,7 @@ msgstr "Tête de la machine et polygone du ventilateur"
#: fdmprinter.def.json
msgctxt "machine_head_with_fans_polygon description"
msgid "A 2D silhouette of the print head (fan caps included)."
-msgstr "Une silhouette 2D de la tête d'impression (avec les capuchons du ventilateur)."
+msgstr "Une silhouette 2D de la tête d'impression (avec les carters du ventilateur)."
#: fdmprinter.def.json
msgctxt "gantry_height label"
@@ -398,12 +413,12 @@ msgstr "La différence de hauteur entre la pointe de la buse et le système de p
#: fdmprinter.def.json
msgctxt "machine_nozzle_id label"
msgid "Nozzle ID"
-msgstr "ID buse"
+msgstr "ID de la buse"
#: fdmprinter.def.json
msgctxt "machine_nozzle_id description"
msgid "The nozzle ID for an extruder train, such as \"AA 0.4\" and \"BB 0.8\"."
-msgstr "ID buse pour un train d'extrudeuse, comme « AA 0.4 » et « BB 0.8 »."
+msgstr "ID de la buse pour un système d'extrusion, comme « AA 0.4 » et « BB 0.8 »."
#: fdmprinter.def.json
msgctxt "machine_nozzle_size label"
@@ -418,17 +433,17 @@ 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"
-msgstr "Décalage avec extrudeuse"
+msgstr "Offset avec extrudeuse"
#: fdmprinter.def.json
msgctxt "machine_use_extruder_offset_to_offset_coords description"
msgid "Apply the extruder offset to the coordinate system."
-msgstr "Appliquer le décalage de l'extrudeuse au système de coordonnées."
+msgstr "Appliquer l'offset de l'extrudeuse au système de coordonnées."
#: fdmprinter.def.json
msgctxt "extruder_prime_pos_z label"
msgid "Extruder Prime Z Position"
-msgstr "Extrudeuse Position d'amorçage Z"
+msgstr "Position d'amorçage en Z de l'extrudeuse"
#: fdmprinter.def.json
msgctxt "extruder_prime_pos_z description"
@@ -588,7 +603,7 @@ msgstr "Tous les paramètres qui influent sur la résolution de l'impression. Ce
#: fdmprinter.def.json
msgctxt "layer_height label"
msgid "Layer Height"
-msgstr "Hauteur de la couche"
+msgstr "Hauteur de couche"
#: fdmprinter.def.json
msgctxt "layer_height description"
@@ -598,38 +613,13 @@ msgstr "La hauteur de chaque couche en mm. Des valeurs plus élevées créent de
#: fdmprinter.def.json
msgctxt "layer_height_0 label"
msgid "Initial Layer Height"
-msgstr "Hauteur de la couche initiale"
+msgstr "Hauteur de couche initiale"
#: fdmprinter.def.json
msgctxt "layer_height_0 description"
msgid "The height of the initial layer in mm. A thicker initial layer makes adhesion to the build plate easier."
msgstr "La hauteur de la couche initiale en mm. Une couche initiale plus épaisse adhère plus facilement au plateau."
-#: fdmprinter.def.json
-msgctxt "slicing_tolerance label"
-msgid "Slicing Tolerance"
-msgstr "Tolérance à la découpe"
-
-#: fdmprinter.def.json
-msgctxt "slicing_tolerance description"
-msgid "How to slice layers with diagonal surfaces. The areas of a layer can be generated based on where the middle of the layer intersects the surface (Middle). Alternatively each layer can have the areas which fall inside of the volume throughout the height of the layer (Exclusive) or a layer has the areas which fall inside anywhere within the layer (Inclusive). Exclusive retains the most details, Inclusive makes for the best fit and Middle takes the least time to process."
-msgstr "Comment découper des couches avec des surfaces diagonales. Les zones d'une couche peuvent être générées en fonction de l'endroit où le milieu de la couche croise la surface (Milieu). Alternativement, chaque couche peut posséder des zones situées à l'intérieur du volume à travers toute la hauteur de la couche (Exclusif), ou une couche peut avoir des zones situées à l'intérieur à tout endroit dans la couche (Inclusif). L'option Exclusif permet de retenir le plus de détails, Inclusif permet d'obtenir une adaptation optimale et Milieu demande le moins de temps de traitement."
-
-#: fdmprinter.def.json
-msgctxt "slicing_tolerance option middle"
-msgid "Middle"
-msgstr "Milieu"
-
-#: fdmprinter.def.json
-msgctxt "slicing_tolerance option exclusive"
-msgid "Exclusive"
-msgstr "Exclusif"
-
-#: fdmprinter.def.json
-msgctxt "slicing_tolerance option inclusive"
-msgid "Inclusive"
-msgstr "Inclusif"
-
#: fdmprinter.def.json
msgctxt "line_width label"
msgid "Line Width"
@@ -643,12 +633,12 @@ msgstr "Largeur d'une ligne. Généralement, la largeur de chaque ligne doit cor
#: fdmprinter.def.json
msgctxt "wall_line_width label"
msgid "Wall Line Width"
-msgstr "Largeur de ligne de la paroi"
+msgstr "Largeur de ligne de la coque"
#: fdmprinter.def.json
msgctxt "wall_line_width description"
msgid "Width of a single wall line."
-msgstr "Largeur d'une seule ligne de la paroi."
+msgstr "Largeur d'une seule ligne de la paroie."
#: fdmprinter.def.json
msgctxt "wall_line_width_0 label"
@@ -670,16 +660,6 @@ msgctxt "wall_line_width_x description"
msgid "Width of a single wall line for all wall lines except the outermost one."
msgstr "Largeur d'une seule ligne de la paroi pour toutes les lignes de paroi, à l’exception de la ligne la plus externe."
-#: fdmprinter.def.json
-msgctxt "roofing_line_width label"
-msgid "Top Surface Skin Line Width"
-msgstr "Largeur de ligne de couche extérieure de la surface supérieure"
-
-#: fdmprinter.def.json
-msgctxt "roofing_line_width description"
-msgid "Width of a single line of the areas at the top of the print."
-msgstr "Largeur d'une seule ligne de la zone en haut de l'impression."
-
#: fdmprinter.def.json
msgctxt "skin_line_width label"
msgid "Top/Bottom Line Width"
@@ -713,7 +693,7 @@ msgstr "Largeur d'une seule ligne de jupe ou de bordure."
#: fdmprinter.def.json
msgctxt "support_line_width label"
msgid "Support Line Width"
-msgstr "Largeur de ligne de support"
+msgstr "Largeur de ligne des supports"
#: fdmprinter.def.json
msgctxt "support_line_width description"
@@ -733,12 +713,12 @@ msgstr "Largeur d'une seule ligne de plafond ou de bas de support."
#: fdmprinter.def.json
msgctxt "support_roof_line_width label"
msgid "Support Roof Line Width"
-msgstr "Largeur de ligne de plafond de support"
+msgstr "Largeur de ligne du toit de support"
#: fdmprinter.def.json
msgctxt "support_roof_line_width description"
msgid "Width of a single support roof line."
-msgstr "Largeur d'une seule ligne de plafond de support."
+msgstr "Largeur d'une seule ligne de toit de support."
#: fdmprinter.def.json
msgctxt "support_bottom_line_width label"
@@ -788,7 +768,7 @@ msgstr "Extrudeuse de paroi"
#: fdmprinter.def.json
msgctxt "wall_extruder_nr description"
msgid "The extruder train used for printing the walls. This is used in multi-extrusion."
-msgstr "Le train d'extrudeuse utilisé pour l'impression des parois. Cela est utilisé en multi-extrusion."
+msgstr "Le système d'extrusion utilisé pour l'impression des parois. Cela est utilisé en multi-extrusion."
#: fdmprinter.def.json
msgctxt "wall_0_extruder_nr label"
@@ -798,7 +778,7 @@ msgstr "Extrudeuse de paroi externe"
#: fdmprinter.def.json
msgctxt "wall_0_extruder_nr description"
msgid "The extruder train used for printing the outer wall. This is used in multi-extrusion."
-msgstr "Le train d'extrudeuse utilisé pour l'impression des parois externes. Cela est utilisé en multi-extrusion."
+msgstr "Le système d'extrusion utilisé pour l'impression des parois externes. Cela est utilisé en multi-extrusion."
#: fdmprinter.def.json
msgctxt "wall_x_extruder_nr label"
@@ -808,7 +788,7 @@ msgstr "Extrudeuse de paroi interne"
#: fdmprinter.def.json
msgctxt "wall_x_extruder_nr description"
msgid "The extruder train used for printing the inner walls. This is used in multi-extrusion."
-msgstr "Le train d'extrudeuse utilisé pour l'impression des parois internes. Cela est utilisé en multi-extrusion."
+msgstr "Le système d'extrusion utilisé pour l'impression des parois internes. Cela est utilisé en multi-extrusion."
#: fdmprinter.def.json
msgctxt "wall_thickness label"
@@ -848,7 +828,7 @@ msgstr "Extrudeuse de couche extérieure de la surface supérieure"
#: fdmprinter.def.json
msgctxt "roofing_extruder_nr description"
msgid "The extruder train used for printing the top most skin. This is used in multi-extrusion."
-msgstr "Le train d'extrudeuse utilisé pour l'impression de la couche extérieure supérieure. Cela est utilisé en multi-extrusion."
+msgstr "Le système d'extrusion utilisé pour l'impression de la couche extérieure supérieure. Cela est utilisé en multi-extrusion."
#: fdmprinter.def.json
msgctxt "roofing_layer_count label"
@@ -860,41 +840,6 @@ msgctxt "roofing_layer_count description"
msgid "The number of top most skin layers. Usually only one top most layer is sufficient to generate higher quality top surfaces."
msgstr "Nombre de couches extérieures supérieures. En général, une seule couche supérieure est suffisante pour générer des surfaces supérieures de qualité."
-#: fdmprinter.def.json
-msgctxt "roofing_pattern label"
-msgid "Top Surface Skin Pattern"
-msgstr "Motif de couche extérieure de surface supérieure"
-
-#: fdmprinter.def.json
-msgctxt "roofing_pattern description"
-msgid "The pattern of the top most layers."
-msgstr "Le motif des couches supérieures."
-
-#: fdmprinter.def.json
-msgctxt "roofing_pattern option lines"
-msgid "Lines"
-msgstr "Lignes"
-
-#: fdmprinter.def.json
-msgctxt "roofing_pattern option concentric"
-msgid "Concentric"
-msgstr "Concentrique"
-
-#: fdmprinter.def.json
-msgctxt "roofing_pattern option zigzag"
-msgid "Zig Zag"
-msgstr "Zig Zag"
-
-#: fdmprinter.def.json
-msgctxt "roofing_angles label"
-msgid "Top Surface Skin Line Directions"
-msgstr "Sens de lignes de couche extérieure de surface supérieure"
-
-#: fdmprinter.def.json
-msgctxt "roofing_angles description"
-msgid "A list of integer line directions to use when the top surface skin layers use the lines or zig zag pattern. 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 traditional default angles (45 and 135 degrees)."
-msgstr "Une liste de sens de ligne (exprimés en nombres entiers) à utiliser lorsque les couches extérieures de la surface supérieure utilisent le motif en lignes ou en zig zag. Les éléments de la liste sont utilisés de manière séquentielle à mesure de l'avancement des couches. La liste reprend depuis le début lorsque la fin est atteinte. Les éléments de la liste sont séparés par des virgules et la liste entière est encadrée entre crochets. La valeur par défaut est une liste vide, ce qui signifie que les angles traditionnels par défaut seront utilisés (45 et 135 degrés)."
-
#: fdmprinter.def.json
msgctxt "top_bottom_extruder_nr label"
msgid "Top/Bottom Extruder"
@@ -903,7 +848,7 @@ msgstr "Extrudeuse du dessus/dessous"
#: fdmprinter.def.json
msgctxt "top_bottom_extruder_nr description"
msgid "The extruder train used for printing the top and bottom skin. This is used in multi-extrusion."
-msgstr "Le train d'extrudeuse utilisé pour l'impression de la couche extérieure du haut et du bas. Cela est utilisé en multi-extrusion."
+msgstr "Le système d'extrusion utilisé pour l'impression de la couche extérieure du haut et du bas. Cela est utilisé en multi-extrusion."
#: fdmprinter.def.json
msgctxt "top_bottom_thickness label"
@@ -1018,12 +963,22 @@ msgstr "Une liste de sens de ligne (exprimés en nombres entiers) à utiliser lo
#: fdmprinter.def.json
msgctxt "wall_0_inset label"
msgid "Outer Wall Inset"
-msgstr "Insert de paroi externe"
+msgstr "Enchevêtrement de la paroi externe"
#: fdmprinter.def.json
msgctxt "wall_0_inset description"
msgid "Inset applied to the path of the outer wall. If the outer wall is smaller than the nozzle, and printed after the inner walls, use this offset to get the hole in the nozzle to overlap with the inner walls instead of the outside of the model."
-msgstr "Insert appliqué sur le passage de la paroi externe. Si la paroi externe est plus petite que la buse et imprimée après les parois intérieures, utiliser ce décalage pour que le trou dans la buse chevauche les parois internes et non l'extérieur du modèle."
+msgstr "Enchevêtrement appliqué sur le passage de la paroi externe. Si la paroi externe est plus petite que la buse et imprimée après les parois intérieures, utiliser cet Offset pour que le trou dans la buse chevauche les parois internes et non l'extérieur du modèle."
+
+#: fdmprinter.def.json
+msgctxt "optimize_wall_printing_order label"
+msgid "Optimize Wall Printing Order"
+msgstr "Optimiser l'ordre d'impression des parois"
+
+#: fdmprinter.def.json
+msgctxt "optimize_wall_printing_order description"
+msgid "Optimize the order in which walls are printed so as to reduce the number of retractions and the distance travelled. Most parts will benefit from this being enabled but some may actually take longer so please compare the print time estimates with and without optimization."
+msgstr "Optimiser l'ordre dans lequel des parois sont imprimées de manière à réduire le nombre de retraits et les distances parcourues. La plupart des pièces bénéficieront de cette possibilité, mais certaines peuvent en fait prendre plus de temps à l'impression ; veuillez dès lors comparer les estimations de durée d'impression avec et sans optimisation."
#: fdmprinter.def.json
msgctxt "outer_inset_first label"
@@ -1078,12 +1033,12 @@ msgstr "Compenser le débit pour les parties d'une paroi intérieure imprimées
#: fdmprinter.def.json
msgctxt "fill_perimeter_gaps label"
msgid "Fill Gaps Between Walls"
-msgstr "Remplir les trous entre les parois"
+msgstr "Remplir l'espace entre les parois"
#: fdmprinter.def.json
msgctxt "fill_perimeter_gaps description"
msgid "Fills the gaps between walls where no walls fit."
-msgstr "Imprime les remplissages entre les parois lorsqu'aucune paroi ne convient."
+msgstr "Rempli l'espace entre les parois lorsqu'aucune paroi ne convient."
#: fdmprinter.def.json
msgctxt "fill_perimeter_gaps option nowhere"
@@ -1095,6 +1050,16 @@ msgctxt "fill_perimeter_gaps option everywhere"
msgid "Everywhere"
msgstr "Partout"
+#: fdmprinter.def.json
+msgctxt "filter_out_tiny_gaps label"
+msgid "Filter Out Tiny Gaps"
+msgstr "Filtrer les petits espaces"
+
+#: fdmprinter.def.json
+msgctxt "filter_out_tiny_gaps description"
+msgid "Filter out tiny gaps to reduce blobs on outside of model."
+msgstr "Filtrer les petits espaces pour réduire la présence de gouttes à l'extérieur du modèle."
+
#: fdmprinter.def.json
msgctxt "fill_outline_gaps label"
msgid "Print Thin Walls"
@@ -1108,12 +1073,12 @@ msgstr "Imprimer les parties du modèle qui sont horizontalement plus fines que
#: fdmprinter.def.json
msgctxt "xy_offset label"
msgid "Horizontal Expansion"
-msgstr "Vitesse d’impression horizontale"
+msgstr "Expansion horizontale"
#: fdmprinter.def.json
msgctxt "xy_offset description"
msgid "Amount of offset applied to all polygons in each layer. Positive values can compensate for too big holes; negative values can compensate for too small holes."
-msgstr "Le décalage appliqué à tous les polygones dans chaque couche. Une valeur positive peut compenser les trous trop gros ; une valeur négative peut compenser les trous trop petits."
+msgstr "L'offset appliqué à tous les polygones dans chaque couche. Une valeur positive peut compenser les trous trop gros ; une valeur négative peut compenser les trous trop petits."
#: fdmprinter.def.json
msgctxt "xy_offset_layer_0 label"
@@ -1123,7 +1088,7 @@ msgstr "Expansion horizontale de la couche initiale"
#: fdmprinter.def.json
msgctxt "xy_offset_layer_0 description"
msgid "Amount of offset applied to all polygons in the first layer. A negative value can compensate for squishing of the first layer known as \"elephant's foot\"."
-msgstr "Le décalage appliqué à tous les polygones dans la première couche. Une valeur négative peut compenser l'écrasement de la première couche, appelé « patte d'éléphant »."
+msgstr "L'offset appliqué à tous les polygones dans la première couche. Une valeur négative peut compenser l'écrasement de la première couche, appelé « patte d'éléphant »."
#: fdmprinter.def.json
msgctxt "z_seam_type label"
@@ -1133,7 +1098,7 @@ msgstr "Alignement de la jointure en Z"
#: fdmprinter.def.json
msgctxt "z_seam_type description"
msgid "Starting point of each path in a layer. When paths in consecutive layers start at the same point a vertical seam may show on the print. When aligning these near a user specified location, the seam is easiest to remove. When placed randomly the inaccuracies at the paths' start will be less noticeable. When taking the shortest path the print will be quicker."
-msgstr "Point de départ de chaque voie dans une couche. Quand les voies dans les couches consécutives démarrent au même endroit, une jointure verticale peut apparaître sur l'impression. En alignant les points de départ près d'un emplacement défini par l'utilisateur, la jointure sera plus facile à faire disparaître. Lorsqu'elles sont disposées de manière aléatoire, les imprécisions de départ des voies seront moins visibles. En choisissant la voie la plus courte, l'impression se fera plus rapidement."
+msgstr "Point de départ de chaque chemin dans une couche. Quand les chemins dans les couches consécutives démarrent au même endroit, une jointure verticale peut apparaître sur l'impression. En alignant les points de départ près d'un emplacement défini par l'utilisateur, la jointure sera plus facile à faire disparaître. Lorsqu'elles sont disposées de manière aléatoire, les imprécisions de départ des chemins seront moins visibles. En choisissant le chemin le plus court, l'impression se fera plus rapidement."
#: fdmprinter.def.json
msgctxt "z_seam_type option back"
@@ -1218,12 +1183,12 @@ 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"
+msgstr "Ignorer les petits espaces 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."
+msgstr "Quand le modèle présente de petits espaces 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."
#: fdmprinter.def.json
msgctxt "skin_outline_count label"
@@ -1238,32 +1203,32 @@ msgstr "Remplace la partie la plus externe du motif du dessus/dessous par un cer
#: fdmprinter.def.json
msgctxt "ironing_enabled label"
msgid "Enable Ironing"
-msgstr "Activer l'étirage"
+msgstr "Activer le lissage"
#: fdmprinter.def.json
msgctxt "ironing_enabled description"
msgid "Go over the top surface one additional time, but without extruding material. This is meant to melt the plastic on top further, creating a smoother surface."
-msgstr "Aller au-dessus de la surface supérieure une fois supplémentaire, mais sans extruder de matériau. Cela signifie de faire fondre le plastique en haut un peu plus, pour créer une surface lisse."
+msgstr "Aller au-dessus de la surface supérieure une fois supplémentaire, mais sans extruder de matériau. Cela signifie de faire fondre le plastique sur les couches supérieures, pour créer une surface lisse."
#: fdmprinter.def.json
msgctxt "ironing_only_highest_layer label"
msgid "Iron Only Highest Layer"
-msgstr "N'étirer que la couche supérieure"
+msgstr "Ne lisser que la couche supérieure"
#: fdmprinter.def.json
msgctxt "ironing_only_highest_layer description"
msgid "Only perform ironing on the very last layer of the mesh. This saves time if the lower layers don't need a smooth surface finish."
-msgstr "N'exécute un étirage que sur l'ultime couche du maillage. Ceci économise du temps si les couches inférieures ne nécessitent pas de fini lisse de surface."
+msgstr "N'exécute un lissage que sur la dernière couche du maillage. Ceci économise du temps si les couches inférieures ne nécessitent pas de finition lissée."
#: fdmprinter.def.json
msgctxt "ironing_pattern label"
msgid "Ironing Pattern"
-msgstr "Motif d'étirage"
+msgstr "Motif de lissage"
#: fdmprinter.def.json
msgctxt "ironing_pattern description"
msgid "The pattern to use for ironing top surfaces."
-msgstr "Le motif à utiliser pour étirer les surfaces supérieures."
+msgstr "Le motif à utiliser pour lisser les surfaces supérieures."
#: fdmprinter.def.json
msgctxt "ironing_pattern option concentric"
@@ -1278,37 +1243,37 @@ msgstr "Zig Zag"
#: fdmprinter.def.json
msgctxt "ironing_line_spacing label"
msgid "Ironing Line Spacing"
-msgstr "Interligne de l'étirage"
+msgstr "Interligne de lissage"
#: fdmprinter.def.json
msgctxt "ironing_line_spacing description"
msgid "The distance between the lines of ironing."
-msgstr "La distance entre les lignes d'étirage."
+msgstr "La distance entre les lignes de lissage"
#: fdmprinter.def.json
msgctxt "ironing_flow label"
msgid "Ironing Flow"
-msgstr "Flux d'étirage"
+msgstr "Flux de lissage"
#: fdmprinter.def.json
msgctxt "ironing_flow description"
msgid "The amount of material, relative to a normal skin line, to extrude during ironing. Keeping the nozzle filled helps filling some of the crevices of the top surface, but too much results in overextrusion and blips on the side of the surface."
-msgstr "La quantité de matériau, relative à une ligne de couche extérieure normale, à extruder pendant l'étirage. Le fait de garder la buse pleine aide à remplir certaines des crevasses de la surface supérieure ; mais si la quantité est trop importante, cela entraînera une surextrusion et l'apparition de coupures sur le côté de la surface."
+msgstr "La quantité de matériau, relative à une ligne de couche extérieure normale, à extruder pendant le lissage. Le fait de garder la buse pleine aide à remplir certaines des crevasses de la surface supérieure ; mais si la quantité est trop importante, cela entraînera une surextrusion et l'apparition de coupures sur le côté de la surface."
#: fdmprinter.def.json
msgctxt "ironing_inset label"
msgid "Ironing Inset"
-msgstr "Insert d'étirage"
+msgstr "Chevauchement du lissage"
#: fdmprinter.def.json
msgctxt "ironing_inset description"
msgid "A distance to keep from the edges of the model. Ironing all the way to the edge of the mesh may result in a jagged edge on your print."
-msgstr "Distance à garder à partir des bords du modèle. Étirer jusqu'au bord de la maille peut entraîner l'apparition d'un bord denté sur votre impression."
+msgstr "Distance à garder à partir des bords du modèle. Lisser jusqu'au bord de la maille peut entraîner l'apparition d'un bord denté sur votre impression."
#: fdmprinter.def.json
msgctxt "speed_ironing label"
msgid "Ironing Speed"
-msgstr "Vitesse d'étirage"
+msgstr "Vitesse de lissage"
#: fdmprinter.def.json
msgctxt "speed_ironing description"
@@ -1318,22 +1283,22 @@ msgstr "La vitesse à laquelle passer sur la surface supérieure."
#: fdmprinter.def.json
msgctxt "acceleration_ironing label"
msgid "Ironing Acceleration"
-msgstr "Accélération d'étirage"
+msgstr "Accélération du lissage"
#: fdmprinter.def.json
msgctxt "acceleration_ironing description"
msgid "The acceleration with which ironing is performed."
-msgstr "L'accélération selon laquelle l'étirage est effectué."
+msgstr "L'accélération selon laquelle le lissage est effectué."
#: fdmprinter.def.json
msgctxt "jerk_ironing label"
msgid "Ironing Jerk"
-msgstr "Saccade d'étirage"
+msgstr "Saccade du lissage"
#: fdmprinter.def.json
msgctxt "jerk_ironing description"
msgid "The maximum instantaneous velocity change while performing ironing."
-msgstr "Le changement instantané maximal de vitesse lors de l'étirage."
+msgstr "Le changement instantané maximal de vitesse lors du lissage."
#: fdmprinter.def.json
msgctxt "infill label"
@@ -1353,7 +1318,7 @@ msgstr "Extrudeuse de remplissage"
#: fdmprinter.def.json
msgctxt "infill_extruder_nr description"
msgid "The extruder train used for printing infill. This is used in multi-extrusion."
-msgstr "Le train d'extrudeuse utilisé pour l'impression du remplissage. Cela est utilisé en multi-extrusion."
+msgstr "Le système d'extrusion utilisé pour l'impression du remplissage. Cela est utilisé en multi-extrusion."
#: fdmprinter.def.json
msgctxt "infill_sparse_density label"
@@ -1378,12 +1343,12 @@ msgstr "Distance entre les lignes de remplissage imprimées. Ce paramètre est c
#: fdmprinter.def.json
msgctxt "infill_pattern label"
msgid "Infill Pattern"
-msgstr "Motif de remplissage"
+msgstr "Motif du 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."
+msgstr "Le motif du 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."
#: fdmprinter.def.json
msgctxt "infill_pattern option grid"
@@ -1473,22 +1438,22 @@ msgstr "Une liste de sens de ligne (exprimés en nombres entiers) à utiliser. L
#: fdmprinter.def.json
msgctxt "infill_offset_x label"
msgid "Infill X Offset"
-msgstr "Remplissage Décalage X"
+msgstr "Offset Remplissage X"
#: fdmprinter.def.json
msgctxt "infill_offset_x description"
-msgid "The infill pattern is offset this distance along the X axis."
-msgstr "Le motif de remplissage est décalé de cette distance sur l'axe X."
+msgid "The infill pattern is moved this distance along the X axis."
+msgstr "Le motif de remplissage est décalé de cette distance sur l'axe X."
#: fdmprinter.def.json
msgctxt "infill_offset_y label"
msgid "Infill Y Offset"
-msgstr "Remplissage Décalage Y"
+msgstr "Remplissage Offset Y"
#: fdmprinter.def.json
msgctxt "infill_offset_y description"
-msgid "The infill pattern is offset this distance along the Y axis."
-msgstr "Le motif de remplissage est décalé de cette distance sur l'axe Y."
+msgid "The infill pattern is moved this distance along the Y axis."
+msgstr "Le motif de remplissage est décalé de cette distance sur l'axe Y."
#: fdmprinter.def.json
msgctxt "sub_div_rad_add label"
@@ -1507,8 +1472,8 @@ msgstr "Pourcentage de chevauchement du remplissage"
#: fdmprinter.def.json
msgctxt "infill_overlap description"
-msgid "The amount of overlap between the infill and the walls. A slight overlap allows the walls to connect firmly to the infill."
-msgstr "Le degré de chevauchement entre le remplissage et les parois. Un léger chevauchement permet de lier fermement les parois au remplissage."
+msgid "The amount of overlap between the infill and the walls as a percentage of the infill line width. A slight overlap allows the walls to connect firmly to the infill."
+msgstr "Le degré de chevauchement entre le remplissage et les parois exprimé en pourcentage de la largeur de ligne de remplissage. Un chevauchement faible permet aux parois de se connecter fermement au remplissage."
#: fdmprinter.def.json
msgctxt "infill_overlap_mm label"
@@ -1527,8 +1492,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 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. 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 "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."
#: fdmprinter.def.json
msgctxt "skin_overlap_mm label"
@@ -1690,16 +1655,6 @@ msgctxt "material description"
msgid "Material"
msgstr "Matériau"
-#: fdmprinter.def.json
-msgctxt "material_flow_dependent_temperature label"
-msgid "Auto Temperature"
-msgstr "Température auto"
-
-#: fdmprinter.def.json
-msgctxt "material_flow_dependent_temperature description"
-msgid "Change the temperature for each layer automatically with the average flow speed of that layer."
-msgstr "Modifie automatiquement la température pour chaque couche en fonction de la vitesse de flux moyenne pour cette couche."
-
#: fdmprinter.def.json
msgctxt "default_material_print_temperature label"
msgid "Default Printing Temperature"
@@ -1708,7 +1663,7 @@ msgstr "Température d’impression par défaut"
#: fdmprinter.def.json
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."
+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 offset basés sur cette valeur."
#: fdmprinter.def.json
msgctxt "material_print_temperature label"
@@ -1750,16 +1705,6 @@ msgctxt "material_final_print_temperature description"
msgid "The temperature to which to already start cooling down just before the end of printing."
msgstr "La température à laquelle le refroidissement commence juste avant la fin de l'impression."
-#: fdmprinter.def.json
-msgctxt "material_flow_temp_graph label"
-msgid "Flow Temperature Graph"
-msgstr "Graphique de la température du flux"
-
-#: fdmprinter.def.json
-msgctxt "material_flow_temp_graph description"
-msgid "Data linking material flow (in mm3 per second) to temperature (degrees Celsius)."
-msgstr "Données reliant le flux de matériau (en mm3 par seconde) à la température (degrés Celsius)."
-
#: fdmprinter.def.json
msgctxt "material_extrusion_cool_down_speed label"
msgid "Extrusion Cool Down Speed Modifier"
@@ -1777,8 +1722,8 @@ msgstr "Température du plateau"
#: fdmprinter.def.json
msgctxt "material_bed_temperature description"
-msgid "The temperature used for the heated build plate. If this is 0, the bed will not heat up for this print."
-msgstr "Température utilisée pour le plateau chauffant. Si elle est définie sur 0, le plateau ne sera pas chauffé pour cette impression."
+msgid "The temperature used for the heated build plate. If this is 0, the bed temperature will not be adjusted."
+msgstr "Température utilisée pour le plateau chauffant. Si elle est définie sur 0, la température du plateau ne sera pas ajustée."
#: fdmprinter.def.json
msgctxt "material_bed_temperature_layer_0 label"
@@ -1848,7 +1793,7 @@ msgstr "Rétracter au changement de couche"
#: fdmprinter.def.json
msgctxt "retract_at_layer_change description"
msgid "Retract the filament when the nozzle is moving to the next layer."
-msgstr "Rétracter le filament quand le bec se déplace vers la prochaine couche. "
+msgstr "Rétracter le filament quand la buse se déplace vers la prochaine couche."
#: fdmprinter.def.json
msgctxt "retraction_amount label"
@@ -2603,12 +2548,12 @@ msgstr "déplacement"
#: fdmprinter.def.json
msgctxt "retraction_combing label"
msgid "Combing Mode"
-msgstr "Mode de détours"
+msgstr "Mode detour"
#: 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 by combing within the infill only."
-msgstr "Les détours (le 'combing') maintiennent le bec 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 le bec 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 en effectuant les détours uniquement dans le remplissage."
+msgstr "Les détours (le 'combing') 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 buze 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 en effectuant les détours uniquement dans le remplissage."
#: fdmprinter.def.json
msgctxt "retraction_combing option off"
@@ -2788,7 +2733,7 @@ msgstr "La durée de couche qui définit la limite entre la vitesse régulière
#: fdmprinter.def.json
msgctxt "cool_fan_speed_0 label"
msgid "Initial Fan Speed"
-msgstr "Vitesse des ventilateurs initiale"
+msgstr "Vitesse initiale des ventilateurs"
#: fdmprinter.def.json
msgctxt "cool_fan_speed_0 description"
@@ -2873,7 +2818,7 @@ msgstr "Extrudeuse de support"
#: fdmprinter.def.json
msgctxt "support_extruder_nr description"
msgid "The extruder train to use for printing the support. This is used in multi-extrusion."
-msgstr "Le train d'extrudeuse à utiliser pour l'impression du support. Cela est utilisé en multi-extrusion."
+msgstr "Le système d'extrusion à utiliser pour l'impression du support. Cela est utilisé en multi-extrusion."
#: fdmprinter.def.json
msgctxt "support_infill_extruder_nr label"
@@ -2883,7 +2828,7 @@ msgstr "Extrudeuse de remplissage du support"
#: fdmprinter.def.json
msgctxt "support_infill_extruder_nr description"
msgid "The extruder train to use for printing the infill of the support. This is used in multi-extrusion."
-msgstr "Le train d'extrudeuse à utiliser pour l'impression du remplissage du support. Cela est utilisé en multi-extrusion."
+msgstr "Le système d'extrusion à utiliser pour l'impression du remplissage du support. Cela est utilisé en multi-extrusion."
#: fdmprinter.def.json
msgctxt "support_extruder_nr_layer_0 label"
@@ -2893,7 +2838,7 @@ msgstr "Extrudeuse de support de la première couche"
#: fdmprinter.def.json
msgctxt "support_extruder_nr_layer_0 description"
msgid "The extruder train to use for printing the first layer of support infill. This is used in multi-extrusion."
-msgstr "Le train d'extrudeuse à utiliser pour l'impression de la première couche de remplissage du support. Cela est utilisé en multi-extrusion."
+msgstr "Le système d'extrusion à utiliser pour l'impression de la première couche de remplissage du support. Cela est utilisé en multi-extrusion."
#: fdmprinter.def.json
msgctxt "support_interface_extruder_nr label"
@@ -2903,7 +2848,7 @@ msgstr "Extrudeuse de l'interface du support"
#: fdmprinter.def.json
msgctxt "support_interface_extruder_nr description"
msgid "The extruder train to use for printing the roofs and floors of the support. This is used in multi-extrusion."
-msgstr "Le train d'extrudeuse à utiliser pour l'impression des plafonds et bas du support. Cela est utilisé en multi-extrusion."
+msgstr "Le système d'extrusion à utiliser pour l'impression des plafonds et bas du support. Cela est utilisé en multi-extrusion."
#: fdmprinter.def.json
msgctxt "support_roof_extruder_nr label"
@@ -2913,7 +2858,7 @@ msgstr "Extrudeuse des plafonds de support"
#: fdmprinter.def.json
msgctxt "support_roof_extruder_nr description"
msgid "The extruder train to use for printing the roofs of the support. This is used in multi-extrusion."
-msgstr "Le train d'extrudeuse à utiliser pour l'impression des plafonds du support. Cela est utilisé en multi-extrusion."
+msgstr "Le système d'extrusion à utiliser pour l'impression des plafonds du support. Cela est utilisé en multi-extrusion."
#: fdmprinter.def.json
msgctxt "support_bottom_extruder_nr label"
@@ -2923,7 +2868,7 @@ msgstr "Extrudeuse des bas de support"
#: fdmprinter.def.json
msgctxt "support_bottom_extruder_nr description"
msgid "The extruder train to use for printing the floors of the support. This is used in multi-extrusion."
-msgstr "Le train d'extrudeuse à utiliser pour l'impression des bas du support. Cela est utilisé en multi-extrusion."
+msgstr "Le système d'extrusion à utiliser pour l'impression des bas du support. Cela est utilisé en multi-extrusion."
#: fdmprinter.def.json
msgctxt "support_type label"
@@ -3138,7 +3083,7 @@ msgstr "Expansion horizontale des supports"
#: fdmprinter.def.json
msgctxt "support_offset description"
msgid "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."
-msgstr "Le décalage appliqué à tous les polygones pour chaque couche. Une valeur positive peut lisser les zones de support et rendre le support plus solide."
+msgstr "L'offset appliqué à tous les polygones pour chaque couche. Une valeur positive peut lisser les zones de support et rendre le support plus solide."
#: fdmprinter.def.json
msgctxt "support_infill_sparse_thickness label"
@@ -3450,6 +3395,16 @@ msgctxt "support_tower_roof_angle description"
msgid "The angle of a rooftop of a tower. A higher value results in pointed tower roofs, a lower value results in flattened tower roofs."
msgstr "L'angle du toit d'une tour. Une valeur plus élevée entraîne des toits de tour pointus, tandis qu'une valeur plus basse résulte en des toits plats."
+#: fdmprinter.def.json
+msgctxt "support_mesh_drop_down label"
+msgid "Drop Down Support Mesh"
+msgstr "Maillage de support descendant"
+
+#: fdmprinter.def.json
+msgctxt "support_mesh_drop_down description"
+msgid "Make support everywhere below the support mesh, so that there's no overhang in the support mesh."
+msgstr "Inclure du support à tout emplacement sous le maillage de support, de sorte à ce qu'il n'y ait pas de porte-à-faux dans le maillage de support."
+
#: fdmprinter.def.json
msgctxt "platform_adhesion label"
msgid "Build Plate Adhesion"
@@ -3528,7 +3483,7 @@ msgstr "Extrudeuse d'adhérence du plateau"
#: fdmprinter.def.json
msgctxt "adhesion_extruder_nr description"
msgid "The extruder train to use for printing the skirt/brim/raft. This is used in multi-extrusion."
-msgstr "Le train d'extrudeuse à utiliser pour l'impression de la jupe/la bordure/du radeau. Cela est utilisé en multi-extrusion."
+msgstr "Le système d'extrusion à utiliser pour l'impression de la jupe/la bordure/du radeau. Cela est utilisé en multi-extrusion."
#: fdmprinter.def.json
msgctxt "skirt_line_count label"
@@ -3550,7 +3505,9 @@ msgctxt "skirt_gap description"
msgid ""
"The horizontal distance between the skirt and the first layer of the print.\n"
"This is the minimum distance. Multiple skirt lines will extend outwards from this distance."
-msgstr "La distance horizontale entre la jupe et la première couche de l’impression.\nIl s’agit de la distance minimale séparant la jupe de l’objet. Si la jupe a d’autres lignes, celles-ci s’étendront vers l’extérieur."
+msgstr ""
+"La distance horizontale entre la jupe et la première couche de l’impression.\n"
+"Il s’agit de la distance minimale séparant la jupe de l’objet. Si la jupe a d’autres lignes, celles-ci s’étendront vers l’extérieur."
#: fdmprinter.def.json
msgctxt "skirt_brim_minimal_length label"
@@ -3975,7 +3932,7 @@ msgstr "Compensation du débit : la quantité de matériau extrudée est multip
#: fdmprinter.def.json
msgctxt "prime_tower_wipe_enabled label"
msgid "Wipe Inactive Nozzle on Prime Tower"
-msgstr "Essuyer le bec d'impression inactif sur la tour primaire"
+msgstr "Essuyer la buse d'impression inactif sur la tour primaire"
#: fdmprinter.def.json
msgctxt "prime_tower_wipe_enabled description"
@@ -4082,16 +4039,6 @@ msgctxt "meshfix_keep_open_polygons description"
msgid "Normally Cura tries to stitch up small holes in the mesh and remove parts of a layer with big holes. Enabling this option keeps those parts which cannot be stitched. This option should be used as a last resort option when everything else fails to produce proper GCode."
msgstr "Normalement, Cura essaye de raccommoder les petits trous dans le maillage et supprime les parties des couches contenant de gros trous. Activer cette option pousse Cura à garder les parties qui ne peuvent être raccommodées. Cette option doit être utilisée en dernier recours quand tout le reste échoue à produire un GCode correct."
-#: fdmprinter.def.json
-msgctxt "meshfix_maximum_resolution label"
-msgid "Maximum Resolution"
-msgstr "Résolution maximum"
-
-#: fdmprinter.def.json
-msgctxt "meshfix_maximum_resolution description"
-msgid "The minimum size of a line segment after slicing. If you increase this, the mesh will have a lower resolution. This may allow the printer to keep up with the speed it has to process g-code and will increase slice speed by removing details of the mesh that it can't process anyway."
-msgstr "Taille minimum d'un segment de ligne après découpage. Si vous augmentez cette valeur, la maille aura une résolution plus faible. Cela peut permettre à l'imprimante de suivre la vitesse à laquelle elle doit traiter le G-Code et augmentera la vitesse de découpe en enlevant des détails de la maille que l'imprimante ne peut pas traiter de toute manière."
-
#: fdmprinter.def.json
msgctxt "multiple_mesh_overlap label"
msgid "Merged Meshes Overlap"
@@ -4242,16 +4189,6 @@ msgctxt "support_mesh description"
msgid "Use this mesh to specify support areas. This can be used to generate support structure."
msgstr "Utiliser ce maillage pour spécifier des zones de support. Cela peut être utilisé pour générer une structure de support."
-#: fdmprinter.def.json
-msgctxt "support_mesh_drop_down label"
-msgid "Drop Down Support Mesh"
-msgstr "Maillage de support descendant"
-
-#: fdmprinter.def.json
-msgctxt "support_mesh_drop_down description"
-msgid "Make support everywhere below the support mesh, so that there's no overhang in the support mesh."
-msgstr "Inclure du support à tout emplacement sous le maillage de support, de sorte à ce qu'il n'y ait pas de porte-à-faux dans le maillage de support."
-
#: fdmprinter.def.json
msgctxt "anti_overhang_mesh label"
msgid "Anti Overhang Mesh"
@@ -4328,14 +4265,194 @@ msgid "experimental!"
msgstr "expérimental !"
#: fdmprinter.def.json
-msgctxt "optimize_wall_printing_order label"
-msgid "Optimize Wall Printing Order"
-msgstr "Optimiser l'ordre d'impression des parois"
+msgctxt "support_tree_enable label"
+msgid "Tree Support"
+msgstr "Support arborescent"
#: fdmprinter.def.json
-msgctxt "optimize_wall_printing_order description"
-msgid "Optimize the order in which walls are printed so as to reduce the number of retractions and the distance travelled. Most parts will benefit from this being enabled but some may actually take longer so please compare the print time estimates with and without optimization."
-msgstr "Optimiser l'ordre dans lequel des parois sont imprimées de manière à réduire le nombre de retraits et les distances parcourues. La plupart des pièces bénéficieront de cette possibilité, mais certaines peuvent en fait prendre plus de temps à l'impression ; veuillez dès lors comparer les estimations de durée d'impression avec et sans optimisation."
+msgctxt "support_tree_enable description"
+msgid "Generate a tree-like support with branches that support your print. This may reduce material usage and print time, but greatly increases slicing time."
+msgstr "Générer un support arborescent avec des branches qui soutiennent votre impression. Cela peut réduire l'utilisation de matériau et le temps d'impression, mais augmente considérablement le temps de découpage."
+
+#: fdmprinter.def.json
+msgctxt "support_tree_angle label"
+msgid "Tree Support Branch Angle"
+msgstr "Angle des branches de support arborescent"
+
+#: fdmprinter.def.json
+msgctxt "support_tree_angle description"
+msgid "The angle of the branches. Use a lower angle to make them more vertical and more stable. Use a higher angle to be able to have more reach."
+msgstr "Angle des branches. Utilisez un angle plus faible pour les rendre plus verticales et plus stables ; utilisez un angle plus élevé pour avoir plus de portée."
+
+#: fdmprinter.def.json
+msgctxt "support_tree_branch_distance label"
+msgid "Tree Support Branch Distance"
+msgstr "Distance des branches de support arborescent"
+
+#: fdmprinter.def.json
+msgctxt "support_tree_branch_distance description"
+msgid "How far apart the branches need to be when they touch the model. Making this distance small will cause the tree support to touch the model at more points, causing better overhang but making support harder to remove."
+msgstr "Distance à laquelle doivent se trouver les branches lorsqu'elles touchent le modèle. Si vous réduisez cette distance, le support arborescent touchera le modèle à plus d'endroits, ce qui causera un meilleur porte-à-faux mais rendra le support plus difficile à enlever."
+
+#: fdmprinter.def.json
+msgctxt "support_tree_branch_diameter label"
+msgid "Tree Support Branch Diameter"
+msgstr "Diamètre des branches de support arborescent"
+
+#: fdmprinter.def.json
+msgctxt "support_tree_branch_diameter description"
+msgid "The diameter of the thinnest branches of tree support. Thicker branches are more sturdy. Branches towards the base will be thicker than this."
+msgstr "Diamètre des branches les plus minces du support arborescent. Plus les branches sont épaisses, plus elles sont robustes ; les branches proches de la base seront plus épaisses que cette valeur."
+
+#: fdmprinter.def.json
+msgctxt "support_tree_branch_diameter_angle label"
+msgid "Tree Support Branch Diameter Angle"
+msgstr "Angle de diamètre des branches de support arborescent"
+
+#: fdmprinter.def.json
+msgctxt "support_tree_branch_diameter_angle description"
+msgid "The angle of the branches' diameter as they gradually become thicker towards the bottom. An angle of 0 will cause the branches to have uniform thickness over their length. A bit of an angle can increase stability of the tree support."
+msgstr "Angle du diamètre des branches au fur et à mesure qu'elles s'épaississent lorsqu'elles sont proches du fond. Avec un angle de 0°, les branches auront une épaisseur uniforme sur toute leur longueur. Donner un peu d'angle permet d'augmenter la stabilité du support arborescent."
+
+#: fdmprinter.def.json
+msgctxt "support_tree_collision_resolution label"
+msgid "Tree Support Collision Resolution"
+msgstr "Résolution de collision du support arborescent"
+
+#: fdmprinter.def.json
+msgctxt "support_tree_collision_resolution description"
+msgid "Resolution to compute collisions with to avoid hitting the model. Setting this lower will produce more accurate trees that fail less often, but increases slicing time dramatically."
+msgstr "Résolution servant à calculer les collisions afin d'éviter de heurter le modèle. Plus ce paramètre est faible, plus les arborescences seront précises et stables, mais cela augmente considérablement le temps de découpage."
+
+#: fdmprinter.def.json
+msgctxt "support_tree_wall_thickness label"
+msgid "Tree Support Wall Thickness"
+msgstr "Épaisseur de la paroi du support arborescent"
+
+#: fdmprinter.def.json
+msgctxt "support_tree_wall_thickness description"
+msgid "The thickness of the walls of the branches of tree support. Thicker walls take longer to print but don't fall over as easily."
+msgstr "Épaisseur des parois des branches du support arborescent. Les parois plus épaisses prennent plus de temps à imprimer, mais ne tombent pas aussi facilement."
+
+#: fdmprinter.def.json
+msgctxt "support_tree_wall_count label"
+msgid "Tree Support Wall Line Count"
+msgstr "Nombre de lignes de la paroi du support arborescent"
+
+#: fdmprinter.def.json
+msgctxt "support_tree_wall_count description"
+msgid "The number of walls of the branches of tree support. Thicker walls take longer to print but don't fall over as easily."
+msgstr "Nombre de parois des branches du support arborescent. Les parois plus épaisses prennent plus de temps à imprimer, mais ne tombent pas aussi facilement."
+
+#: fdmprinter.def.json
+msgctxt "slicing_tolerance label"
+msgid "Slicing Tolerance"
+msgstr "Tolérance à la découpe"
+
+#: fdmprinter.def.json
+msgctxt "slicing_tolerance description"
+msgid "How to slice layers with diagonal surfaces. The areas of a layer can be generated based on where the middle of the layer intersects the surface (Middle). Alternatively each layer can have the areas which fall inside of the volume throughout the height of the layer (Exclusive) or a layer has the areas which fall inside anywhere within the layer (Inclusive). Exclusive retains the most details, Inclusive makes for the best fit and Middle takes the least time to process."
+msgstr "Comment découper des couches avec des surfaces diagonales. Les zones d'une couche peuvent être générées en fonction de l'endroit où le milieu de la couche croise la surface (Milieu). Alternativement, chaque couche peut posséder des zones situées à l'intérieur du volume à travers toute la hauteur de la couche (Exclusif), ou une couche peut avoir des zones situées à l'intérieur à tout endroit dans la couche (Inclusif). L'option Exclusif permet de retenir le plus de détails, Inclusif permet d'obtenir une adaptation optimale et Milieu demande le moins de temps de traitement."
+
+#: fdmprinter.def.json
+msgctxt "slicing_tolerance option middle"
+msgid "Middle"
+msgstr "Milieu"
+
+#: fdmprinter.def.json
+msgctxt "slicing_tolerance option exclusive"
+msgid "Exclusive"
+msgstr "Exclusif"
+
+#: fdmprinter.def.json
+msgctxt "slicing_tolerance option inclusive"
+msgid "Inclusive"
+msgstr "Inclusif"
+
+#: fdmprinter.def.json
+msgctxt "roofing_line_width label"
+msgid "Top Surface Skin Line Width"
+msgstr "Largeur de ligne de couche extérieure de la surface supérieure"
+
+#: fdmprinter.def.json
+msgctxt "roofing_line_width description"
+msgid "Width of a single line of the areas at the top of the print."
+msgstr "Largeur d'une seule ligne de la zone en haut de l'impression."
+
+#: fdmprinter.def.json
+msgctxt "roofing_pattern label"
+msgid "Top Surface Skin Pattern"
+msgstr "Motif de couche extérieure de surface supérieure"
+
+#: fdmprinter.def.json
+msgctxt "roofing_pattern description"
+msgid "The pattern of the top most layers."
+msgstr "Le motif des couches supérieures."
+
+#: fdmprinter.def.json
+msgctxt "roofing_pattern option lines"
+msgid "Lines"
+msgstr "Lignes"
+
+#: fdmprinter.def.json
+msgctxt "roofing_pattern option concentric"
+msgid "Concentric"
+msgstr "Concentrique"
+
+#: fdmprinter.def.json
+msgctxt "roofing_pattern option zigzag"
+msgid "Zig Zag"
+msgstr "Zig Zag"
+
+#: fdmprinter.def.json
+msgctxt "roofing_angles label"
+msgid "Top Surface Skin Line Directions"
+msgstr "Sens de lignes de couche extérieure de surface supérieure"
+
+#: fdmprinter.def.json
+msgctxt "roofing_angles description"
+msgid "A list of integer line directions to use when the top surface skin layers use the lines or zig zag pattern. 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 traditional default angles (45 and 135 degrees)."
+msgstr "Une liste de sens de ligne (exprimés en nombres entiers) à utiliser lorsque les couches extérieures de la surface supérieure utilisent le motif en lignes ou en zig zag. Les éléments de la liste sont utilisés de manière séquentielle à mesure de l'avancement des couches. La liste reprend depuis le début lorsque la fin est atteinte. Les éléments de la liste sont séparés par des virgules et la liste entière est encadrée entre crochets. La valeur par défaut est une liste vide, ce qui signifie que les angles traditionnels par défaut seront utilisés (45 et 135 degrés)."
+
+#: fdmprinter.def.json
+msgctxt "infill_enable_travel_optimization label"
+msgid "Infill Travel Optimization"
+msgstr "Optimisation du déplacement de remplissage"
+
+#: fdmprinter.def.json
+msgctxt "infill_enable_travel_optimization description"
+msgid "When enabled, the order in which the infill lines are printed is optimized to reduce the distance travelled. The reduction in travel time achieved very much depends on the model being sliced, infill pattern, density, etc. Note that, for some models that have many small areas of infill, the time to slice the model may be greatly increased."
+msgstr "Lorsque cette option est activée, l'ordre dans lequel les lignes de remplissage sont imprimées est optimisé pour réduire la distance parcourue. La réduction du temps de parcours dépend en grande partie du modèle à découper, du type de remplissage, de la densité, etc. Remarque : pour certains modèles possédant beaucoup de petites zones de remplissage, le temps de découpe du modèle peut en être considérablement augmenté."
+
+#: fdmprinter.def.json
+msgctxt "material_flow_dependent_temperature label"
+msgid "Auto Temperature"
+msgstr "Température auto"
+
+#: fdmprinter.def.json
+msgctxt "material_flow_dependent_temperature description"
+msgid "Change the temperature for each layer automatically with the average flow speed of that layer."
+msgstr "Modifie automatiquement la température pour chaque couche en fonction de la vitesse de flux moyenne pour cette couche."
+
+#: fdmprinter.def.json
+msgctxt "material_flow_temp_graph label"
+msgid "Flow Temperature Graph"
+msgstr "Graphique de la température du flux"
+
+#: fdmprinter.def.json
+msgctxt "material_flow_temp_graph description"
+msgid "Data linking material flow (in mm3 per second) to temperature (degrees Celsius)."
+msgstr "Données reliant le flux de matériau (en mm3 par seconde) à la température (degrés Celsius)."
+
+#: fdmprinter.def.json
+msgctxt "meshfix_maximum_resolution label"
+msgid "Maximum Resolution"
+msgstr "Résolution maximum"
+
+#: fdmprinter.def.json
+msgctxt "meshfix_maximum_resolution description"
+msgid "The minimum size of a line segment after slicing. If you increase this, the mesh will have a lower resolution. This may allow the printer to keep up with the speed it has to process g-code and will increase slice speed by removing details of the mesh that it can't process anyway."
+msgstr "Taille minimum d'un segment de ligne après découpage. Si vous augmentez cette valeur, la maille aura une résolution plus faible. Cela peut permettre à l'imprimante de suivre la vitesse à laquelle elle doit traiter le G-Code et augmentera la vitesse de découpe en enlevant des détails de la maille que l'imprimante ne peut pas traiter de toute manière."
#: fdmprinter.def.json
msgctxt "support_skip_some_zags label"
@@ -4555,7 +4672,7 @@ msgstr "Insert en spaghettis"
#: fdmprinter.def.json
msgctxt "spaghetti_inset description"
msgid "The offset from the walls from where the spaghetti infill will be printed."
-msgstr "Le décalage à partir des parois depuis lesquelles le remplissage en spaghettis sera imprimé."
+msgstr "L'offset à partir des parois depuis lesquelles le remplissage en spaghettis sera imprimé."
#: fdmprinter.def.json
msgctxt "spaghetti_flow label"
@@ -4660,7 +4777,7 @@ msgstr "Distance moyenne entre les points ajoutés aléatoirement sur chaque seg
#: fdmprinter.def.json
msgctxt "flow_rate_max_extrusion_offset label"
msgid "Flow rate compensation max extrusion offset"
-msgstr "Décalage d'extrusion max. pour compensation du débit"
+msgstr "Offset d'extrusion max. pour compensation du débit"
#: fdmprinter.def.json
msgctxt "flow_rate_max_extrusion_offset description"
@@ -4827,7 +4944,9 @@ msgctxt "wireframe_up_half_speed description"
msgid ""
"Distance of an upward move which is extruded with half speed.\n"
"This can cause better adhesion to previous layers, while not heating the material in those layers too much. Only applies to Wire Printing."
-msgstr "Distance d’un déplacement ascendant qui est extrudé à mi-vitesse.\nCela peut permettre une meilleure adhérence aux couches précédentes sans surchauffer le matériau dans ces couches. Uniquement applicable à l'impression filaire."
+msgstr ""
+"Distance d’un déplacement ascendant qui est extrudé à mi-vitesse.\n"
+"Cela peut permettre une meilleure adhérence aux couches précédentes sans surchauffer le matériau dans ces couches. Uniquement applicable à l'impression filaire."
#: fdmprinter.def.json
msgctxt "wireframe_top_jump label"
@@ -4934,6 +5053,46 @@ msgctxt "wireframe_nozzle_clearance description"
msgid "Distance between the nozzle and horizontally downward lines. Larger clearance results in diagonally downward lines with a less steep angle, which in turn results in less upward connections with the next layer. Only applies to Wire Printing."
msgstr "Distance entre la buse et les lignes descendantes horizontalement. Un espacement plus important génère des lignes diagonalement descendantes avec un angle moins abrupt, qui génère alors des connexions moins ascendantes avec la couche suivante. Uniquement applicable à l'impression filaire."
+#: fdmprinter.def.json
+msgctxt "adaptive_layer_height_enabled label"
+msgid "Use adaptive layers"
+msgstr "Utiliser des couches adaptatives"
+
+#: fdmprinter.def.json
+msgctxt "adaptive_layer_height_enabled description"
+msgid "Adaptive layers computes the layer heights depending on the shape of the model."
+msgstr "Cette option calcule la hauteur des couches en fonction de la forme du modèle."
+
+#: fdmprinter.def.json
+msgctxt "adaptive_layer_height_variation label"
+msgid "Adaptive layers maximum variation"
+msgstr "Variation maximale des couches adaptatives"
+
+#: fdmprinter.def.json
+msgctxt "adaptive_layer_height_variation description"
+msgid "The maximum allowed height different from the base layer height in mm."
+msgstr "Hauteur maximale autorisée par rapport à la couche de base, en mm."
+
+#: fdmprinter.def.json
+msgctxt "adaptive_layer_height_variation_step label"
+msgid "Adaptive layers variation step size"
+msgstr "Taille des étapes de variation des couches adaptatives"
+
+#: fdmprinter.def.json
+msgctxt "adaptive_layer_height_variation_step description"
+msgid "The difference in height of the next layer height compared to the previous one."
+msgstr "Différence de hauteur de la couche suivante par rapport à la précédente."
+
+#: fdmprinter.def.json
+msgctxt "adaptive_layer_height_threshold label"
+msgid "Adaptive layers threshold"
+msgstr "Limite des couches adaptatives"
+
+#: fdmprinter.def.json
+msgctxt "adaptive_layer_height_threshold description"
+msgid "Threshold whether to use a smaller layer or not. This number is compared to the tan of the steepest slope in a layer."
+msgstr "Limite indiquant d'utiliser ou non une couche plus petite. Ce nombre est comparé à la tangente de la pente la plus raide d'une couche."
+
#: fdmprinter.def.json
msgctxt "command_line_settings label"
msgid "Command Line Settings"
@@ -4982,7 +5141,7 @@ msgstr "Position z de la maille"
#: fdmprinter.def.json
msgctxt "mesh_position_z description"
msgid "Offset applied to the object in the z direction. With this you can perform what was used to be called 'Object Sink'."
-msgstr "Décalage appliqué à l'objet dans le sens z. Cela vous permet d'exécuter ce que l'on appelait « Affaissement de l'objet »."
+msgstr "Offset appliqué à l'objet dans le sens z. Cela vous permet d'exécuter ce que l'on appelait « Affaissement de l'objet »."
#: fdmprinter.def.json
msgctxt "mesh_rotation_matrix label"
@@ -4994,6 +5153,26 @@ 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 "infill_offset_x description"
+#~ msgid "The infill pattern is offset this distance along the X axis."
+#~ msgstr "Le motif de remplissage est décalé de cette distance sur l'axe X."
+
+#~ msgctxt "infill_offset_y description"
+#~ msgid "The infill pattern is offset this distance along the Y axis."
+#~ msgstr "Le motif de remplissage est décalé de cette distance sur l'axe Y."
+
+#~ msgctxt "infill_overlap description"
+#~ msgid "The amount of overlap between the infill and the walls. A slight overlap allows the walls to connect firmly to the infill."
+#~ msgstr "Le degré de chevauchement entre le remplissage et les parois. Un léger chevauchement permet de lier fermement les parois au remplissage."
+
+#~ msgctxt "skin_overlap description"
+#~ msgid "The amount of overlap between the skin and the walls as a percentage of the 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. 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 "material_bed_temperature description"
+#~ msgid "The temperature used for the heated build plate. If this is 0, the bed will not heat up for this print."
+#~ msgstr "Température utilisée pour le plateau chauffant. Si elle est définie sur 0, le plateau ne sera pas chauffé pour cette impression."
+
#~ msgctxt "wall_x_extruder_nr label"
#~ msgid "Inner Walls Extruder"
#~ msgstr "Extrudeuse de parois internes"
diff --git a/resources/i18n/it_IT/cura.po b/resources/i18n/it_IT/cura.po
index a4c9ef40f8..d6f066aa22 100644
--- a/resources/i18n/it_IT/cura.po
+++ b/resources/i18n/it_IT/cura.po
@@ -1,22 +1,22 @@
# Cura
-# Copyright (C) 2017 Ultimaker
+# Copyright (C) 2018 Ultimaker
# This file is distributed under the same license as the Cura package.
-# Ruben Dulek , 2017.
-#
+# Ruben Dulek , 2018.
+#
msgid ""
msgstr ""
-"Project-Id-Version: Cura 3.0\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2017-11-21 16:58+0100\n"
-"PO-Revision-Date: 2017-11-30 13:05+0100\n"
-"Last-Translator: Bothof \n"
+"Project-Id-Version: Cura 3.2\n"
+"Report-Msgid-Bugs-To: r.dulek@ultimaker.com\n"
+"POT-Creation-Date: 2018-01-29 09:48+0000\n"
+"PO-Revision-Date: 2018-02-13 13:15+0100\n"
+"Last-Translator: Crea-3D \n"
"Language-Team: Italian\n"
"Language: it_IT\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.py:29
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.py:26
msgctxt "@action"
msgid "Machine Settings"
msgstr "Impostazioni macchina"
@@ -53,12 +53,11 @@ msgstr "Collegamento a Doodle3D Connect"
#: /home/ruben/Projects/Cura/plugins/Doodle3D-cura-plugin/Doodle3D/D3DCloudPrintOutputDevicePlugin.py:87
#: /home/ruben/Projects/Cura/plugins/Doodle3D-cura-plugin/Doodle3D/D3DCloudPrintOutputDevicePlugin.py:155
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:874
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:646
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:875
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:659
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/DiscoverUM3Action.qml:370
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/PrintWindow.qml:78
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/ConfigDialog.qml:104
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/ExportSTLUI.qml:99
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:355
#: /home/ruben/Projects/Cura/plugins/ImageReader/ConfigUI.qml:188
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:376
#: /home/ruben/Projects/Cura/plugins/PluginBrowser/PluginBrowser.qml:139
@@ -98,7 +97,7 @@ msgctxt "@info:tooltip"
msgid "Open the Doodle3D Connect web interface"
msgstr "Apri interfaccia web Doodle3D Connect"
-#: /home/ruben/Projects/Cura/plugins/ChangeLogPlugin/ChangeLog.py:34
+#: /home/ruben/Projects/Cura/plugins/ChangeLogPlugin/ChangeLog.py:33
msgctxt "@item:inmenu"
msgid "Show Changelog"
msgstr "Visualizza registro modifiche"
@@ -106,85 +105,90 @@ msgstr "Visualizza registro modifiche"
#: /home/ruben/Projects/Cura/plugins/ProfileFlattener/ProfileFlattener.py:20
msgctxt "@item:inmenu"
msgid "Flatten active settings"
-msgstr "Impostazioni attive profilo appiattito"
+msgstr "Resetta impostazioni attive"
#: /home/ruben/Projects/Cura/plugins/ProfileFlattener/ProfileFlattener.py:32
msgctxt "@info:status"
msgid "Profile has been flattened & activated."
-msgstr "Il profilo è stato appiattito e attivato."
+msgstr "Il profilo è stato resettato e attivato."
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:26
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:27
msgctxt "@item:inmenu"
msgid "USB printing"
msgstr "Stampa USB"
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:27
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:28
msgctxt "@action:button Preceded by 'Ready to'."
msgid "Print via USB"
msgstr "Stampa tramite USB"
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:28
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:29
msgctxt "@info:tooltip"
msgid "Print via USB"
msgstr "Stampa tramite USB"
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:30
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:31
msgctxt "@info:status"
msgid "Connected via USB"
msgstr "Connesso tramite USB"
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:154
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:183
msgctxt "@info:status"
msgid "Unable to start a new job because the printer is busy or not connected."
msgstr "Impossibile avviare un nuovo processo di stampa perché la stampante è occupata o non collegata."
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:154
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:183
msgctxt "@info:title"
msgid "Printer Unavailable"
msgstr "Stampante non disponibile"
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:457
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:485
msgctxt "@info:status"
msgid "This printer does not support USB printing because it uses UltiGCode flavor."
msgstr "Questa stampante non supporta la stampa tramite USB in quanto utilizza la versione UltiGCode."
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:457
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:485
msgctxt "@info:title"
msgid "USB Printing"
msgstr "Stampa USB"
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:461
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:489
msgctxt "@info:status"
msgid "Unable to start a new job because the printer does not support usb printing."
msgstr "Impossibile avviare un nuovo processo di stampa perché la stampante non supporta la stampa tramite USB."
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:461
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDeviceManager.py:108
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:489
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDeviceManager.py:103
#: /home/ruben/Projects/Cura/plugins/RemovableDriveOutputDevice/RemovableDriveOutputDevice.py:146
#: /home/ruben/Projects/Cura/plugins/RemovableDriveOutputDevice/RemovableDriveOutputDevice.py:158
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:945
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1349
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1417
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:946
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1418
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1496
msgctxt "@info:title"
msgid "Warning"
-msgstr "Avvertenza"
+msgstr "Attenzione"
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDeviceManager.py:108
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDeviceManager.py:103
msgctxt "@info"
msgid "Unable to update firmware because there are no printers connected."
msgstr "Impossibile aggiornare il firmware perché non ci sono stampanti collegate."
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDeviceManager.py:122
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDeviceManager.py:117
#, python-format
msgctxt "@info"
msgid "Could not find firmware required for the printer at %s."
msgstr "Impossibile trovare il firmware richiesto per la stampante a %s."
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDeviceManager.py:122
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDeviceManager.py:117
msgctxt "@info:title"
msgid "Printer Firmware"
msgstr "Firmware stampante"
+#: /home/ruben/Projects/Cura/plugins/PrepareStage/__init__.py:12
+msgctxt "@item:inmenu"
+msgid "Prepare"
+msgstr "Prepara"
+
#: /home/ruben/Projects/Cura/plugins/RemovableDriveOutputDevice/RemovableDriveOutputDevice.py:23
msgctxt "@action:button Preceded by 'Ready to'."
msgid "Save to Removable Drive"
@@ -228,11 +232,11 @@ 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:132
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:692
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:700
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:146
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:693
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:701
#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:153
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1358
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:160
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1427
msgctxt "@info:title"
msgid "Error"
msgstr "Errore"
@@ -257,7 +261,7 @@ msgstr "Rimuovi"
#, python-brace-format
msgctxt "@action"
msgid "Eject removable device {0}"
-msgstr "Rimuovi il dispositivo rimovibile {0}"
+msgstr "Espelli il dispositivo rimovibile {0}"
#: /home/ruben/Projects/Cura/plugins/RemovableDriveOutputDevice/RemovableDriveOutputDevice.py:156
#, python-brace-format
@@ -282,7 +286,7 @@ msgid "Removable Drive"
msgstr "Unità rimovibile"
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:109
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:53
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:51
msgctxt "@action:button Preceded by 'Ready to'."
msgid "Print over network"
msgstr "Stampa sulla rete"
@@ -396,113 +400,113 @@ msgctxt "@info:title"
msgid "Printer Status"
msgstr "Stato stampante"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:691
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:692
#, python-brace-format
msgctxt "@info:status"
msgid "Unable to start a new print job. No Printcore loaded in slot {0}"
msgstr "Impossibile avviare un nuovo processo di stampa. Nessun Printcore caricato nello slot {0}"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:699
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:700
#, python-brace-format
msgctxt "@info:status"
msgid "Unable to start a new print job. No material loaded in slot {0}"
msgstr "Impossibile avviare un nuovo processo di stampa. Nessun materiale caricato nello slot {0}"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:709
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:710
#, python-brace-format
msgctxt "@label"
msgid "Not enough material for spool {0}."
msgstr "Materiale per la bobina insufficiente {0}."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:719
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:720
#, python-brace-format
msgctxt "@label"
msgid "Different PrintCore (Cura: {0}, Printer: {1}) selected for extruder {2}"
msgstr "PrintCore diverso (Cura: {0}, Stampante: {1}) selezionata per estrusore {2}"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:733
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:734
#, 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/NetworkPrinterOutputDevice.py:741
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:742
#, python-brace-format
msgctxt "@label"
msgid "PrintCore {0} is not properly calibrated. XY calibration needs to be performed on the printer."
msgstr "PrintCore {0} non correttamente calibrato. Necessario eseguire calibrazione XY sulla stampante."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:746
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:747
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/NetworkPrinterOutputDevice.py:747
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:748
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."
+msgstr "Le configurazioni o la calibrazione della stampante e di Cura non corrispondono. Per risultati ottimali, sezionare sempre i PrintCore e i materiali inseriti nella stampante utilizzata."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:753
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:754
msgctxt "@window:title"
msgid "Mismatched configuration"
msgstr "Mancata corrispondenza della configurazione"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:864
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:262
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:865
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:258
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/NetworkPrinterOutputDevice.py:873
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:874
msgctxt "@info:status"
msgid "Sending data to printer"
msgstr "Invio dati alla stampante in corso"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:873
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:874
msgctxt "@info:title"
msgid "Sending Data"
msgstr "Invio dati"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:944
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:945
msgctxt "@info:status"
msgid "Unable to send data to printer. Is another job still active?"
msgstr "Impossibile inviare i dati alla stampante. Altro processo ancora attivo?"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:1085
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:1087
#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:196
msgctxt "@label:MonitorStatus"
msgid "Aborting print..."
msgstr "Interruzione stampa in corso..."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:1091
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:1093
msgctxt "@label:MonitorStatus"
msgid "Print aborted. Please check the printer"
msgstr "Stampa interrotta. Controllare la stampante"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:1097
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:1099
msgctxt "@label:MonitorStatus"
msgid "Pausing print..."
msgstr "Messa in pausa stampa..."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:1099
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:1101
msgctxt "@label:MonitorStatus"
msgid "Resuming print..."
msgstr "Ripresa stampa..."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:1289
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:1291
msgctxt "@window:title"
msgid "Sync with your printer"
msgstr "Sincronizzazione con la stampante"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:1291
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:1293
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/NetworkPrinterOutputDevice.py:1293
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:1295
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."
+msgstr "I PrintCore e/o i materiali sulla stampante differiscono da quelli contenuti nel tuo attuale progetto. Per risultati ottimali, sezionare sempre i PrintCore e i materiali inseriti nella stampante utilizzata."
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:112
msgid "This printer is not set up to host a group of connected Ultimaker 3 printers."
@@ -517,148 +521,191 @@ msgstr "Questa stampante fa da host per un gruppo di {count} stampanti Ultimaker
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:114
#, python-brace-format
msgid "{printer_name} has finished printing '{job_name}'. Please collect the print and confirm clearing the build plate."
-msgstr "{printer_name} ha terminato la stampa '{job_name}'. Raccogliere la stampa e confermare la liberazione del piano di stampa."
+msgstr "{printer_name} ha terminato la stampa '{job_name}'. Rimuovere la stampa e confermare la pulizia del piano di stampa."
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:115
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:520
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:533
#, python-brace-format
msgid "{printer_name} is reserved to print '{job_name}'. Please change the printer's configuration to match the job, for it to start printing."
msgstr "{printer_name} è riservata per la stampa di '{job_name}'. Modificare la configurazione della stampante in modo che corrisponda al lavoro da eseguire per avviare il processo di stampa."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:278
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:277
msgctxt "@info:status"
msgid "Unable to send new print job: this 3D printer is not (yet) set up to host a group of connected Ultimaker 3 printers."
msgstr "Impossibile inviare nuovo processo di stampa: questa stampante 3D non è (ancora) configurata per supportare la connessione di un gruppo di stampanti Ultimaker 3."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:410
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:423
#, python-brace-format
msgctxt "@info:status"
msgid "Unable to send print job to group {cluster_name}."
msgstr "Impossibile inviare processo di stampa a gruppo {cluster_name}."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:418
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:431
#, python-brace-format
msgctxt "@info:status"
msgid "Sent {file_name} to group {cluster_name}."
msgstr "Inviato {file_name} a gruppo {cluster_name}."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:423
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:436
msgctxt "@action:button"
msgid "Show print jobs"
msgstr "Mostra processi di stampa"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:424
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:437
msgctxt "@info:tooltip"
msgid "Opens the print jobs interface in your browser."
msgstr "Apre l'interfaccia processi di stampa sul browser."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:489
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:502
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/DiscoverUM3Action.qml:239
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/PrinterInfoBlock.qml:47
-msgctxt "@label"
+msgctxt "@label Printer name"
msgid "Unknown"
msgstr "Sconosciuto"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:492
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:505
#, 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/NetworkClusterPrinterOutputDevice.py:494
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:497
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:507
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:510
msgctxt "@info:status"
msgid "Print finished"
msgstr "Stampa finita"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:522
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:525
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:535
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:538
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/PrinterInfoBlock.qml:282
msgctxt "@label:status"
msgid "Action required"
-msgstr "Richiede un'azione"
+msgstr "Azione richiesta"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:643
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:656
#, python-brace-format
msgctxt "@info:progress"
msgid "Sending {file_name} to group {cluster_name}"
msgstr "Invio {file_name} a gruppo {cluster_name}"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/DiscoverUM3Action.py:19
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/DiscoverUM3Action.py:17
msgctxt "@action"
msgid "Connect via Network"
msgstr "Collega tramite rete"
-#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py:64
+#: /home/ruben/Projects/Cura/plugins/MonitorStage/__init__.py:12
+msgctxt "@item:inmenu"
+msgid "Monitor"
+msgstr "Controlla"
+
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py:66
#, 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:65
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py:67
#, 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:66
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py:68
msgctxt "@action:button"
msgid "How to update"
msgstr "Modalità di aggiornamento"
-#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py:77
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py:79
msgctxt "@info"
msgid "Could not access update information."
msgstr "Non è possibile accedere alle informazioni di aggiornamento."
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksReader.py:199
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksReader.py:579
msgctxt "@info:status"
-msgid "Errors appeared while opening your SolidWorks file! Please check, whether it is possible to open your file in SolidWorks itself without any problems as well!"
-msgstr "Rilevati errori all'apertura del file SolidWorks! Controllare se è possibile aprire il file in SolidWorks senza che si verifichino problemi!"
+msgid "SolidWorks reported errors, while opening your file. We recommend to solve these issues inside SolidWorks itself."
+msgstr "SolidWorks ha segnalato errori all’apertura del file. Si consiglia di risolvere queste problematiche all’interno di SolidWorks stesso."
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/__init__.py:31
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksReader.py:591
+msgctxt "@info:status"
+msgid ""
+"Found no models inside your drawing. Could you please check it's content again and make sure one part or assembly is inside?\n"
+"\n"
+" Thanks!."
+msgstr "Nessun modello trovato nel disegno. Si prega di controllare nuovamente il contenuto e accertarsi che all’interno vi sia un componente o gruppo.\n\n Grazie."
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksReader.py:595
+msgctxt "@info:status"
+msgid ""
+"Found more then one part or assembly inside your drawing. We currently only support drawings with exactly one part or assembly inside.\n"
+"\n"
+"Sorry!"
+msgstr "Trovato più di un componente o gruppo all’interno del disegno. Attualmente sono supportati solo i disegni con esattamente un componente o gruppo all’interno.\n\n Spiacenti."
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/__init__.py:25
msgctxt "@item:inlistbox"
msgid "SolidWorks part file"
msgstr "File part SolidWorks"
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/__init__.py:35
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/__init__.py:29
msgctxt "@item:inlistbox"
msgid "SolidWorks assembly file"
msgstr "File gruppo SolidWorks"
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/ConfigDialog.py:21
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/__init__.py:33
+msgctxt "@item:inlistbox"
+msgid "SolidWorks drawing file"
+msgstr "File disegno SolidWorks"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/__init__.py:48
+msgctxt "@info:status"
+msgid ""
+"Dear customer,\n"
+"We could not find a valid installation of SolidWorks on your system. That means that either SolidWorks is not installed or you don't own an valid license. Please make sure that running SolidWorks itself works without issues and/or contact your ICT.\n"
+"\n"
+"With kind regards\n"
+" - Thomas Karl Pietrowski"
+msgstr "Gentile cliente,\nnon abbiamo trovato un’installazione valida di SolidWorks nel suo sistema. Questo significa che SolidWorks non è installato o che non possiede una licenza valida. La invitiamo a verificare che l’esecuzione di SolidWorks avvenga senza problemi e/o a contattare il suo ICT.\n\nCordiali saluti\n - Thomas Karl Pietrowski"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/__init__.py:57
+msgctxt "@info:status"
+msgid ""
+"Dear customer,\n"
+"You are currently running this plugin on an operating system other than Windows. This plugin will only work on Windows with SolidWorks installed, including an valid license. Please install this plugin on a Windows machine with SolidWorks installed.\n"
+"\n"
+"With kind regards\n"
+" - Thomas Karl Pietrowski"
+msgstr "Gentile cliente,\nattualmente ha in esecuzione questo plugin su un sistema operativo diverso da Windows. Questo plugin funziona solo su Windows con SolidWorks installato, con inclusa una licenza valida. Si prega di installare questo plugin su una macchina Windows con SolidWorks installato.\n\nCordiali saluti\n - Thomas Karl Pietrowski"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksDialogHandler.py:70
msgid "Configure"
msgstr "Configura"
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/CommonComReader.py:135
-#, python-format
-msgctxt "@info:status"
-msgid "Error while starting %s!"
-msgstr "Errore durante l'avvio di %s!"
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksDialogHandler.py:71
+msgid "Installation guide for SolidWorks macro"
+msgstr "Guida per l’installazione di macro SolidWorks"
#: /home/ruben/Projects/Cura/plugins/SimulationView/__init__.py:14
msgctxt "@item:inlistbox"
-msgid "Simulation view"
-msgstr "Vista simulazione"
+msgid "Layer view"
+msgstr "Visualizzazione layer"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.py:100
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.py:103
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:101
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.py:104
msgctxt "@info:title"
msgid "Simulation View"
msgstr "Vista simulazione"
-#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.py:26
+#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.py:25
msgid "Modify G-Code"
msgstr "Modifica G-code"
#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/SliceInfo.py:43
msgctxt "@info"
-msgid "Cura collects anonymised slicing statistics. You can disable this in the preferences."
-msgstr "Cura acquisisce dati statistici elaborati in forma anonima. L'acquisizione può essere disabilitata nelle preferenze."
+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"
@@ -667,14 +714,41 @@ msgstr "Acquisizione dati"
#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/SliceInfo.py:48
msgctxt "@action:button"
-msgid "Dismiss"
-msgstr "Ignora"
+msgid "Allow"
+msgstr "Consenti"
+
+#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/SliceInfo.py:49
+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/SliceInfoPlugin/SliceInfo.py:50
+msgctxt "@action:button"
+msgid "Disable"
+msgstr "Disabilita"
+
+#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/SliceInfo.py:51
+msgctxt "@action:tooltip"
+msgid "Don't allow Cura to send anonymized usage statistics. You can enable it again in the preferences."
+msgstr "Non consente a Cura di inviare statistiche di utilizzo in forma anonima. È possibile riabilitare nelle preferenze."
#: /home/ruben/Projects/Cura/plugins/LegacyProfileReader/__init__.py:14
msgctxt "@item:inlistbox"
msgid "Cura 15.04 profiles"
msgstr "Profili Cura 15.04"
+#: /home/ruben/Projects/Cura/plugins/CuraBlenderPlugin/__init__.py:15
+msgctxt "@item:inlistbox"
+msgid "Blender file"
+msgstr "File Blender"
+
+#: /home/ruben/Projects/Cura/plugins/CuraBlenderPlugin/CadIntegrationUtils/CommonReader.py:199
+msgctxt "@info:status"
+msgid ""
+"Could not export using \"{}\" quality!\n"
+"Felt back to \"{}\"."
+msgstr "Impossibile esportare utilizzando qualità \"{}\" quality!\nTornato a \"{}\"."
+
#: /home/ruben/Projects/Cura/plugins/GCodeProfileReader/__init__.py:14
#: /home/ruben/Projects/Cura/plugins/GCodeReader/__init__.py:14
msgctxt "@item:inlistbox"
@@ -706,49 +780,49 @@ msgctxt "@item:inlistbox"
msgid "GIF Image"
msgstr "Immagine GIF"
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:269
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:299
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."
+msgstr "Impossibile eseguire lo slicing con il materiale corrente in quanto incompatibile con la macchina o la configurazione selezionata."
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:269
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:297
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:319
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:299
#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:327
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:336
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:349
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:357
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:366
msgctxt "@info:title"
msgid "Unable to slice"
-msgstr "Sezionamento impossibile"
+msgstr "Slicing impossibile"
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:296
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:326
#, 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}"
+msgstr "Impossibile eseguire lo slicing con le impostazioni attuali. Le seguenti impostazioni presentano errori: {0}"
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:318
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:348
#, 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}"
+msgstr "Impossibile eseguire lo slicing a causa di alcune impostazioni del modello. Le seguenti impostazioni presentano errori su uno o più modelli: {error_labels}"
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:326
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:356
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."
+msgstr "Impossibile eseguire lo slicing perché la prime tower o la prime position non sono valide."
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:335
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:365
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à."
#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py:50
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py:239
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py:242
msgctxt "@info:status"
msgid "Processing Layers"
msgstr "Elaborazione dei livelli"
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py:239
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py:242
msgctxt "@info:title"
msgid "Information"
msgstr "Informazioni"
@@ -769,30 +843,30 @@ msgstr "Installazione"
#: /home/ruben/Projects/Cura/plugins/cura-siemensnx-plugin/Installer.py:43
msgid "Failed to copy Siemens NX plugins files. Please check your UGII_USER_DIR. It is not set to a directory."
-msgstr "Impossibile copiare i file di plugin Siemens NX. Controllare UGII_USER_DIR. Non è assegnato ad alcuna directory."
+msgstr "Impossibile copiare i file dei plugin Siemens NX. Controllare UGII_USER_DIR. Non è assegnato ad alcuna directory."
#: /home/ruben/Projects/Cura/plugins/cura-siemensnx-plugin/Installer.py:50
#: /home/ruben/Projects/Cura/plugins/cura-siemensnx-plugin/Installer.py:59
#: /home/ruben/Projects/Cura/plugins/cura-siemensnx-plugin/Installer.py:81
msgid "Successfully installed Siemens NX Cura plugin."
-msgstr "Installato correttamente plugin Siemens NX Cura."
+msgstr "Siemens NX Cura plugin installato correttamente."
#: /home/ruben/Projects/Cura/plugins/cura-siemensnx-plugin/Installer.py:65
msgid "Failed to copy Siemens NX plugins files. Please check your UGII_USER_DIR."
-msgstr "Impossibile copiare i file di plugin Siemens NX. Controllare UGII_USER_DIR."
+msgstr "Impossibile copiare i file dei plugin Siemens NX. Controllare UGII_USER_DIR."
#: /home/ruben/Projects/Cura/plugins/cura-siemensnx-plugin/Installer.py:85
msgid "Failed to install Siemens NX plugin. Could not set environment variable UGII_USER_DIR for Siemens NX."
-msgstr "Impossibile installare plugin Siemens NX. Impossibile impostare la variabile di ambiente UGII_USER_DIR per Siemens NX."
+msgstr "Impossibile installare il plugin Siemens NX. Impossibile impostare la variabile di ambiente UGII_USER_DIR per Siemens NX."
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.py:167
-#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:585
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.py:165
+#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:590
msgctxt "@title:tab"
msgid "Recommended"
msgstr "Consigliata"
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.py:169
-#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:590
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.py:167
+#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:595
msgctxt "@title:tab"
msgid "Custom"
msgstr "Personalizzata"
@@ -803,24 +877,24 @@ msgctxt "@item:inlistbox"
msgid "3MF File"
msgstr "File 3MF"
-#: /home/ruben/Projects/Cura/plugins/3MFReader/ThreeMFWorkspaceReader.py:126
-#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:1142
+#: /home/ruben/Projects/Cura/plugins/3MFReader/ThreeMFWorkspaceReader.py:159
+#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:1185
msgctxt "@label"
msgid "Nozzle"
msgstr "Ugello"
-#: /home/ruben/Projects/Cura/plugins/PluginBrowser/PluginBrowser.py:164
+#: /home/ruben/Projects/Cura/plugins/PluginBrowser/PluginBrowser.py:152
#, python-brace-format
msgctxt "@info:status"
msgid "Failed to get plugin ID from {0}"
-msgstr "Impossibile ottenere ID plugin da {0}"
+msgstr "Impossibile ottenere ID del plugin da {0}"
-#: /home/ruben/Projects/Cura/plugins/PluginBrowser/PluginBrowser.py:165
+#: /home/ruben/Projects/Cura/plugins/PluginBrowser/PluginBrowser.py:153
msgctxt "@info:tile"
msgid "Warning"
-msgstr "Avvertenza"
+msgstr "Attenzione"
-#: /home/ruben/Projects/Cura/plugins/PluginBrowser/PluginBrowser.py:203
+#: /home/ruben/Projects/Cura/plugins/PluginBrowser/PluginBrowser.py:191
msgctxt "@window:title"
msgid "Plugin browser"
msgstr "Browser plugin"
@@ -835,21 +909,21 @@ msgctxt "@item:inlistbox"
msgid "G File"
msgstr "File G"
-#: /home/ruben/Projects/Cura/plugins/GCodeReader/GCodeReader.py:314
+#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:321
msgctxt "@info:status"
msgid "Parsing G-code"
-msgstr "Parsing codice G"
+msgstr "Analisi G-code"
-#: /home/ruben/Projects/Cura/plugins/GCodeReader/GCodeReader.py:316
-#: /home/ruben/Projects/Cura/plugins/GCodeReader/GCodeReader.py:426
+#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:323
+#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:464
msgctxt "@info:title"
msgid "G-code Details"
-msgstr "Dettagli codice G"
+msgstr "Dettagli G-code"
-#: /home/ruben/Projects/Cura/plugins/GCodeReader/GCodeReader.py:424
+#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:462
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."
+msgstr "Verifica che il G-code sia idoneo alla tua stampante e alla sua configurazione prima di trasmettere il file. La rappresentazione del G-code potrebbe non essere accurata."
#: /home/ruben/Projects/Cura/plugins/CuraProfileWriter/__init__.py:14
#: /home/ruben/Projects/Cura/plugins/CuraProfileReader/__init__.py:14
@@ -857,6 +931,16 @@ msgctxt "@item:inlistbox"
msgid "Cura Profile"
msgstr "Profilo Cura"
+#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/__init__.py:12
+msgctxt "@item:inmenu"
+msgid "Profile Assistant"
+msgstr "Assistente profilo"
+
+#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/__init__.py:17
+msgctxt "@item:inlistbox"
+msgid "Profile Assistant"
+msgstr "Assistente profilo"
+
#: /home/ruben/Projects/Cura/plugins/3MFWriter/__init__.py:30
msgctxt "@item:inlistbox"
msgid "3MF file"
@@ -888,142 +972,116 @@ msgctxt "@action"
msgid "Level build plate"
msgstr "Livella piano di stampa"
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:89
+#: /home/ruben/Projects/Cura/cura/PrintInformation.py:98
msgctxt "@tooltip"
msgid "Outer Wall"
msgstr "Parete esterna"
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:90
+#: /home/ruben/Projects/Cura/cura/PrintInformation.py:99
msgctxt "@tooltip"
msgid "Inner Walls"
msgstr "Pareti interne"
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:91
+#: /home/ruben/Projects/Cura/cura/PrintInformation.py:100
msgctxt "@tooltip"
msgid "Skin"
msgstr "Rivestimento esterno"
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:92
+#: /home/ruben/Projects/Cura/cura/PrintInformation.py:101
msgctxt "@tooltip"
msgid "Infill"
msgstr "Riempimento"
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:93
+#: /home/ruben/Projects/Cura/cura/PrintInformation.py:102
msgctxt "@tooltip"
msgid "Support Infill"
msgstr "Riempimento del supporto"
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:94
+#: /home/ruben/Projects/Cura/cura/PrintInformation.py:103
msgctxt "@tooltip"
msgid "Support Interface"
msgstr "Interfaccia supporto"
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:95
+#: /home/ruben/Projects/Cura/cura/PrintInformation.py:104
msgctxt "@tooltip"
msgid "Support"
msgstr "Supporto"
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:96
+#: /home/ruben/Projects/Cura/cura/PrintInformation.py:105
msgctxt "@tooltip"
msgid "Skirt"
msgstr "Skirt"
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:97
+#: /home/ruben/Projects/Cura/cura/PrintInformation.py:106
msgctxt "@tooltip"
msgid "Travel"
msgstr "Spostamenti"
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:98
+#: /home/ruben/Projects/Cura/cura/PrintInformation.py:107
msgctxt "@tooltip"
msgid "Retractions"
msgstr "Retrazioni"
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:99
+#: /home/ruben/Projects/Cura/cura/PrintInformation.py:108
msgctxt "@tooltip"
msgid "Other"
msgstr "Altro"
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:199
+#: /home/ruben/Projects/Cura/cura/PrintInformation.py:231
msgctxt "@label unknown material"
msgid "Unknown"
msgstr "Sconosciuto"
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:284
+#: /home/ruben/Projects/Cura/cura/PrintInformation.py:318
#, python-brace-format
msgctxt "@label"
msgid "Pre-sliced file {0}"
msgstr "File pre-sezionato {0}"
-#: /home/ruben/Projects/Cura/cura/PrinterOutputDevice.py:469
+#: /home/ruben/Projects/Cura/cura/PrinterOutputDevice.py:440
msgctxt "@item:material"
msgid "No material loaded"
msgstr "Nessun materiale caricato"
-#: /home/ruben/Projects/Cura/cura/PrinterOutputDevice.py:476
+#: /home/ruben/Projects/Cura/cura/PrinterOutputDevice.py:447
msgctxt "@item:material"
msgid "Unknown material"
msgstr "Materiale sconosciuto"
-#: /home/ruben/Projects/Cura/cura/ArrangeObjectsJob.py:30
-msgctxt "@info:status"
-msgid "Finding new location for objects"
-msgstr "Ricerca nuova posizione per gli oggetti"
-
-#: /home/ruben/Projects/Cura/cura/ArrangeObjectsJob.py:34
-msgctxt "@info:title"
-msgid "Finding Location"
-msgstr "Ricerca posizione"
-
-#: /home/ruben/Projects/Cura/cura/ArrangeObjectsJob.py:89
-#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:83
-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/ArrangeObjectsJob.py:90
-msgctxt "@info:title"
-msgid "Can't Find Location"
-msgstr "Impossibile individuare posizione"
-
-#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:431
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:113
+#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:437
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:120
msgctxt "@title:window"
msgid "File Already Exists"
msgstr "Il file esiste già"
-#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:432
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:114
+#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:438
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:121
#, python-brace-format
msgctxt "@label Don't translate the XML tag !"
msgid "The file {0} already exists. Are you sure you want to overwrite it?"
msgstr "Il file {0} esiste già. Sei sicuro di volerlo sovrascrivere?"
-#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:815
+#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:872
msgctxt "@label"
msgid "Custom"
msgstr "Personalizzata"
-#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:819
+#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:876
msgctxt "@label"
msgid "Custom Material"
msgstr "Materiale personalizzato"
-#: /home/ruben/Projects/Cura/cura/Settings/ExtrudersModel.py:182
-msgctxt "@menuitem"
-msgid "Global"
-msgstr "Globale"
-
-#: /home/ruben/Projects/Cura/cura/Settings/ExtrudersModel.py:229
+#: /home/ruben/Projects/Cura/cura/Settings/ExtrudersModel.py:205
msgctxt "@menuitem"
msgid "Not overridden"
msgstr "Non sottoposto a override"
-#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:117
+#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:124
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."
-#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:118
+#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:125
#: /home/ruben/Projects/Cura/cura/Settings/MaterialManager.py:24
msgctxt "@info:title"
msgid "Incompatible Material"
@@ -1044,67 +1102,89 @@ msgctxt "@action"
msgid "Undo changing the material diameter."
msgstr "Annulla modifica del diametro del materiale."
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:144
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:151
#, 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:151
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:158
#, 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:156
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:163
#, 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:157
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:164
msgctxt "@info:title"
msgid "Export succeeded"
msgstr "Esportazione riuscita"
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:183
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:205
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:214
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:248
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:190
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:211
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:271
#, 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}"
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:216
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:252
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:230
+#, python-brace-format
+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."
+
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:240
+#, python-brace-format
+msgctxt "@info:status Don't translate the XML tags or !"
+msgid "The machine defined in profile {0} doesn't match with your current machine, could not import it."
+msgstr "La macchina definita nel profilo {0} non corrisponde alla macchina corrente, impossibile importarlo."
+
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:274
#, python-brace-format
msgctxt "@info:status"
msgid "Successfully imported profile {0}"
msgstr "Profilo importato correttamente {0}"
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:255
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:277
+#, 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:280
#, 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:274
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:298
msgctxt "@label"
msgid "Custom profile"
msgstr "Profilo personalizzato"
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:285
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:313
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:321
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:349
#, 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:46
+#, python-brace-format
+msgctxt "@label"
+msgid "Group #{group_nr}"
+msgstr "Gruppo #{group_nr}"
+
#: /home/ruben/Projects/Cura/cura/BuildVolume.py:100
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."
@@ -1115,142 +1195,167 @@ msgctxt "@info:title"
msgid "Build Volume"
msgstr "Volume di stampa"
-#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:34
+#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:25
msgctxt "@info:status"
msgid "Multiplying and placing objects"
msgstr "Moltiplicazione e collocazione degli oggetti"
-#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:35
-#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:83
+#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:26
+#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:78
msgctxt "@info:title"
msgid "Placing Object"
msgstr "Sistemazione oggetto"
-#: /home/ruben/Projects/Cura/cura/CrashHandler.py:80
+#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:78
+#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsJob.py:88
+#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsAllBuildPlatesJob.py:152
+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:29
+#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsAllBuildPlatesJob.py:64
+msgctxt "@info:status"
+msgid "Finding new location for objects"
+msgstr "Ricerca nuova posizione per gli oggetti"
+
+#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsJob.py:33
+#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsAllBuildPlatesJob.py:68
+msgctxt "@info:title"
+msgid "Finding Location"
+msgstr "Ricerca posizione"
+
+#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsJob.py:89
+#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsAllBuildPlatesJob.py:153
+msgctxt "@info:title"
+msgid "Can't Find Location"
+msgstr "Impossibile individuare posizione"
+
+#: /home/ruben/Projects/Cura/cura/CrashHandler.py:81
msgctxt "@title:window"
msgid "Crash Report"
-msgstr "Rapporto su crash"
+msgstr "Rapporto sul crash"
-#: /home/ruben/Projects/Cura/cura/CrashHandler.py:93
+#: /home/ruben/Projects/Cura/cura/CrashHandler.py:94
msgctxt "@label crash message"
msgid ""
-"
A fatal exception has occurred. Please send us this Crash Report to fix the problem
\n"
+"
A fatal error has occurred. Please send us this Crash Report to fix the problem
\n"
"
Please use the \"Send report\" button to post a bug report automatically to our servers
\n"
" "
-msgstr "
Si è verificata un'eccezione irreversibile. Si prega di inviarci questo crash report per risolvere il problema
\n
Utilizzare il pulsante \"Invia report\" per inviare un report sui bug automaticamente ai nostri server
\n "
+msgstr "
Si è verificato un errore fatale. Si prega di inviare questo Report su crash per correggere il problema
\n
Usare il pulsante “Invia report\" per inviare automaticamente una segnalazione errore ai nostri server
"
-#: /home/ruben/Projects/Cura/cura/CrashHandler.py:141
+#: /home/ruben/Projects/Cura/cura/CrashHandler.py:147
msgctxt "@title:groupbox"
-msgid "Exception traceback"
-msgstr "Analisi eccezione"
+msgid "Error traceback"
+msgstr "Analisi errori"
-#: /home/ruben/Projects/Cura/cura/CrashHandler.py:208
+#: /home/ruben/Projects/Cura/cura/CrashHandler.py:214
msgctxt "@title:groupbox"
msgid "Logs"
msgstr "Registri"
-#: /home/ruben/Projects/Cura/cura/CrashHandler.py:231
+#: /home/ruben/Projects/Cura/cura/CrashHandler.py:237
msgctxt "@title:groupbox"
msgid "User description"
msgstr "Descrizione utente"
-#: /home/ruben/Projects/Cura/cura/CrashHandler.py:246
+#: /home/ruben/Projects/Cura/cura/CrashHandler.py:252
msgctxt "@action:button"
msgid "Send report"
msgstr "Invia report"
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:256
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:274
msgctxt "@info:progress"
msgid "Loading machines..."
msgstr "Caricamento macchine in corso..."
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:661
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:660
msgctxt "@info:progress"
msgid "Setting up scene..."
msgstr "Impostazione scena in corso..."
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:703
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:702
msgctxt "@info:progress"
msgid "Loading interface..."
msgstr "Caricamento interfaccia in corso..."
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:874
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:899
#, 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:1348
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1417
#, 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}"
+msgstr "È possibile caricare un solo file G-code per volta. Importazione saltata {0}"
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1357
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1426
#, 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}"
+msgstr "Impossibile aprire altri file durante il caricamento del G-code. Importazione saltata {0}"
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1416
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1495
msgctxt "@info:status"
msgid "The selected model was too small to load."
msgstr "Il modello selezionato è troppo piccolo per il caricamento."
@@ -1279,12 +1384,11 @@ msgstr "X (Larghezza)"
#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:119
#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:129
#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:235
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:288
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:300
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:391
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:401
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:413
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:840
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:383
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:394
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:412
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:424
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:849
msgctxt "@label"
msgid "mm"
msgstr "mm"
@@ -1322,7 +1426,7 @@ msgstr "Versione GCode"
#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:181
msgctxt "@label"
msgid "Printhead Settings"
-msgstr "Impostazioni della testina di stampa"
+msgstr "Impostazioni della testa di stampa"
#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:191
msgctxt "@label"
@@ -1332,7 +1436,7 @@ msgstr "X min"
#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:192
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\"."
+msgstr "Distanza tra il lato sinistro della testa di stampa e il centro dell'ugello. Utilizzata per evitare collisioni tra le stampe precedenti e la testa di stampa durante la stampa \"Uno alla volta\"."
#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:201
msgctxt "@label"
@@ -1342,7 +1446,7 @@ msgstr "Y min"
#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:202
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\"."
+msgstr "Distanza tra il lato anteriore della testa di stampa e il centro dell'ugello. Utilizzata per evitare collisioni tra le stampe precedenti e la testa di stampa durante la stampa \"Uno alla volta\"."
#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:211
msgctxt "@label"
@@ -1352,7 +1456,7 @@ msgstr "X max"
#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:212
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\"."
+msgstr "Distanza tra il lato destro della testa di stampa e il centro dell'ugello. Utilizzata per evitare collisioni tra le stampe precedenti e la testa di stampa durante la stampa \"Uno alla volta\"."
#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:221
msgctxt "@label"
@@ -1362,7 +1466,7 @@ msgstr "Y max"
#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:222
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\"."
+msgstr "Distanza tra il lato posteriore della testa di stampa e il centro dell'ugello. Utilizzata per evitare collisioni tra le stampe precedenti e la testa di stampa durante la stampa \"Uno alla volta\"."
#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:234
msgctxt "@label"
@@ -1374,71 +1478,70 @@ 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:255
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:254
msgctxt "@label"
msgid "Number of Extruders"
msgstr "Numero di estrusori"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:289
-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:291
-msgctxt "@label"
-msgid "Material diameter"
-msgstr "Diametro materiale"
-
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:299
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:390
-msgctxt "@label"
-msgid "Nozzle size"
-msgstr "Dimensione ugello"
-
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:317
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:310
msgctxt "@label"
msgid "Start Gcode"
msgstr "Avvio GCode"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:327
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:320
msgctxt "@tooltip"
msgid "Gcode commands to be executed at the very start."
msgstr "Comandi Gcode da eseguire all’avvio."
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:336
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:329
msgctxt "@label"
msgid "End Gcode"
msgstr "Fine GCode"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:346
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:339
msgctxt "@tooltip"
msgid "Gcode commands to be executed at the very end."
msgstr "Comandi Gcode da eseguire alla fine."
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:378
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:370
msgctxt "@label"
msgid "Nozzle Settings"
msgstr "Impostazioni ugello"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:400
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:382
+msgctxt "@label"
+msgid "Nozzle size"
+msgstr "Dimensione ugello"
+
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:393
+msgctxt "@label"
+msgid "Compatible material diameter"
+msgstr "Diametro del materiale compatibile"
+
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:395
+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à sovrascritto dal materiale e/o dal profilo."
+
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:411
msgctxt "@label"
msgid "Nozzle offset X"
msgstr "Scostamento X ugello"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:412
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:423
msgctxt "@label"
msgid "Nozzle offset Y"
msgstr "Scostamento Y ugello"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:433
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:444
msgctxt "@label"
msgid "Extruder Start Gcode"
-msgstr "Codice G avvio estrusore"
+msgstr "Gcode avvio estrusore"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:451
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.qml:462
msgctxt "@label"
msgid "Extruder End Gcode"
-msgstr "Codice G fine estrusore"
+msgstr "Gcode fine estrusore"
#: /home/ruben/Projects/Cura/plugins/ChangeLogPlugin/ChangeLog.qml:18
msgctxt "@label"
@@ -1448,8 +1551,9 @@ msgstr "Registro modifiche"
#: /home/ruben/Projects/Cura/plugins/ChangeLogPlugin/ChangeLog.qml:37
#: /home/ruben/Projects/Cura/plugins/USBPrinting/FirmwareUpdateWindow.qml:107
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/UM3InfoComponents.qml:55
-#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.qml:445
-#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:357
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksMacroTutorial.qml:306
+#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.qml:456
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:492
#: /home/ruben/Projects/Cura/plugins/PluginBrowser/PluginBrowser.qml:80
#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:123
#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:147
@@ -1514,7 +1618,7 @@ 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\nSelezionare la stampante dall’elenco seguente:"
+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 Gcode alla stampante.\n\nSelezionare la stampante dall’elenco seguente:"
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/DiscoverUM3Action.qml:75
#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:44
@@ -1530,7 +1634,7 @@ msgstr "Modifica"
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/DiscoverUM3Action.qml:96
#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:50
#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:95
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:190
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:171
msgctxt "@action:button"
msgid "Remove"
msgstr "Rimuovi"
@@ -1552,14 +1656,14 @@ msgid "Type"
msgstr "Tipo"
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/DiscoverUM3Action.qml:233
-msgctxt "@label"
+msgctxt "@label Printer name"
msgid "Ultimaker 3"
msgstr "Ultimaker 3"
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/DiscoverUM3Action.qml:236
-msgctxt "@label"
+msgctxt "@label Printer name"
msgid "Ultimaker 3 Extended"
-msgstr "Ultimaker3 Extended"
+msgstr "Ultimaker 3 Extended"
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/DiscoverUM3Action.qml:252
msgctxt "@label"
@@ -1603,8 +1707,6 @@ 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/DiscoverUM3Action.qml:379
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/ConfigDialog.qml:92
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/ExportSTLUI.qml:88
#: /home/ruben/Projects/Cura/plugins/ImageReader/ConfigUI.qml:181
msgctxt "@action:button"
msgid "OK"
@@ -1613,7 +1715,7 @@ msgstr "OK"
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/PrintWindow.qml:24
msgctxt "@title:window"
msgid "Print over network"
-msgstr "Stampa sulla rete"
+msgstr "Stampa tramite rete"
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/PrintWindow.qml:92
msgctxt "@action:button"
@@ -1625,6 +1727,11 @@ msgctxt "@label: arg 1 is group name"
msgid "%1 is not set up to host a group of connected Ultimaker 3 printers"
msgstr "%1 non è configurata per supportare la connessione di un gruppo di stampanti Ultimaker 3"
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/ClusterMonitorItem.qml:55
+msgctxt "@label link to connect manager"
+msgid "Add/Remove printers"
+msgstr "Aggiungi/Rimuovi stampanti"
+
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/OpenPanelButton.qml:14
msgctxt "@info:tooltip"
msgid "Opens the print jobs page with your default web browser."
@@ -1655,11 +1762,16 @@ msgid "Available"
msgstr "Disponibile"
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/PrinterInfoBlock.qml:43
-#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:101
+#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:100
msgctxt "@label:MonitorStatus"
msgid "Lost connection with the printer"
msgstr "Persa connessione con la stampante"
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/PrinterInfoBlock.qml:47
+msgctxt "@label Printer status"
+msgid "Unknown"
+msgstr "Sconosciuto"
+
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/PrinterInfoBlock.qml:257
msgctxt "@label:status"
msgid "Disabled"
@@ -1704,7 +1816,7 @@ msgstr "Finisce alle: "
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/PrinterInfoBlock.qml:405
msgctxt "@label"
msgid "Clear build plate"
-msgstr "Cancellare piano di stampa"
+msgstr "Pulire piano di stampa"
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/PrinterInfoBlock.qml:414
msgctxt "@label"
@@ -1751,138 +1863,250 @@ msgctxt "@action:button"
msgid "Activate Configuration"
msgstr "Attiva la configurazione"
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/ConfigDialog.qml:20
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksWizard.qml:21
msgctxt "@title:window"
-msgid "Cura SolidWorks Plugin Configuration"
-msgstr "Configurazione plugin Cura SolidWorks"
+msgid "SolidWorks: Export wizard"
+msgstr "SolidWorks: procedura guidata per l’esportazione"
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/ConfigDialog.qml:44
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksWizard.qml:45
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:140
msgctxt "@action:label"
-msgid "Default quality of the exported STL:"
-msgstr "Qualità predefinita STL esportato:"
+msgid "Quality:"
+msgstr "Qualità:"
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/ConfigDialog.qml:79
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksWizard.qml:78
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:179
msgctxt "@option:curaSolidworksStlQuality"
-msgid "Always ask"
-msgstr "Chiedi sempre"
+msgid "Fine (3D-printing)"
+msgstr "Fine (stampa 3D)"
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/ConfigDialog.qml:80
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksWizard.qml:79
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:180
msgctxt "@option:curaSolidworksStlQuality"
-msgid "Always use Fine quality"
-msgstr "Utilizza sempre la qualità Fine"
+msgid "Coarse (3D-printing)"
+msgstr "Grossolana (stampa 3D)"
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/ConfigDialog.qml:81
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksWizard.qml:80
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:181
msgctxt "@option:curaSolidworksStlQuality"
-msgid "Always use Coarse quality"
-msgstr "Utilizza sempre la qualità Grossolana"
+msgid "Fine (SolidWorks)"
+msgstr "Fine (SolidWorks)"
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/ExportSTLUI.qml:20
-msgctxt "@title:window"
-msgid "Import SolidWorks File as STL..."
-msgstr "Importa file SolidWorks come STL..."
-
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/ExportSTLUI.qml:43
-msgctxt "@info:tooltip"
-msgid "Quality of the Exported STL"
-msgstr "Qualità STL esportato"
-
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/ExportSTLUI.qml:48
-msgctxt "@action:label"
-msgid "Quality"
-msgstr "Qualità"
-
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/ExportSTLUI.qml:62
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksWizard.qml:81
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:182
msgctxt "@option:curaSolidworksStlQuality"
-msgid "Coarse"
-msgstr "Grossolana"
+msgid "Coarse (SolidWorks)"
+msgstr "Grossolana (SolidWorks)"
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/ExportSTLUI.qml:63
-msgctxt "@option:curaSolidworksStlQuality"
-msgid "Fine"
-msgstr "Fine"
-
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/ExportSTLUI.qml:78
-#: /home/ruben/Projects/Cura/resources/qml/AskOpenAsProjectOrModelsDialog.qml:82
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksWizard.qml:94
msgctxt "@text:window"
-msgid "Remember my choice"
-msgstr "Ricorda la scelta"
+msgid "Show this dialog again"
+msgstr "Mostra nuovamente questa finestra di dialogo"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:81
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksWizard.qml:104
+msgctxt "@action:button"
+msgid "Continue"
+msgstr "Continua"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksWizard.qml:116
+msgctxt "@action:button"
+msgid "Abort"
+msgstr "Interrompi"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksMacroTutorial.qml:21
+msgctxt "@title:window"
+msgid "How to install Cura SolidWorks macro"
+msgstr "Come installare la macro Cura SolidWorks"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksMacroTutorial.qml:62
+msgctxt "@description:label"
+msgid "Steps:"
+msgstr "Fasi:"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksMacroTutorial.qml:140
+msgctxt "@action:button"
+msgid ""
+"Open the directory\n"
+"with macro and icon"
+msgstr "Aprire la directory\ncon macro e icona"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksMacroTutorial.qml:160
+msgctxt "@description:label"
+msgid "Instructions:"
+msgstr "Istruzioni:"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksMacroTutorial.qml:202
+msgctxt "@action:playpause"
+msgid "Play"
+msgstr "Riproduci"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksMacroTutorial.qml:206
+msgctxt "@action:playpause"
+msgid "Pause"
+msgstr "Pausa"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksMacroTutorial.qml:268
+msgctxt "@action:button"
+msgid "Previous Step"
+msgstr "Fase precedente"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksMacroTutorial.qml:283
+msgctxt "@action:button"
+msgid "Done"
+msgstr "Eseguito"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksMacroTutorial.qml:287
+msgctxt "@action:button"
+msgid "Next Step"
+msgstr "Fase successiva"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:21
+msgctxt "@title:window"
+msgid "SolidWorks plugin: Configuration"
+msgstr "Plugin SolidWorks: configurazione"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:39
+msgctxt "@title:tab"
+msgid "Conversion settings"
+msgstr "Impostazioni di conversione"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:66
+msgctxt "@label"
+msgid "First choice:"
+msgstr "Prima scelta:"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:86
+msgctxt "@text:menu"
+msgid "Latest installed version (Recommended)"
+msgstr "Ultima versione installata (consigliata)"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:95
+msgctxt "@text:menu"
+msgid "Default version"
+msgstr "Versione predefinita"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:193
+msgctxt "@label"
+msgid "Show wizard before opening SolidWorks files"
+msgstr "Mostra la procedura guidata prima di aprire i file SolidWorks"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:203
+msgctxt "@label"
+msgid "Automatically rotate opened file into normed orientation"
+msgstr "Ruota automaticamente il file aperto nell’orientamento corretto"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:210
+msgctxt "@title:tab"
+msgid "Installation(s)"
+msgstr "Installazione(i)"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:284
+msgctxt "@label"
+msgid "COM service found"
+msgstr "Servizio COM trovato"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:295
+msgctxt "@label"
+msgid "Executable found"
+msgstr "Eseguibile trovato"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:306
+msgctxt "@label"
+msgid "COM starting"
+msgstr "COM in avvio"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:317
+msgctxt "@label"
+msgid "Revision number"
+msgstr "Numero di revisione"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:328
+msgctxt "@label"
+msgid "Functions available"
+msgstr "Funzioni disponibili"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:341
+#: /home/ruben/Projects/Cura/resources/qml/WorkspaceSummaryDialog.qml:264
+msgctxt "@action:button"
+msgid "Save"
+msgstr "Salva"
+
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:117
msgctxt "@label"
msgid "Color scheme"
msgstr "Schema colori"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:96
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:132
msgctxt "@label:listbox"
msgid "Material Color"
msgstr "Colore materiale"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:100
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:136
msgctxt "@label:listbox"
msgid "Line Type"
msgstr "Tipo di linea"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:104
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:140
msgctxt "@label:listbox"
msgid "Feedrate"
msgstr "Velocità"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:108
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:144
msgctxt "@label:listbox"
msgid "Layer thickness"
-msgstr "Spessore strato"
+msgstr "Spessore layer"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:148
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:185
msgctxt "@label"
msgid "Compatibility Mode"
msgstr "Modalità di compatibilità"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:230
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:264
msgctxt "@label"
msgid "Show Travels"
msgstr "Mostra spostamenti"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:236
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:270
msgctxt "@label"
msgid "Show Helpers"
msgstr "Mostra helper"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:242
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:276
msgctxt "@label"
msgid "Show Shell"
msgstr "Mostra guscio"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:248
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:282
msgctxt "@label"
msgid "Show Infill"
msgstr "Mostra riempimento"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:297
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:330
msgctxt "@label"
msgid "Only Show Top Layers"
msgstr "Mostra solo strati superiori"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:306
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:339
msgctxt "@label"
msgid "Show 5 Detailed Layers On Top"
-msgstr "Mostra 5 strati superiori in dettaglio"
+msgstr "Mostra 5 layer superiori in dettaglio"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:317
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:350
msgctxt "@label"
msgid "Top / Bottom"
msgstr "Superiore / Inferiore"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:321
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:354
msgctxt "@label"
msgid "Inner Wall"
msgstr "Parete interna"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:378
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:410
msgctxt "@label"
msgid "min"
msgstr "min."
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:420
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.qml:452
msgctxt "@label"
msgid "max"
msgstr "max."
@@ -1907,7 +2131,7 @@ msgctxt "@label"
msgid "Settings"
msgstr "Impostazioni"
-#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.qml:455
+#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.qml:466
msgctxt "@info:tooltip"
msgid "Change active post-processing scripts"
msgstr "Modifica script di post-elaborazione attivi"
@@ -1982,23 +2206,53 @@ msgctxt "@action:label"
msgid "Smoothing"
msgstr "Smoothing"
-#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:208
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:38
+msgctxt "@label"
+msgid "Mesh Type"
+msgstr "Tipo di maglia"
+
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:69
+msgctxt "@label"
+msgid "Normal model"
+msgstr "Modello normale"
+
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:76
+msgctxt "@label"
+msgid "Print as support"
+msgstr "Stampa come supporto"
+
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:84
+msgctxt "@label"
+msgid "Don't support overlap with other models"
+msgstr "Non supporta sovrapposizione con altri modelli"
+
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:92
+msgctxt "@label"
+msgid "Modify settings for overlap with other models"
+msgstr "Modifica impostazioni per sovrapposizione con altri modelli"
+
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:100
+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:333
msgctxt "@action:button"
msgid "Select settings"
msgstr "Seleziona impostazioni"
-#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:248
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:375
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:272
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:402
#: /home/ruben/Projects/Cura/resources/qml/Preferences/SettingVisibilityPage.qml:91
msgctxt "@label:textbox"
msgid "Filter..."
msgstr "Filtro..."
-#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:296
+#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:426
msgctxt "@label:checkbox"
msgid "Show all"
msgstr "Mostra tutto"
@@ -2197,7 +2451,7 @@ msgstr "Seleziona qualsiasi aggiornamento realizzato per questa Ultimaker 2."
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UM2UpgradeSelectionMachineAction.qml:45
msgctxt "@label"
msgid "Olsson Block"
-msgstr "Blocco Olsson"
+msgstr "Olsson Block"
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/BedLevelMachineAction.qml:27
msgctxt "@title"
@@ -2212,7 +2466,7 @@ msgstr "Per assicurarsi stampe di alta qualità, è ora possibile regolare il pi
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/BedLevelMachineAction.qml:47
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."
+msgstr "Per ciascuna posizione: inserire un pezzo di carta sotto l'ugello e regolare l'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
msgctxt "@action:button"
@@ -2357,66 +2611,66 @@ 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:88
+#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:87
msgctxt "@label:MonitorStatus"
msgid "Not connected to a printer"
msgstr "Non collegato ad una stampante"
-#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:90
+#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:89
msgctxt "@label:MonitorStatus"
msgid "Printer does not accept commands"
msgstr "La stampante non accetta comandi"
-#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:96
+#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:95
#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:194
msgctxt "@label:MonitorStatus"
msgid "In maintenance. Please check the printer"
msgstr "In manutenzione. Controllare la stampante"
-#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:103
+#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:102
#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:184
msgctxt "@label:MonitorStatus"
msgid "Printing..."
msgstr "Stampa in corso..."
-#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:106
+#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:105
#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:186
msgctxt "@label:MonitorStatus"
msgid "Paused"
msgstr "In pausa"
-#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:109
+#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:108
#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:188
msgctxt "@label:MonitorStatus"
msgid "Preparing..."
msgstr "Preparazione in corso..."
-#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:111
+#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:110
msgctxt "@label:MonitorStatus"
msgid "Please remove the print"
msgstr "Rimuovere la stampa"
-#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:237
+#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:241
msgctxt "@label:"
msgid "Resume"
msgstr "Riprendi"
-#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:241
+#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:245
msgctxt "@label:"
msgid "Pause"
msgstr "Pausa"
-#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:270
+#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:274
msgctxt "@label:"
msgid "Abort Print"
msgstr "Interrompi la stampa"
-#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:280
+#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:284
msgctxt "@window:title"
msgid "Abort print"
msgstr "Interrompi la stampa"
-#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:282
+#: /home/ruben/Projects/Cura/resources/qml/MonitorButton.qml:286
msgctxt "@label"
msgid "Are you sure you want to abort the print?"
msgstr "Sei sicuro di voler interrompere la stampa?"
@@ -2449,19 +2703,19 @@ msgid "Customized"
msgstr "Valore personalizzato"
#: /home/ruben/Projects/Cura/resources/qml/DiscardOrKeepProfileChangesDialog.qml:157
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:593
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:595
msgctxt "@option:discardOrKeep"
msgid "Always ask me this"
msgstr "Chiedi sempre"
#: /home/ruben/Projects/Cura/resources/qml/DiscardOrKeepProfileChangesDialog.qml:158
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:594
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:596
msgctxt "@option:discardOrKeep"
msgid "Discard and never ask again"
msgstr "Elimina e non chiedere nuovamente"
#: /home/ruben/Projects/Cura/resources/qml/DiscardOrKeepProfileChangesDialog.qml:159
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:595
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:597
msgctxt "@option:discardOrKeep"
msgid "Keep and never ask again"
msgstr "Mantieni e non chiedere nuovamente"
@@ -2496,72 +2750,72 @@ msgctxt "@label"
msgid "Brand"
msgstr "Marchio"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:92
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:88
msgctxt "@label"
msgid "Material Type"
msgstr "Tipo di materiale"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:105
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:97
msgctxt "@label"
msgid "Color"
msgstr "Colore"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:139
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:141
msgctxt "@label"
msgid "Properties"
msgstr "Proprietà"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:141
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:143
msgctxt "@label"
msgid "Density"
msgstr "Densità"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:156
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:158
msgctxt "@label"
msgid "Diameter"
msgstr "Diametro"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:185
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:187
msgctxt "@label"
msgid "Filament Cost"
msgstr "Costo del filamento"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:201
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:203
msgctxt "@label"
msgid "Filament weight"
msgstr "Peso del filamento"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:218
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:220
msgctxt "@label"
msgid "Filament length"
msgstr "Lunghezza del filamento"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:227
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:229
msgctxt "@label"
msgid "Cost per Meter"
msgstr "Costo al metro"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:241
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:243
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/MaterialView.qml:248
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:250
msgctxt "@label"
msgid "Unlink Material"
msgstr "Scollega materiale"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:259
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:261
msgctxt "@label"
msgid "Description"
msgstr "Descrizione"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:272
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:274
msgctxt "@label"
msgid "Adhesion Information"
msgstr "Informazioni sull’aderenza"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:298
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialView.qml:300
msgctxt "@label"
msgid "Print settings"
msgstr "Impostazioni di stampa"
@@ -2602,7 +2856,7 @@ msgid "Unit"
msgstr "Unità"
#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:14
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:439
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:509
msgctxt "@title:tab"
msgid "General"
msgstr "Generale"
@@ -2617,230 +2871,255 @@ msgctxt "@label"
msgid "Language:"
msgstr "Lingua:"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:205
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:207
msgctxt "@label"
msgid "Currency:"
msgstr "Valuta:"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:219
+#: /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:279
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:281
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:296
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:298
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:304
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:306
msgctxt "@option:check"
msgid "Slice automatically"
msgstr "Seziona automaticamente"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:318
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:320
msgctxt "@label"
msgid "Viewport behavior"
msgstr "Comportamento del riquadro di visualizzazione"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:326
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:328
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:335
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:337
msgctxt "@option:check"
msgid "Display overhang"
msgstr "Visualizza sbalzo"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:342
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:344
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"
+msgstr "Sposta la camera in modo che il modello si trovi al centro della visualizzazione quando è selezionato"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:347
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:349
msgctxt "@action:button"
msgid "Center camera when item is selected"
-msgstr "Centratura fotocamera alla selezione dell'elemento"
+msgstr "Centratura camera alla selezione dell'elemento"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:356
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:358
msgctxt "@info:tooltip"
msgid "Should the default zoom behavior of cura be inverted?"
msgstr "Il comportamento dello zoom predefinito di Cura dovrebbe essere invertito?"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:361
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:363
msgctxt "@action:button"
msgid "Invert the direction of camera zoom."
-msgstr "Inverti la direzione dello zoom della fotocamera."
+msgstr "Inverti la direzione dello zoom della camera."
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:370
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:372
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:375
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:377
msgctxt "@action:button"
msgid "Zoom toward mouse direction"
msgstr "Zoom verso la direzione del mouse"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:384
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:386
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:389
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:391
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:397
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:399
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:402
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:404
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:414
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:416
msgctxt "@info:tooltip"
msgid "Show caution message in gcode reader."
-msgstr "Visualizza il messaggio di avvertimento sul lettore codice G."
+msgstr "Visualizza il messaggio di avvertimento sul lettore gcode."
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:423
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:425
msgctxt "@option:check"
msgid "Caution message in gcode reader"
-msgstr "Messaggio di avvertimento sul lettore codice G"
+msgstr "Messaggio di avvertimento sul lettore gcode"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:430
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:432
msgctxt "@info:tooltip"
msgid "Should layer be forced into compatibility mode?"
-msgstr "Lo strato deve essere forzato in modalità di compatibilità?"
+msgstr "Il layer deve essere forzato in modalità di compatibilità?"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:435
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:437
msgctxt "@option:check"
msgid "Force layer view compatibility mode (restart required)"
-msgstr "Forzare la modalità di compatibilità visualizzazione strato (riavvio necessario)"
+msgstr "Forzare la modalità di compatibilità visualizzazione layer (riavvio necessario)"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:451
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:453
msgctxt "@label"
msgid "Opening and saving files"
msgstr "Apertura e salvataggio file"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:457
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:459
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:462
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:464
msgctxt "@option:check"
msgid "Scale large models"
msgstr "Ridimensiona i modelli troppo grandi"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:471
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:473
msgctxt "@info:tooltip"
msgid "An model may appear extremely small if its unit is for example in meters rather than millimeters. Should these models be scaled up?"
msgstr "Un modello può apparire eccessivamente piccolo se la sua unità di misura è espressa in metri anziché in millimetri. Questi modelli devono essere aumentati?"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:476
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:478
msgctxt "@option:check"
msgid "Scale extremely small models"
msgstr "Ridimensiona i modelli eccessivamente piccoli"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:485
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:487
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:490
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:492
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:499
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:501
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:503
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:505
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:512
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:514
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:520
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:522
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:533
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:535
msgctxt "@option:openProject"
msgid "Always ask"
msgstr "Chiedi sempre"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:534
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:536
msgctxt "@option:openProject"
msgid "Always open as a project"
msgstr "Apri sempre come progetto"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:535
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:537
msgctxt "@option:openProject"
msgid "Always import models"
msgstr "Importa sempre i modelli"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:571
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:573
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:580
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:582
msgctxt "@label"
msgid "Override Profile"
msgstr "Override profilo"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:629
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:631
msgctxt "@label"
msgid "Privacy"
msgstr "Privacy"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:636
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:638
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:641
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:643
msgctxt "@option:check"
msgid "Check for updates on start"
msgstr "Controlla aggiornamenti all’avvio"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:651
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:653
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:656
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:658
msgctxt "@option:check"
msgid "Send (anonymous) print information"
msgstr "Invia informazioni di stampa (anonime)"
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:674
+msgctxt "@label"
+msgid "Experimental"
+msgstr "Sperimentale"
+
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:680
+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:685
+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/GeneralPage.qml:694
+msgctxt "@info:tooltip"
+msgid "Should newly loaded models be arranged on the build plate? Used in conjunction with multi build plate (EXPERIMENTAL)"
+msgstr "I modelli appena caricati devono essere sistemati sul piano di stampa? Utilizzato in abbinamento al piano di stampa multiplo (SPERIMENTALE)"
+
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/GeneralPage.qml:699
+msgctxt "@option:check"
+msgid "Do not arrange objects on load"
+msgstr "Non posizionare oggetti dopo il caricamento"
+
#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:15
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:444
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:514
msgctxt "@title:tab"
msgid "Printers"
msgstr "Stampanti"
#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:37
#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:51
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:137
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:138
msgctxt "@action:button"
msgid "Activate"
msgstr "Attiva"
@@ -2875,7 +3154,7 @@ msgstr "Stato:"
#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:190
msgctxt "@label:MonitorStatus"
msgid "Waiting for someone to clear the build plate"
-msgstr "In attesa di qualcuno che cancelli il piano di stampa"
+msgstr "In attesa che qualcuno liberi il piano di stampa"
#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:199
msgctxt "@label:MonitorStatus"
@@ -2883,7 +3162,7 @@ msgid "Waiting for a printjob"
msgstr "In attesa di un processo di stampa"
#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:15
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:448
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:518
msgctxt "@title:tab"
msgid "Profiles"
msgstr "Profili"
@@ -2909,13 +3188,13 @@ msgid "Duplicate"
msgstr "Duplica"
#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:113
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:201
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:182
msgctxt "@action:button"
msgid "Import"
msgstr "Importa"
#: /home/ruben/Projects/Cura/resources/qml/Preferences/ProfilesPage.qml:119
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:212
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:193
msgctxt "@action:button"
msgid "Export"
msgstr "Esporta"
@@ -2981,7 +3260,7 @@ msgid "Export Profile"
msgstr "Esporta profilo"
#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:15
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:446
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:516
msgctxt "@title:tab"
msgid "Materials"
msgstr "Materiali"
@@ -2996,60 +3275,60 @@ msgctxt "@action:label %1 is printer name"
msgid "Printer: %1"
msgstr "Stampante: %1"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:149
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:150
msgctxt "@action:button"
msgid "Create"
msgstr "Crea"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:168
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:160
msgctxt "@action:button"
msgid "Duplicate"
msgstr "Duplica"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:311
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:319
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:298
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:306
msgctxt "@title:window"
msgid "Import Material"
msgstr "Importa materiale"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:320
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:307
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/MaterialsPage.qml:324
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:311
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/MaterialsPage.qml:343
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:358
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:329
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:344
msgctxt "@title:window"
msgid "Export Material"
msgstr "Esporta materiale"
-#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:362
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:348
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/MaterialsPage.qml:368
+#: /home/ruben/Projects/Cura/resources/qml/Preferences/MaterialsPage.qml:354
msgctxt "@info:status Don't translate the XML tag !"
msgid "Successfully exported material to %1"
msgstr "Materiale esportato correttamente su %1"
#: /home/ruben/Projects/Cura/resources/qml/AddMachineDialog.qml:18
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:793
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:869
msgctxt "@title:window"
msgid "Add Printer"
msgstr "Aggiungi stampante"
-#: /home/ruben/Projects/Cura/resources/qml/AddMachineDialog.qml:185
+#: /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:208
+#: /home/ruben/Projects/Cura/resources/qml/AddMachineDialog.qml:217
msgctxt "@action:button"
msgid "Add Printer"
msgstr "Aggiungi stampante"
@@ -3176,12 +3455,7 @@ msgctxt "@label"
msgid "Profile:"
msgstr "Profilo:"
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:66
-msgctxt "@"
-msgid "No Profile Available"
-msgstr "Nessun profilo disponibile"
-
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:104
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:102
msgctxt "@tooltip"
msgid ""
"Some setting/override values are different from the values stored in the profile.\n"
@@ -3189,37 +3463,37 @@ msgid ""
"Click to open the profile manager."
msgstr "Alcuni valori di impostazione/esclusione sono diversi dai valori memorizzati nel profilo.\n\nFare clic per aprire la gestione profili."
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:152
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:150
msgctxt "@label:textbox"
msgid "Search..."
msgstr "Ricerca..."
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:483
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:482
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:498
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:497
msgctxt "@action:menu"
msgid "Hide this setting"
msgstr "Nascondi questa impostazione"
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:508
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:507
msgctxt "@action:menu"
msgid "Don't show this setting"
msgstr "Nascondi questa impostazione"
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:512
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:511
msgctxt "@action:menu"
msgid "Keep this setting visible"
msgstr "Mantieni visibile questa impostazione"
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:531
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingView.qml:530
msgctxt "@action:menu"
msgid "Configure setting visiblity..."
msgstr "Configurazione visibilità delle impostazioni in corso..."
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingCategory.qml:123
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingCategory.qml:250
msgctxt "@label"
msgid ""
"Some hidden settings use values different from their normal calculated value.\n"
@@ -3227,27 +3501,27 @@ msgid ""
"Click to make these settings visible."
msgstr "Alcune impostazioni nascoste utilizzano valori diversi dal proprio valore normale calcolato.\n\nFare clic per rendere visibili queste impostazioni."
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:62
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:61
msgctxt "@label Header for list of settings."
msgid "Affects"
msgstr "Influisce su"
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:67
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:66
msgctxt "@label Header for list of settings."
msgid "Affected By"
msgstr "Influenzato da"
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:157
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:156
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"
+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:160
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:159
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:186
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:190
msgctxt "@label"
msgid ""
"This setting has a value that is different from the profile.\n"
@@ -3255,7 +3529,7 @@ msgid ""
"Click to restore the value of the profile."
msgstr "Questa impostazione ha un valore diverso dal profilo.\n\nFare clic per ripristinare il valore del profilo."
-#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:284
+#: /home/ruben/Projects/Cura/resources/qml/Settings/SettingItem.qml:288
msgctxt "@label"
msgid ""
"This setting is normally calculated, but it currently has an absolute value set.\n"
@@ -3263,71 +3537,71 @@ msgid ""
"Click to restore the calculated value."
msgstr "Questa impostazione normalmente viene calcolata, ma attualmente ha impostato un valore assoluto.\n\nFare clic per ripristinare il valore calcolato."
-#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:120
+#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:128
msgctxt "@label:listbox"
msgid "Print Setup"
msgstr "Impostazione di stampa"
-#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:120
+#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:128
msgctxt "@label:listbox"
msgid ""
"Print Setup disabled\n"
"G-code files cannot be modified"
-msgstr "Impostazione di stampa disabilitata\nI file codice G non possono essere modificati"
+msgstr "Impostazione di stampa disabilitata\nI file G-code non possono essere modificati"
-#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:336
+#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:342
msgctxt "@label Hours and minutes"
msgid "00h 00min"
msgstr "00h 00min"
-#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:354
+#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:359
msgctxt "@tooltip"
-msgid "Time specification
"
-msgstr "Indicazione del tempo
"
+msgid "Time specification"
+msgstr "Indicazioni di tempo"
-#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:429
+#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:441
msgctxt "@label"
msgid "Cost specification"
msgstr "Indicazione di costo"
-#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:434
-#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:445
+#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:446
+#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:455
msgctxt "@label m for meter"
msgid "%1m"
msgstr "%1m"
-#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:435
-#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:446
+#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:447
+#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:456
msgctxt "@label g for grams"
msgid "%1g"
msgstr "%1g"
-#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:444
+#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:454
msgctxt "@label"
msgid "Total:"
msgstr "Totale:"
-#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:498
+#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:504
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/resources/qml/Sidebar.qml:503
+#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:509
msgctxt "@label Print estimates: m for meters, g for grams"
msgid "%1m / ~ %2g"
msgstr "%1m / ~ %2g"
-#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:586
+#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:591
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/Sidebar.qml:591
+#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:596
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."
+msgstr "Impostazione di stampa personalizzata
Stampa con il controllo grana fine su ogni sezione finale del processo di slicing."
-#: /home/ruben/Projects/Cura/resources/qml/Menus/MaterialMenu.qml:49
+#: /home/ruben/Projects/Cura/resources/qml/Menus/MaterialMenu.qml:50
msgctxt "@title:menuitem %1 is the automatically selected material"
msgid "Automatic: %1"
msgstr "Automatico: %1"
@@ -3337,6 +3611,16 @@ msgctxt "@title:menu menubar:toplevel"
msgid "&View"
msgstr "&Visualizza"
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ViewMenu.qml:37
+msgctxt "@action:inmenu menubar:view"
+msgid "&Camera position"
+msgstr "&Posizione fotocamera"
+
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ViewMenu.qml:52
+msgctxt "@action:inmenu menubar:view"
+msgid "&Build plate"
+msgstr "&Piano di stampa"
+
#: /home/ruben/Projects/Cura/resources/qml/Menus/NozzleMenu.qml:40
msgctxt "@title:menuitem %1 is the nozzle currently loaded in the printer"
msgid "Automatic: %1"
@@ -3349,14 +3633,14 @@ msgid_plural "Print Selected Models With:"
msgstr[0] "Stampa modello selezionato con:"
msgstr[1] "Stampa modelli selezionati con:"
-#: /home/ruben/Projects/Cura/resources/qml/Menus/ContextMenu.qml:83
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ContextMenu.qml:114
msgctxt "@title:window"
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/Menus/ContextMenu.qml:108
+#: /home/ruben/Projects/Cura/resources/qml/Menus/ContextMenu.qml:139
msgctxt "@label"
msgid "Number of Copies"
msgstr "Numero di copie"
@@ -3372,7 +3656,7 @@ msgid "No printer connected"
msgstr "Nessuna stampante collegata"
#: /home/ruben/Projects/Cura/resources/qml/PrintMonitor.qml:90
-#: /home/ruben/Projects/Cura/resources/qml/SidebarHeader.qml:138
+#: /home/ruben/Projects/Cura/resources/qml/SidebarHeader.qml:139
msgctxt "@label"
msgid "Extruder"
msgstr "Estrusore"
@@ -3420,7 +3704,7 @@ msgstr "La temperatura corrente del piano riscaldato."
#: /home/ruben/Projects/Cura/resources/qml/PrintMonitor.qml:423
msgctxt "@tooltip of temperature input"
msgid "The temperature to pre-heat the bed to."
-msgstr "La temperatura di preriscaldo del piano."
+msgstr "La temperatura di preriscaldamento del piano."
#: /home/ruben/Projects/Cura/resources/qml/PrintMonitor.qml:623
msgctxt "@button Cancel pre-heating"
@@ -3430,7 +3714,7 @@ msgstr "Annulla"
#: /home/ruben/Projects/Cura/resources/qml/PrintMonitor.qml:623
msgctxt "@button"
msgid "Pre-heat"
-msgstr "Pre-riscaldo"
+msgstr "Pre-riscaldamento"
#: /home/ruben/Projects/Cura/resources/qml/PrintMonitor.qml:650
msgctxt "@tooltip of pre-heat"
@@ -3482,254 +3766,294 @@ msgctxt "@label"
msgid "Estimated time left"
msgstr "Tempo residuo stimato"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:72
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:79
msgctxt "@action:inmenu"
msgid "Toggle Fu&ll Screen"
msgstr "Att&iva/disattiva schermo intero"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:79
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:86
msgctxt "@action:inmenu menubar:edit"
msgid "&Undo"
msgstr "&Annulla"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:89
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:96
msgctxt "@action:inmenu menubar:edit"
msgid "&Redo"
msgstr "Ri&peti"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:99
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:106
msgctxt "@action:inmenu menubar:file"
msgid "&Quit"
msgstr "E&sci"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:107
-msgctxt "@action:inmenu menubar:view"
-msgid "&Reset camera position"
-msgstr "&Ripristina la posizione della telecamera"
-
#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:114
+msgctxt "@action:inmenu menubar:view"
+msgid "&3D View"
+msgstr "&Visualizzazione 3D"
+
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:121
+msgctxt "@action:inmenu menubar:view"
+msgid "&Front View"
+msgstr "&Visualizzazione frontale"
+
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:128
+msgctxt "@action:inmenu menubar:view"
+msgid "&Top View"
+msgstr "&Visualizzazione superiore"
+
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:135
+msgctxt "@action:inmenu menubar:view"
+msgid "&Left Side View"
+msgstr "&Visualizzazione lato sinistro"
+
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:142
+msgctxt "@action:inmenu menubar:view"
+msgid "&Right Side View"
+msgstr "&Visualizzazione lato destro"
+
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:149
msgctxt "@action:inmenu"
msgid "Configure Cura..."
msgstr "Configura Cura..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:121
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:156
msgctxt "@action:inmenu menubar:printer"
msgid "&Add Printer..."
msgstr "A&ggiungi stampante..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:127
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:162
msgctxt "@action:inmenu menubar:printer"
msgid "Manage Pr&inters..."
msgstr "&Gestione stampanti..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:134
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:169
msgctxt "@action:inmenu"
msgid "Manage Materials..."
msgstr "Gestione materiali..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:142
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:177
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:150
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:185
msgctxt "@action:inmenu menubar:profile"
msgid "&Discard current changes"
msgstr "&Elimina le modifiche correnti"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:162
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:197
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:168
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:203
msgctxt "@action:inmenu menubar:profile"
msgid "Manage Profiles..."
msgstr "Gestione profili..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:175
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:210
msgctxt "@action:inmenu menubar:help"
msgid "Show Online &Documentation"
msgstr "Mostra documentazione &online"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:183
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:218
msgctxt "@action:inmenu menubar:help"
msgid "Report a &Bug"
msgstr "Se&gnala un errore"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:191
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:226
msgctxt "@action:inmenu menubar:help"
msgid "&About..."
msgstr "I&nformazioni..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:198
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:233
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:208
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:243
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:217
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:252
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:226
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:261
msgctxt "@action:inmenu"
msgid "Delete Model"
msgstr "Elimina modello"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:234
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:269
msgctxt "@action:inmenu"
msgid "Ce&nter Model on Platform"
msgstr "C&entra modello su piattaforma"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:240
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:275
msgctxt "@action:inmenu menubar:edit"
msgid "&Group Models"
msgstr "&Raggruppa modelli"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:250
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:295
msgctxt "@action:inmenu menubar:edit"
msgid "Ungroup Models"
msgstr "Separa modelli"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:260
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:305
msgctxt "@action:inmenu menubar:edit"
msgid "&Merge Models"
msgstr "&Unisci modelli"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:270
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:315
msgctxt "@action:inmenu"
msgid "&Multiply Model..."
msgstr "Mo<iplica modello"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:277
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:322
msgctxt "@action:inmenu menubar:edit"
msgid "&Select All Models"
msgstr "Sel&eziona tutti i modelli"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:287
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:332
msgctxt "@action:inmenu menubar:edit"
msgid "&Clear Build Plate"
-msgstr "&Cancellare piano di stampa"
+msgstr "&Pulire piano di stampa"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:297
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:342
msgctxt "@action:inmenu menubar:file"
msgid "Re&load All Models"
msgstr "R&icarica tutti i modelli"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:306
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:351
+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:358
msgctxt "@action:inmenu menubar:edit"
msgid "Arrange All Models"
msgstr "Sistema tutti i modelli"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:314
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:366
msgctxt "@action:inmenu menubar:edit"
msgid "Arrange Selection"
msgstr "Sistema selezione"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:321
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:373
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:328
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:380
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:335
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:387
msgctxt "@action:inmenu menubar:file"
msgid "&Open File(s)..."
msgstr "&Apri file..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:343
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:395
msgctxt "@action:inmenu menubar:file"
msgid "&New Project..."
msgstr "&Nuovo Progetto..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:350
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:402
msgctxt "@action:inmenu menubar:help"
msgid "Show Engine &Log..."
-msgstr "M&ostra log motore..."
+msgstr "M&ostra motore log..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:358
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:410
msgctxt "@action:inmenu menubar:help"
msgid "Show Configuration Folder"
msgstr "Mostra cartella di configurazione"
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:365
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:417
msgctxt "@action:menu"
msgid "Configure setting visibility..."
msgstr "Configura visibilità delle impostazioni..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:372
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:424
msgctxt "@action:menu"
msgid "Browse plugins..."
msgstr "Sfoglia plugin..."
-#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:379
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:431
msgctxt "@action:menu"
msgid "Installed plugins..."
msgstr "Plugin installati..."
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:28
+#: /home/ruben/Projects/Cura/resources/qml/Actions.qml:438
+msgctxt "@action:inmenu menubar:view"
+msgid "Expand/Collapse Sidebar"
+msgstr "Espandi/Riduci barra laterale"
+
+#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:26
msgctxt "@label:PrintjobStatus"
msgid "Please load a 3D model"
msgstr "Caricare un modello 3D"
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:34
+#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:36
msgctxt "@label:PrintjobStatus"
msgid "Ready to slice"
msgstr "Pronto per il sezionamento"
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:36
+#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:38
msgctxt "@label:PrintjobStatus"
msgid "Slicing..."
-msgstr "Sezionamento in corso..."
+msgstr "Slicing in corso..."
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:38
+#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:40
msgctxt "@label:PrintjobStatus %1 is target operation"
msgid "Ready to %1"
msgstr "Pronto a %1"
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:40
+#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:42
msgctxt "@label:PrintjobStatus"
msgid "Unable to Slice"
-msgstr "Sezionamento impossibile"
+msgstr "Slicing impossibile"
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:42
+#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:44
msgctxt "@label:PrintjobStatus"
msgid "Slicing unavailable"
msgstr "Sezionamento non disponibile"
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:162
+#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:171
+msgctxt "@info:tooltip"
+msgid "Slice current printjob"
+msgstr "Seziona processo di stampa corrente"
+
+#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:171
+msgctxt "@info:tooltip"
+msgid "Cancel slicing process"
+msgstr "Annulla processo di slicing"
+
+#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:183
msgctxt "@label:Printjob"
msgid "Prepare"
msgstr "Prepara"
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:162
+#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:183
msgctxt "@label:Printjob"
msgid "Cancel"
msgstr "Annulla"
-#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:302
+#: /home/ruben/Projects/Cura/resources/qml/SaveButton.qml:317
msgctxt "@info:tooltip"
msgid "Select the active output device"
-msgstr "Seleziona l'unità di uscita attiva"
+msgstr "Seleziona l'unità output attiva"
#: /home/ruben/Projects/Cura/resources/qml/OpenFilesIncludingProjectsDialog.qml:19
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:620
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:696
msgctxt "@title:window"
msgid "Open file(s)"
msgstr "Apri file"
@@ -3749,114 +4073,114 @@ msgctxt "@title:window"
msgid "Ultimaker Cura"
msgstr "Ultimaker Cura"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:81
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:102
msgctxt "@title:menu menubar:toplevel"
msgid "&File"
msgstr "&File"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:98
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:119
msgctxt "@action:inmenu menubar:file"
msgid "&Save Selection to File"
msgstr "&Salva selezione su file"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:107
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:128
msgctxt "@title:menu menubar:file"
msgid "Save &As..."
msgstr "Salva &come..."
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:118
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:139
msgctxt "@title:menu menubar:file"
-msgid "Save project"
-msgstr "Salva progetto"
+msgid "Save &Project..."
+msgstr "Salva &progetto..."
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:141
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:162
msgctxt "@title:menu menubar:toplevel"
msgid "&Edit"
msgstr "&Modifica"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:158
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:179
msgctxt "@title:menu"
msgid "&View"
msgstr "&Visualizza"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:163
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:184
msgctxt "@title:menu"
msgid "&Settings"
msgstr "&Impostazioni"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:165
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:186
msgctxt "@title:menu menubar:toplevel"
msgid "&Printer"
msgstr "S&tampante"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:175
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:187
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:196
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:208
msgctxt "@title:menu"
msgid "&Material"
msgstr "Ma&teriale"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:176
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:188
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:197
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:209
msgctxt "@title:menu"
msgid "&Profile"
msgstr "&Profilo"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:180
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:201
msgctxt "@action:inmenu"
msgid "Set as Active Extruder"
msgstr "Imposta come estrusore attivo"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:198
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:219
msgctxt "@title:menu menubar:toplevel"
msgid "E&xtensions"
msgstr "Es&tensioni"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:232
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:253
msgctxt "@title:menu menubar:toplevel"
msgid "P&lugins"
msgstr "&Plugin"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:240
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:261
msgctxt "@title:menu menubar:toplevel"
msgid "P&references"
msgstr "P&referenze"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:248
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:269
msgctxt "@title:menu menubar:toplevel"
msgid "&Help"
msgstr "&Help"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:330
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:351
msgctxt "@action:button"
msgid "Open File"
msgstr "Apri file"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:442
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:512
msgctxt "@title:tab"
msgid "Settings"
msgstr "Impostazioni"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:478
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:554
msgctxt "@title:window"
msgid "New project"
msgstr "Nuovo progetto"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:479
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:555
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:721
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:797
msgctxt "@window:title"
msgid "Install Plugin"
msgstr "Installa plugin"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:728
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:804
msgctxt "@title:window"
msgid "Open File(s)"
msgstr "Apri file"
-#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:731
+#: /home/ruben/Projects/Cura/resources/qml/Cura.qml:807
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. "
@@ -3881,97 +4205,82 @@ 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:264
-msgctxt "@action:button"
-msgid "Save"
-msgstr "Salva"
-
-#: /home/ruben/Projects/Cura/resources/qml/Topbar.qml:74
-msgctxt "@title:tab"
-msgid "Prepare"
-msgstr "Prepara"
-
-#: /home/ruben/Projects/Cura/resources/qml/Topbar.qml:100
-msgctxt "@title:tab"
-msgid "Monitor"
-msgstr "Controlla"
-
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:163
+#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:175
msgctxt "@label"
msgid "Layer Height"
msgstr "Altezza dello strato"
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:323
+#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:345
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:340
+#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:362
msgctxt "@label"
msgid "Print Speed"
msgstr "Velocità di stampa"
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:350
+#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:374
msgctxt "@label"
msgid "Slower"
msgstr "Più lenta"
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:361
+#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:385
msgctxt "@label"
msgid "Faster"
msgstr "Più veloce"
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:388
+#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:423
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:413
+#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:446
msgctxt "@label"
msgid "Infill"
msgstr "Riempimento"
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:633
+#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:668
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:645
+#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:680
msgctxt "@label"
msgid "Enable gradual"
msgstr "Consenti variazione graduale"
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:712
+#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:747
msgctxt "@label"
msgid "Generate Support"
msgstr "Generazione supporto"
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:746
+#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:781
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:764
+#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:799
msgctxt "@label"
msgid "Support Extruder"
msgstr "Estrusore del supporto"
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:816
+#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:851
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:839
+#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:874
msgctxt "@label"
msgid "Build Plate Adhesion"
msgstr "Adesione piano di stampa"
-#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:894
+#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:929
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:934
+#: /home/ruben/Projects/Cura/resources/qml/SidebarSimple.qml:969
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"
@@ -3988,17 +4297,22 @@ msgctxt "@title:window"
msgid "Open project file"
msgstr "Apri file progetto"
-#: /home/ruben/Projects/Cura/resources/qml/AskOpenAsProjectOrModelsDialog.qml:72
+#: /home/ruben/Projects/Cura/resources/qml/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
+msgctxt "@text:window"
+msgid "Remember my choice"
+msgstr "Ricorda la scelta"
+
+#: /home/ruben/Projects/Cura/resources/qml/AskOpenAsProjectOrModelsDialog.qml:122
msgctxt "@action:button"
msgid "Open as project"
msgstr "Apri come progetto"
-#: /home/ruben/Projects/Cura/resources/qml/AskOpenAsProjectOrModelsDialog.qml:122
+#: /home/ruben/Projects/Cura/resources/qml/AskOpenAsProjectOrModelsDialog.qml:131
msgctxt "@action:button"
msgid "Import models"
msgstr "Importa i modelli"
@@ -4006,23 +4320,38 @@ msgstr "Importa i modelli"
#: /home/ruben/Projects/Cura/resources/qml/EngineLog.qml:15
msgctxt "@title:window"
msgid "Engine Log"
-msgstr "Log motore"
+msgstr "Motore Log"
-#: /home/ruben/Projects/Cura/resources/qml/SidebarHeader.qml:242
+#: /home/ruben/Projects/Cura/resources/qml/SidebarHeader.qml:245
msgctxt "@label"
msgid "Material"
msgstr "Materiale"
-#: /home/ruben/Projects/Cura/resources/qml/SidebarHeader.qml:349
+#: /home/ruben/Projects/Cura/resources/qml/SidebarHeader.qml:352
msgctxt "@label"
-msgid "Check compatibility"
-msgstr "Controllo compatibilità"
+msgid "Check compatibility"
+msgstr "Controlla compatibilità"
-#: /home/ruben/Projects/Cura/resources/qml/SidebarHeader.qml:369
+#: /home/ruben/Projects/Cura/resources/qml/SidebarHeader.qml:372
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/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/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/ObjectsList.qml:247
+msgctxt "@action:button"
+msgid "Arrange current build plate"
+msgstr "Sistema il piano di stampa corrente"
+
#: MachineSettingsAction/plugin.json
msgctxt "description"
msgid "Provides a way to change machine settings (such as build volume, nozzle size, etc)"
@@ -4113,6 +4442,26 @@ msgctxt "name"
msgid "USB printing"
msgstr "Stampa USB"
+#: PrepareStage/plugin.json
+msgctxt "description"
+msgid "Provides a prepare stage in Cura."
+msgstr "Fornisce una fase di preparazione in Cura."
+
+#: PrepareStage/plugin.json
+msgctxt "name"
+msgid "Prepare Stage"
+msgstr "Fase di preparazione"
+
+#: CuraLiveScriptingPlugin/plugin.json
+msgctxt "description"
+msgid "Provides an edit window for direct script editing."
+msgstr "Fornisce una finestra di modifica per la modifica script diretta."
+
+#: CuraLiveScriptingPlugin/plugin.json
+msgctxt "name"
+msgid "Live scripting tool"
+msgstr "Strumento di script diretto"
+
#: RemovableDriveOutputDevice/plugin.json
msgctxt "description"
msgid "Provides removable drive hotplugging and writing support."
@@ -4133,6 +4482,16 @@ msgctxt "name"
msgid "UM3 Network Connection"
msgstr "Connessione di rete UM3"
+#: MonitorStage/plugin.json
+msgctxt "description"
+msgid "Provides a monitor stage in Cura."
+msgstr "Fornisce una fase di controllo in Cura."
+
+#: MonitorStage/plugin.json
+msgctxt "name"
+msgid "Monitor Stage"
+msgstr "Fase di controllo"
+
#: FirmwareUpdateChecker/plugin.json
msgctxt "description"
msgid "Checks for firmware updates."
@@ -4145,8 +4504,8 @@ msgstr "Controllo aggiornamento firmware"
#: CuraSolidWorksPlugin/plugin.json
msgctxt "description"
-msgid "Gives you the possibility to open certain files via SolidWorks itself. These are then converted and loaded into Cura"
-msgstr "Offre la possibilità di aprire alcuni file tramite SolidWorks stessa. Questi vengono quindi convertiti e caricati in Cura"
+msgid "Gives you the possibility to open certain files using SolidWorks itself. Conversion is done by this plugin and additional optimizations."
+msgstr "Offre la possibilità di aprire alcuni file utilizzando SolidWorks. La conversione viene effettuata da questo plugin e ottimizzazioni addizionali."
#: CuraSolidWorksPlugin/plugin.json
msgctxt "name"
@@ -4213,6 +4572,16 @@ msgctxt "name"
msgid "Legacy Cura Profile Reader"
msgstr "Lettore legacy profilo Cura"
+#: CuraBlenderPlugin/plugin.json
+msgctxt "description"
+msgid "Helps to open Blender files directly in Cura."
+msgstr "Aiuta ad aprire i file Blender direttamente in Cura."
+
+#: CuraBlenderPlugin/plugin.json
+msgctxt "name"
+msgid "Blender Integration (experimental)"
+msgstr "Integrazione Blender (sperimentale)"
+
#: GCodeProfileReader/plugin.json
msgctxt "description"
msgid "Provides support for importing profiles from g-code files."
@@ -4296,7 +4665,7 @@ msgstr "Lettore di immagine"
#: CuraEngineBackend/plugin.json
msgctxt "description"
msgid "Provides the link to the CuraEngine slicing backend."
-msgstr "Fornisce il collegamento al back-end di sezionamento CuraEngine."
+msgstr "Fornisce il collegamento al back-end di slicing di CuraEngine."
#: CuraEngineBackend/plugin.json
msgctxt "name"
@@ -4356,12 +4725,12 @@ msgstr "Visualizzazione compatta"
#: GCodeReader/plugin.json
msgctxt "description"
msgid "Allows loading and displaying G-code files."
-msgstr "Consente il caricamento e la visualizzazione dei file codice G."
+msgstr "Consente il caricamento e la visualizzazione dei file G-code."
#: GCodeReader/plugin.json
msgctxt "name"
msgid "G-code Reader"
-msgstr "Lettore codice G"
+msgstr "Lettore G-code"
#: CuraProfileWriter/plugin.json
msgctxt "description"
@@ -4373,6 +4742,16 @@ msgctxt "name"
msgid "Cura Profile Writer"
msgstr "Writer profilo Cura"
+#: CuraPrintProfileCreator/plugin.json
+msgctxt "description"
+msgid "Allows material manufacturers to create new material and quality profiles using a drop-in UI."
+msgstr "Consente ai produttori di materiali di creare nuovi profili materiale e di qualità utilizzando una UI drop-in."
+
+#: CuraPrintProfileCreator/plugin.json
+msgctxt "name"
+msgid "Print Profile Assistant"
+msgstr "Assistente profilo di stampa"
+
#: 3MFWriter/plugin.json
msgctxt "description"
msgid "Provides support for writing 3MF files."
@@ -4413,9 +4792,159 @@ msgctxt "name"
msgid "Cura Profile Reader"
msgstr "Lettore profilo Cura"
+#~ msgctxt "@label"
+#~ msgid "Unknown"
+#~ msgstr "Sconosciuto"
+
+#~ msgctxt "@info:status"
+#~ msgid "Errors appeared while opening your SolidWorks file! Please check, whether it is possible to open your file in SolidWorks itself without any problems as well!"
+#~ msgstr "Rilevati errori all'apertura del file SolidWorks! Controllare se è possibile aprire il file in SolidWorks senza che si verifichino problemi!"
+
+#~ msgctxt "@info:status"
+#~ msgid "Error while starting %s!"
+#~ msgstr "Errore durante l'avvio di %s!"
+
+#~ msgctxt "@item:inlistbox"
+#~ msgid "Simulation view"
+#~ msgstr "Vista simulazione"
+
+#~ msgctxt "@info"
+#~ msgid "Cura collects anonymised slicing statistics. You can disable this in the preferences."
+#~ msgstr "Cura acquisisce dati statistici elaborati in forma anonima. L'acquisizione può essere disabilitata nelle preferenze."
+
+#~ msgctxt "@action:button"
+#~ msgid "Dismiss"
+#~ msgstr "Ignora"
+
+#~ msgctxt "@menuitem"
+#~ msgid "Global"
+#~ msgstr "Globale"
+
+#~ msgctxt "@label crash message"
+#~ msgid ""
+#~ "
A fatal exception has occurred. Please send us this Crash Report to fix the problem
\n"
+#~ "
Please use the \"Send report\" button to post a bug report automatically to our servers
\n"
+#~ " "
+#~ msgstr ""
+#~ "
Si è verificata un'eccezione irreversibile. Si prega di inviarci questo crash report per risolvere il problema
\n"
+#~ "
Utilizzare il pulsante \"Invia report\" per inviare un report sui bug automaticamente ai nostri server
\n"
+#~ " "
+
+#~ msgctxt "@label Cura version"
+#~ msgid "Cura version: {version} "
+#~ msgstr "Versione Cura: {version} "
+
+#~ msgctxt "@label Platform"
+#~ msgid "Platform: {platform} "
+#~ msgstr "Piattaforma: {platform} "
+
+#~ msgctxt "@label Qt version"
+#~ msgid "Qt version: {qt} "
+#~ msgstr "Versione Qt: {qt} "
+
+#~ msgctxt "@label PyQt version"
+#~ msgid "PyQt version: {pyqt} "
+#~ msgstr "Versione PyQt: {pyqt} "
+
+#~ msgctxt "@label OpenGL"
+#~ msgid "OpenGL: {opengl} "
+#~ msgstr "OpenGL: {opengl} "
+
+#~ msgctxt "@title:groupbox"
+#~ msgid "Exception traceback"
+#~ msgstr "Analisi eccezione"
+
+#~ msgctxt "@label"
+#~ msgid "Material diameter"
+#~ msgstr "Diametro materiale"
+
+#~ msgctxt "@label"
+#~ msgid "Ultimaker 3"
+#~ msgstr "Ultimaker 3"
+
+#~ msgctxt "@label"
+#~ msgid "Ultimaker 3 Extended"
+#~ msgstr "Ultimaker3 Extended"
+
+#~ msgctxt "@title:window"
+#~ msgid "Cura SolidWorks Plugin Configuration"
+#~ msgstr "Configurazione plugin Cura SolidWorks"
+
+#~ msgctxt "@action:label"
+#~ msgid "Default quality of the exported STL:"
+#~ msgstr "Qualità predefinita STL esportato:"
+
+#~ msgctxt "@option:curaSolidworksStlQuality"
+#~ msgid "Always ask"
+#~ msgstr "Chiedi sempre"
+
+#~ msgctxt "@option:curaSolidworksStlQuality"
+#~ msgid "Always use Fine quality"
+#~ msgstr "Utilizza sempre la qualità Fine"
+
+#~ msgctxt "@option:curaSolidworksStlQuality"
+#~ msgid "Always use Coarse quality"
+#~ msgstr "Utilizza sempre la qualità Grossolana"
+
+#~ msgctxt "@title:window"
+#~ msgid "Import SolidWorks File as STL..."
+#~ msgstr "Importa file SolidWorks come STL..."
+
+#~ msgctxt "@info:tooltip"
+#~ msgid "Quality of the Exported STL"
+#~ msgstr "Qualità STL esportato"
+
+#~ msgctxt "@action:label"
+#~ msgid "Quality"
+#~ msgstr "Qualità"
+
+#~ msgctxt "@option:curaSolidworksStlQuality"
+#~ msgid "Coarse"
+#~ msgstr "Grossolana"
+
+#~ msgctxt "@option:curaSolidworksStlQuality"
+#~ msgid "Fine"
+#~ msgstr "Fine"
+
+#~ msgctxt "@"
+#~ msgid "No Profile Available"
+#~ msgstr "Nessun profilo disponibile"
+
+#~ 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"
+
+#~ msgctxt "@tooltip"
+#~ msgid "Time specification
"
+#~ msgstr "Indicazione del tempo
"
+
+#~ msgctxt "@action:inmenu menubar:view"
+#~ msgid "&Reset camera position"
+#~ msgstr "&Ripristina la posizione della telecamera"
+
+#~ msgctxt "@title:menu menubar:file"
+#~ msgid "Save project"
+#~ msgstr "Salva progetto"
+
+#~ msgctxt "@title:tab"
+#~ msgid "Prepare"
+#~ msgstr "Prepara"
+
+#~ msgctxt "@title:tab"
+#~ msgid "Monitor"
+#~ msgstr "Controlla"
+
+#~ msgctxt "@label"
+#~ msgid "Check compatibility"
+#~ msgstr "Controllo compatibilità"
+
+#~ msgctxt "description"
+#~ msgid "Gives you the possibility to open certain files via SolidWorks itself. These are then converted and loaded into Cura"
+#~ msgstr "Offre la possibilità di aprire alcuni file tramite SolidWorks stessa. Questi vengono quindi convertiti e caricati in Cura"
+
#~ msgctxt "@label:status"
#~ msgid "Blocked"
-#~ msgstr "Ostacolato"
+#~ msgstr "Bloccato"
#~ msgctxt "@label:status"
#~ msgid "Can't start print"
@@ -4433,13 +4962,9 @@ msgstr "Lettore profilo Cura"
#~ msgid "To ensure that your {machine_name} is equipped with the latest features it is recommended to update the firmware regularly. This can be done on the {machine_name} (when connected to the network) or via USB."
#~ msgstr "Per verificare che la vostra {machine_name} sia dotata delle funzionalità più recenti, si consiglia di aggiornare periodicamente il firmware. Questo può essere fatto sulla {machine_name} (quando connessa alla rete) o via USB."
-msgctxt "@item:inlistbox"
-msgid "Layer view"
-msgstr "Visualizzazione strato"
-
-msgctxt "@info:title"
-msgid "Layer View"
-msgstr "Visualizzazione strato"
+#~ msgctxt "@info:title"
+#~ msgid "Layer View"
+#~ msgstr "Visualizzazione layer"
#~ msgctxt "@menuitem"
#~ msgid "Browse plugins"
@@ -4541,9 +5066,9 @@ msgstr "Visualizzazione strato"
#~ msgid "Provides the Layer view."
#~ msgstr "Fornisce la visualizzazione degli strati."
-msgctxt "name"
-msgid "Layer View"
-msgstr "Visualizzazione strato"
+#~ msgctxt "name"
+#~ msgid "Layer View"
+#~ msgstr "Visualizzazione layer"
#~ msgctxt "@item:inlistbox"
#~ msgid "X-Ray"
@@ -4674,7 +5199,7 @@ msgstr "Visualizzazione strato"
#~ msgctxt "@label"
#~ msgid "Hotend"
-#~ msgstr "Estremità calda"
+#~ msgstr "Hotend"
#~ msgctxt "@action:button"
#~ msgid "View Mode"
@@ -4810,7 +5335,7 @@ msgstr "Visualizzazione strato"
#~ msgctxt "@label"
#~ msgid "The print cores and/or materials on your printer differ from those within your current project. For the best result, always slice for the print cores and materials that are inserted in your printer."
-#~ msgstr "I PrintCore e/o i materiali della stampante sono diversi da quelli del progetto corrente. Per ottenere i migliori risultati, sezionare sempre per i PrintCore e i materiali inseriti nella stampante utilizzata."
+#~ msgstr "I PrintCore e/o i materiali della stampante sono diversi da quelli del progetto corrente. Per risultati ottimali, sezionare sempre i PrintCore e i materiali inseriti nella stampante utilizzata."
#~ msgctxt "@label"
#~ msgid "Post Processing"
@@ -4864,13 +5389,13 @@ msgstr "Visualizzazione strato"
#~ msgid "Provides support for importing profiles from g-code files."
#~ msgstr "Fornisce supporto per l'importazione di profili da file G-Code."
-msgctxt "@label"
-msgid "Layer View"
-msgstr "Visualizzazione strato"
+#~ msgctxt "@label"
+#~ msgid "Layer View"
+#~ msgstr "Visualizzazione layer"
#~ msgctxt "@info:whatsthis"
#~ msgid "Provides the Layer view."
-#~ msgstr "Fornisce la visualizzazione degli strati."
+#~ msgstr "Fornisce la visualizzazione dei layer."
#~ msgctxt "@label"
#~ msgid "Version Upgrade 2.5 to 2.6"
@@ -4910,7 +5435,7 @@ msgstr "Visualizzazione strato"
#~ msgctxt "@info:whatsthis"
#~ msgid "Provides the link to the CuraEngine slicing backend."
-#~ msgstr "Fornisce il collegamento al back-end di sezionamento CuraEngine."
+#~ msgstr "Fornisce il collegamento al back-end di slicing di CuraEngine."
#~ msgctxt "@label"
#~ msgid "Per Model Settings Tool"
@@ -4938,11 +5463,11 @@ msgstr "Visualizzazione strato"
#~ msgctxt "@label"
#~ msgid "G-code Reader"
-#~ msgstr "Lettore codice G"
+#~ msgstr "Lettore G-code"
#~ msgctxt "@info:whatsthis"
#~ msgid "Allows loading and displaying G-code files."
-#~ msgstr "Consente il caricamento e la visualizzazione dei file codice G."
+#~ msgstr "Consente il caricamento e la visualizzazione dei file G-code."
#~ msgctxt "@label"
#~ msgid "Cura Profile Writer"
@@ -5211,7 +5736,7 @@ msgstr "Visualizzazione strato"
#~ msgctxt "@option:check"
#~ msgid "Only display top layer(s) in layer view"
-#~ msgstr "In visualizzazione strato, visualizza solo lo/gli strato/i superiore/i"
+#~ msgstr "In visualizzazione layer, visualizza solo il/i layer(s) superiore/i"
#~ msgctxt "@label"
#~ msgid "Opening files"
diff --git a/resources/i18n/it_IT/fdmextruder.def.json.po b/resources/i18n/it_IT/fdmextruder.def.json.po
index ec3c8051cf..f34ebd04ff 100644
--- a/resources/i18n/it_IT/fdmextruder.def.json.po
+++ b/resources/i18n/it_IT/fdmextruder.def.json.po
@@ -2,12 +2,12 @@
# Copyright (C) 2017 Ultimaker
# This file is distributed under the same license as the Cura package.
# Ruben Dulek , 2017.
-#
+#
msgid ""
msgstr ""
"Project-Id-Version: Cura 3.0\n"
-"Report-Msgid-Bugs-To: http://github.com/ultimaker/uranium\n"
-"POT-Creation-Date: 2017-11-21 16:58+0000\n"
+"Report-Msgid-Bugs-To: r.dulek@ultimaker.com\n"
+"POT-Creation-Date: 2017-08-02 16:53+0000\n"
"PO-Revision-Date: 2017-11-30 13:05+0100\n"
"Last-Translator: Bothof \n"
"Language-Team: Italian\n"
diff --git a/resources/i18n/it_IT/fdmprinter.def.json.po b/resources/i18n/it_IT/fdmprinter.def.json.po
index 5fb7743130..e5f440e2b2 100644
--- a/resources/i18n/it_IT/fdmprinter.def.json.po
+++ b/resources/i18n/it_IT/fdmprinter.def.json.po
@@ -1,15 +1,15 @@
-# Cura JSON setting files
-# Copyright (C) 2017 Ultimaker
+# Cura
+# Copyright (C) 2018 Ultimaker
# This file is distributed under the same license as the Cura package.
-# Ruben Dulek , 2017.
-#
+# Ruben Dulek , 2018.
+#
msgid ""
msgstr ""
-"Project-Id-Version: Cura 3.0\n"
-"Report-Msgid-Bugs-To: http://github.com/ultimaker/uranium\n"
-"POT-Creation-Date: 2017-11-21 16:58+0000\n"
+"Project-Id-Version: Cura 3.2\n"
+"Report-Msgid-Bugs-To: r.dulek@ultimaker.com\n"
+"POT-Creation-Date: 2018-01-29 09:48+0000\n"
"PO-Revision-Date: 2017-11-30 13:05+0100\n"
-"Last-Translator: Bothof \n"
+"Last-Translator: Crea-3D \n"
"Language-Team: Italian\n"
"Language: it_IT\n"
"MIME-Version: 1.0\n"
@@ -49,26 +49,26 @@ msgstr "Sceglie se mostrare le diverse varianti di questa macchina, descritte in
#: fdmprinter.def.json
msgctxt "machine_start_gcode label"
msgid "Start GCode"
-msgstr "Codice G avvio"
+msgstr "Avvio GCode"
#: fdmprinter.def.json
msgctxt "machine_start_gcode description"
msgid ""
"Gcode commands to be executed at the very start - separated by \n"
"."
-msgstr "I comandi codice G da eseguire all’avvio, separati da \n."
+msgstr "I comandi del Gcode da eseguire all’avvio, separati da \n."
#: fdmprinter.def.json
msgctxt "machine_end_gcode label"
msgid "End GCode"
-msgstr "Codice G fine"
+msgstr "Fine GCode"
#: fdmprinter.def.json
msgctxt "machine_end_gcode description"
msgid ""
"Gcode commands to be executed at the very end - separated by \n"
"."
-msgstr "I comandi codice G da eseguire alla fine, separati da \n."
+msgstr "I comandi del Gcode da eseguire alla fine, separati da \n."
#: fdmprinter.def.json
msgctxt "material_guid label"
@@ -88,7 +88,7 @@ msgstr "Attendi il riscaldamento del piano di stampa"
#: fdmprinter.def.json
msgctxt "material_bed_temp_wait description"
msgid "Whether to insert a command to wait until the build plate temperature is reached at the start."
-msgstr "Sceglie se inserire un comando per attendere finché la temperatura del piano di stampa non viene raggiunta all’avvio."
+msgstr "Scegli se inserire un comando per attendere finché la temperatura del piano di stampa non viene raggiunta all’avvio."
#: fdmprinter.def.json
msgctxt "material_print_temp_wait label"
@@ -98,7 +98,7 @@ msgstr "Attendi il riscaldamento dell’ugello"
#: fdmprinter.def.json
msgctxt "material_print_temp_wait description"
msgid "Whether to wait until the nozzle temperature is reached at the start."
-msgstr "Sceglie se attendere finché la temperatura dell’ugello non viene raggiunta all’avvio."
+msgstr "Scegli se attendere finché la temperatura dell’ugello non viene raggiunta all’avvio."
#: fdmprinter.def.json
msgctxt "material_print_temp_prepend label"
@@ -108,7 +108,7 @@ msgstr "Includi le temperature del materiale"
#: fdmprinter.def.json
msgctxt "material_print_temp_prepend description"
msgid "Whether to include nozzle temperature commands at the start of the gcode. When the start_gcode already contains nozzle temperature commands Cura frontend will automatically disable this setting."
-msgstr "Sceglie se includere comandi temperatura ugello all’avvio del codice G. Quando start_gcode contiene già comandi temperatura ugello la parte anteriore di Cura disabilita automaticamente questa impostazione."
+msgstr "Scegli se includere comandi temperatura ugello all’avvio del Gcode. Quando start_gcode contiene già comandi temperatura ugello, il frontend di Cura disabilita automaticamente questa impostazione."
#: fdmprinter.def.json
msgctxt "material_bed_temp_prepend label"
@@ -118,7 +118,7 @@ msgstr "Includi temperatura piano di stampa"
#: fdmprinter.def.json
msgctxt "material_bed_temp_prepend description"
msgid "Whether to include build plate temperature commands at the start of the gcode. When the start_gcode already contains build plate temperature commands Cura frontend will automatically disable this setting."
-msgstr "Sceglie se includere comandi temperatura piano di stampa all’avvio del codice G. Quando start_gcode contiene già comandi temperatura piano di stampa la parte anteriore di Cura disabilita automaticamente questa impostazione."
+msgstr "Scegli se includere comandi temperatura piano di stampa all’avvio del gcode. Quando start_gcode contiene già comandi temperatura piano di stampa il frontend di Cura disabilita automaticamente questa impostazione."
#: fdmprinter.def.json
msgctxt "machine_width label"
@@ -183,7 +183,7 @@ msgstr "Indica se la macchina ha un piano di stampa riscaldato."
#: fdmprinter.def.json
msgctxt "machine_center_is_zero label"
msgid "Is Center Origin"
-msgstr "Origine del centro"
+msgstr "Origine al centro"
#: fdmprinter.def.json
msgctxt "machine_center_is_zero description"
@@ -198,7 +198,7 @@ msgstr "Numero di estrusori"
#: fdmprinter.def.json
msgctxt "machine_extruder_count description"
msgid "Number of extruder trains. An extruder train is the combination of a feeder, bowden tube, and nozzle."
-msgstr "Il numero di treni di estrusori. Un treno di estrusori è la combinazione di un alimentatore, un tubo bowden e un ugello."
+msgstr "Il numero dei blocchi di estrusori. Un blocco di estrusori è la combinazione di un alimentatore, un tubo bowden e un ugello."
#: fdmprinter.def.json
msgctxt "machine_nozzle_tip_outer_diameter label"
@@ -218,7 +218,7 @@ msgstr "Lunghezza ugello"
#: fdmprinter.def.json
msgctxt "machine_nozzle_head_distance description"
msgid "The height difference between the tip of the nozzle and the lowest part of the print head."
-msgstr "La differenza di altezza tra la punta dell’ugello e la parte inferiore della testina di stampa."
+msgstr "La differenza di altezza tra la punta dell’ugello e la parte inferiore della testa di stampa."
#: fdmprinter.def.json
msgctxt "machine_nozzle_expansion_angle label"
@@ -293,12 +293,12 @@ msgstr "Il tempo minimo in cui un estrusore deve essere inattivo prima che l’u
#: fdmprinter.def.json
msgctxt "machine_gcode_flavor label"
msgid "Gcode flavour"
-msgstr "Tipo di codice G"
+msgstr "Tipo di Gcode"
#: fdmprinter.def.json
msgctxt "machine_gcode_flavor description"
msgid "The type of gcode to be generated."
-msgstr "Il tipo di codice G da generare."
+msgstr "Il tipo di gcode da generare."
#: fdmprinter.def.json
msgctxt "machine_gcode_flavor option RepRap (Marlin/Sprinter)"
@@ -345,6 +345,16 @@ msgctxt "machine_gcode_flavor option Repetier"
msgid "Repetier"
msgstr "Repetier"
+#: fdmprinter.def.json
+msgctxt "machine_firmware_retract label"
+msgid "Firmware Retraction"
+msgstr "Retrazione firmware"
+
+#: fdmprinter.def.json
+msgctxt "machine_firmware_retract description"
+msgid "Whether to use firmware retract commands (G10/G11) instead of using the E property in G1 commands to retract the material."
+msgstr "Specifica se usare comandi di retrazione firmware (G10/G11) anziché utilizzare la proprietà E nei comandi G1 per retrarre il materiale."
+
#: fdmprinter.def.json
msgctxt "machine_disallowed_areas label"
msgid "Disallowed areas"
@@ -353,7 +363,7 @@ msgstr "Aree non consentite"
#: fdmprinter.def.json
msgctxt "machine_disallowed_areas description"
msgid "A list of polygons with areas the print head is not allowed to enter."
-msgstr "Un elenco di poligoni con aree alle quali la testina di stampa non può accedere."
+msgstr "Un elenco di poligoni con aree alle quali la testa di stampa non può accedere."
#: fdmprinter.def.json
msgctxt "nozzle_disallowed_areas label"
@@ -368,22 +378,22 @@ 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"
-msgstr "Poligono testina macchina"
+msgstr "Poligono testa macchina"
#: fdmprinter.def.json
msgctxt "machine_head_polygon description"
msgid "A 2D silhouette of the print head (fan caps excluded)."
-msgstr "Una silhouette 2D della testina di stampa (cappucci ventola esclusi)."
+msgstr "Una silhouette 2D della testa di stampa (coperture ventola escluse)."
#: fdmprinter.def.json
msgctxt "machine_head_with_fans_polygon label"
msgid "Machine head & Fan polygon"
-msgstr "Poligono testina macchina e ventola"
+msgstr "Poligono testa macchina e ventola"
#: fdmprinter.def.json
msgctxt "machine_head_with_fans_polygon description"
msgid "A 2D silhouette of the print head (fan caps included)."
-msgstr "Una silhouette 2D della testina di stampa (cappucci ventola inclusi)."
+msgstr "Una silhouette 2D della testa di stampa (coperture ventola incluse)."
#: fdmprinter.def.json
msgctxt "gantry_height label"
@@ -403,7 +413,7 @@ msgstr "ID ugello"
#: fdmprinter.def.json
msgctxt "machine_nozzle_id description"
msgid "The nozzle ID for an extruder train, such as \"AA 0.4\" and \"BB 0.8\"."
-msgstr "ID ugello per un treno estrusore, come \"AA 0.4\" e \"BB 0.8\"."
+msgstr "ID ugello per un blocco estrusore, come \"AA 0.4\" e \"BB 0.8\"."
#: fdmprinter.def.json
msgctxt "machine_nozzle_size label"
@@ -583,52 +593,27 @@ msgstr "Qualità"
#: fdmprinter.def.json
msgctxt "resolution description"
msgid "All settings that influence the resolution of the print. These settings have a large impact on the quality (and print time)"
-msgstr "Indica tutte le impostazioni che influiscono sulla risoluzione della stampa. Queste impostazioni hanno un elevato impatto sulla qualità (e il tempo di stampa)"
+msgstr "Indica tutte le impostazioni che influiscono sulla risoluzione della stampa. Queste impostazioni hanno un elevato impatto sulla qualità (e sul tempo di stampa)"
#: fdmprinter.def.json
msgctxt "layer_height label"
msgid "Layer Height"
-msgstr "Altezza dello strato"
+msgstr "Altezza del layer"
#: fdmprinter.def.json
msgctxt "layer_height description"
msgid "The height of each layer in mm. Higher values produce faster prints in lower resolution, lower values produce slower prints in higher resolution."
-msgstr "Indica l’altezza di ciascuno strato in mm. Valori più elevati generano stampe più rapide con risoluzione inferiore, valori più bassi generano stampe più lente con risoluzione superiore."
+msgstr "Indica l’altezza di ciascun layer in mm. Valori più elevati generano stampe più rapide con risoluzione inferiore, valori più bassi generano stampe più lente con risoluzione superiore."
#: fdmprinter.def.json
msgctxt "layer_height_0 label"
msgid "Initial Layer Height"
-msgstr "Altezza dello strato iniziale"
+msgstr "Altezza iniziale del layer"
#: fdmprinter.def.json
msgctxt "layer_height_0 description"
msgid "The height of the initial layer in mm. A thicker initial layer makes adhesion to the build plate easier."
-msgstr "Indica l’altezza dello strato iniziale in mm. Uno strato iniziale più spesso facilita l’adesione al piano di stampa."
-
-#: fdmprinter.def.json
-msgctxt "slicing_tolerance label"
-msgid "Slicing Tolerance"
-msgstr "Tolleranza di sezionamento"
-
-#: fdmprinter.def.json
-msgctxt "slicing_tolerance description"
-msgid "How to slice layers with diagonal surfaces. The areas of a layer can be generated based on where the middle of the layer intersects the surface (Middle). Alternatively each layer can have the areas which fall inside of the volume throughout the height of the layer (Exclusive) or a layer has the areas which fall inside anywhere within the layer (Inclusive). Exclusive retains the most details, Inclusive makes for the best fit and Middle takes the least time to process."
-msgstr "Modalità di sezionamento di strati con superfici diagonali. Le aree di uno strato possono essere generate in base al punto in cui la parte intermedia dello strato interseca la superficie (intermedia). In alternativa le aree di ciascuno strato possono ricadere all'interno del volume per tutta l'altezza dello strato (Esclusiva) ovvero possono cadere in qualsiasi punto all'interno dello strato (Inclusiva). La tolleranza esclusiva mantiene il maggior numero di dettagli, la tolleranza inclusiva è la più idonea, mentre la tolleranza intermedia richiede il minor tempo di processo."
-
-#: fdmprinter.def.json
-msgctxt "slicing_tolerance option middle"
-msgid "Middle"
-msgstr "Intermedia"
-
-#: fdmprinter.def.json
-msgctxt "slicing_tolerance option exclusive"
-msgid "Exclusive"
-msgstr "Esclusiva"
-
-#: fdmprinter.def.json
-msgctxt "slicing_tolerance option inclusive"
-msgid "Inclusive"
-msgstr "Inclusiva"
+msgstr "Indica l’altezza del layer iniziale in mm. Un layer iniziale più spesso facilita l’adesione al piano di stampa."
#: fdmprinter.def.json
msgctxt "line_width label"
@@ -670,16 +655,6 @@ msgctxt "wall_line_width_x description"
msgid "Width of a single wall line for all wall lines except the outermost one."
msgstr "Indica la larghezza di una singola linea della parete per tutte le linee della parete tranne quella più esterna."
-#: fdmprinter.def.json
-msgctxt "roofing_line_width label"
-msgid "Top Surface Skin Line Width"
-msgstr "Larghezza linea rivestimento superficie superiore"
-
-#: fdmprinter.def.json
-msgctxt "roofing_line_width description"
-msgid "Width of a single line of the areas at the top of the print."
-msgstr "Larghezza di un singola linea delle aree nella parte superiore della stampa"
-
#: fdmprinter.def.json
msgctxt "skin_line_width label"
msgid "Top/Bottom Line Width"
@@ -758,17 +733,17 @@ msgstr "Larghezza della linea della torre di innesco"
#: fdmprinter.def.json
msgctxt "prime_tower_line_width description"
msgid "Width of a single prime tower line."
-msgstr "Indica la larghezza di una singola linea della torre di innesco."
+msgstr "Indica la larghezza di una singola linea della prime tower."
#: fdmprinter.def.json
msgctxt "initial_layer_line_width_factor label"
msgid "Initial Layer Line Width"
-msgstr "Larghezza linea strato iniziale"
+msgstr "Larghezza linea layer iniziale"
#: fdmprinter.def.json
msgctxt "initial_layer_line_width_factor description"
msgid "Multiplier of the line width on the first layer. Increasing this could improve bed adhesion."
-msgstr "Moltiplicatore della larghezza della linea del primo strato Il suo aumento potrebbe migliorare l'adesione al piano"
+msgstr "Moltiplicatore della larghezza della linea del primo layer. Il suo aumento potrebbe migliorare l'adesione al piano"
#: fdmprinter.def.json
msgctxt "shell label"
@@ -788,7 +763,7 @@ msgstr "Estrusore pareti"
#: fdmprinter.def.json
msgctxt "wall_extruder_nr description"
msgid "The extruder train used for printing the walls. This is used in multi-extrusion."
-msgstr "Treno estrusore utilizzato per stampare le pareti. Si utilizza nell'estrusione multipla."
+msgstr "Blocco estrusore utilizzato per stampare le pareti. Si utilizza nell'estrusione multipla."
#: fdmprinter.def.json
msgctxt "wall_0_extruder_nr label"
@@ -798,7 +773,7 @@ msgstr "Estrusore parete esterna"
#: fdmprinter.def.json
msgctxt "wall_0_extruder_nr description"
msgid "The extruder train used for printing the outer wall. This is used in multi-extrusion."
-msgstr "Treno estrusore utilizzato per stampare la parete esterna. Si utilizza nell'estrusione multipla."
+msgstr "Blocco estrusore utilizzato per stampare la parete esterna. Si utilizza nell'estrusione multipla."
#: fdmprinter.def.json
msgctxt "wall_x_extruder_nr label"
@@ -808,7 +783,7 @@ msgstr "Estrusore parete interna"
#: fdmprinter.def.json
msgctxt "wall_x_extruder_nr description"
msgid "The extruder train used for printing the inner walls. This is used in multi-extrusion."
-msgstr "Treno estrusore utilizzato per stampare le pareti interne. Si utilizza nell'estrusione multipla."
+msgstr "Blocco estrusore utilizzato per stampare le pareti interne. Si utilizza nell'estrusione multipla."
#: fdmprinter.def.json
msgctxt "wall_thickness label"
@@ -828,7 +803,7 @@ msgstr "Numero delle linee perimetrali"
#: fdmprinter.def.json
msgctxt "wall_line_count description"
msgid "The number of walls. When calculated by the wall thickness, this value is rounded to a whole number."
-msgstr "Indica il numero delle pareti. Quando calcolato mediante lo spessore della parete, il valore viene arrotondato a numero intero."
+msgstr "Indica il numero delle pareti. Se calcolato mediante lo spessore della parete, il valore viene arrotondato a numero intero."
#: fdmprinter.def.json
msgctxt "wall_0_wipe_dist label"
@@ -848,52 +823,17 @@ msgstr "Estrusore rivestimento superficie superiore"
#: fdmprinter.def.json
msgctxt "roofing_extruder_nr description"
msgid "The extruder train used for printing the top most skin. This is used in multi-extrusion."
-msgstr "Treno estrusore utilizzato per stampare il rivestimento più in alto. Si utilizza nell'estrusione multipla."
+msgstr "Blocco estrusore utilizzato per stampare il rivestimento più in alto. Si utilizza nell'estrusione multipla."
#: fdmprinter.def.json
msgctxt "roofing_layer_count label"
msgid "Top Surface Skin Layers"
-msgstr "Strati di rivestimento superficie superiore"
+msgstr "Layer di rivestimento superficie superiore"
#: fdmprinter.def.json
msgctxt "roofing_layer_count description"
msgid "The number of top most skin layers. Usually only one top most layer is sufficient to generate higher quality top surfaces."
-msgstr "Numero degli strati di rivestimento superiori. Solitamente è sufficiente un unico strato di sommità per ottenere superfici superiori di qualità elevata."
-
-#: fdmprinter.def.json
-msgctxt "roofing_pattern label"
-msgid "Top Surface Skin Pattern"
-msgstr "Configurazione del rivestimento superficie superiore"
-
-#: fdmprinter.def.json
-msgctxt "roofing_pattern description"
-msgid "The pattern of the top most layers."
-msgstr "Configurazione degli strati superiori."
-
-#: fdmprinter.def.json
-msgctxt "roofing_pattern option lines"
-msgid "Lines"
-msgstr "Linee"
-
-#: fdmprinter.def.json
-msgctxt "roofing_pattern option concentric"
-msgid "Concentric"
-msgstr "Concentrica"
-
-#: fdmprinter.def.json
-msgctxt "roofing_pattern option zigzag"
-msgid "Zig Zag"
-msgstr "Zig Zag"
-
-#: fdmprinter.def.json
-msgctxt "roofing_angles label"
-msgid "Top Surface Skin Line Directions"
-msgstr "Direzioni linea rivestimento superficie superiore"
-
-#: fdmprinter.def.json
-msgctxt "roofing_angles description"
-msgid "A list of integer line directions to use when the top surface skin layers use the lines or zig zag pattern. 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 traditional default angles (45 and 135 degrees)."
-msgstr "Un elenco di direzioni linee intere da usare quando gli strati rivestimento superficie superiore utilizzano le linee o la configurazione zig zag. Gli elementi dall’elenco sono utilizzati in sequenza con il progredire degli strati e, al raggiungimento della fine dell’elenco, la sequenza ricomincia dall’inizio. Le voci elencate sono separate da virgole e l’intero elenco è racchiuso tra parentesi quadre. L’elenco predefinito è vuoto, vale a dire che utilizza i valori angolari predefiniti (45 e 135 gradi)."
+msgstr "Numero dei layers di rivestimento superiori. Solitamente è sufficiente un unico layer di sommità per ottenere superfici superiori di qualità elevata."
#: fdmprinter.def.json
msgctxt "top_bottom_extruder_nr label"
@@ -903,67 +843,67 @@ msgstr "Estrusore superiore/inferiore"
#: fdmprinter.def.json
msgctxt "top_bottom_extruder_nr description"
msgid "The extruder train used for printing the top and bottom skin. This is used in multi-extrusion."
-msgstr "Treno estrusore utilizzato per stampare il rivestimento superiore e quello inferiore. Si utilizza nell'estrusione multipla."
+msgstr "Blocco estrusore utilizzato per stampare il rivestimento superiore e quello inferiore. Si utilizza nell'estrusione multipla."
#: fdmprinter.def.json
msgctxt "top_bottom_thickness label"
msgid "Top/Bottom Thickness"
-msgstr "Spessore dello strato superiore/inferiore"
+msgstr "Spessore del layer superiore/inferiore"
#: fdmprinter.def.json
msgctxt "top_bottom_thickness description"
msgid "The thickness of the top/bottom layers in the print. This value divided by the layer height defines the number of top/bottom layers."
-msgstr "Indica lo spessore degli strati superiore/inferiore nella stampa. Questo valore diviso per la l’altezza dello strato definisce il numero degli strati superiori/inferiori."
+msgstr "Indica lo spessore dei layers superiore/inferiore nella stampa. Questo valore diviso per la l’altezza del layer definisce il numero dei layers superiori/inferiori."
#: fdmprinter.def.json
msgctxt "top_thickness label"
msgid "Top Thickness"
-msgstr "Spessore dello strato superiore"
+msgstr "Spessore del layer superiore"
#: fdmprinter.def.json
msgctxt "top_thickness description"
msgid "The thickness of the top layers in the print. This value divided by the layer height defines the number of top layers."
-msgstr "Indica lo spessore degli strati superiori nella stampa. Questo valore diviso per la l’altezza dello strato definisce il numero degli strati superiori."
+msgstr "Indica lo spessore dei layers superiori nella stampa. Questo valore diviso per la l’altezza del layer definisce il numero dei layers superiori."
#: fdmprinter.def.json
msgctxt "top_layers label"
msgid "Top Layers"
-msgstr "Strati superiori"
+msgstr "Layers superiori"
#: fdmprinter.def.json
msgctxt "top_layers description"
msgid "The number of top layers. When calculated by the top thickness, this value is rounded to a whole number."
-msgstr "Indica il numero degli strati superiori. Quando calcolato mediante lo spessore dello strato superiore, il valore viene arrotondato a numero intero."
+msgstr "Indica il numero dei layers superiori. Se calcolato mediante lo spessore del layer superiore, il valore viene arrotondato a numero intero."
#: fdmprinter.def.json
msgctxt "bottom_thickness label"
msgid "Bottom Thickness"
-msgstr "Spessore degli strati inferiori"
+msgstr "Spessore dei layers inferiori"
#: fdmprinter.def.json
msgctxt "bottom_thickness description"
msgid "The thickness of the bottom layers in the print. This value divided by the layer height defines the number of bottom layers."
-msgstr "Indica lo spessore degli strati inferiori nella stampa. Questo valore diviso per la l’altezza dello strato definisce il numero degli strati inferiori."
+msgstr "Indica lo spessore dei layers inferiori nella stampa. Questo valore diviso per la l’altezza del layer definisce il numero dei layers inferiori."
#: fdmprinter.def.json
msgctxt "bottom_layers label"
msgid "Bottom Layers"
-msgstr "Strati inferiori"
+msgstr "Layers inferiori"
#: fdmprinter.def.json
msgctxt "bottom_layers description"
msgid "The number of bottom layers. When calculated by the bottom thickness, this value is rounded to a whole number."
-msgstr "Indica il numero degli strati inferiori. Quando calcolato mediante lo spessore dello strato inferiore, il valore viene arrotondato a numero intero."
+msgstr "Indica il numero dei layers inferiori. Quando calcolato mediante lo spessore del layer inferiore, il valore viene arrotondato a numero intero."
#: fdmprinter.def.json
msgctxt "top_bottom_pattern label"
msgid "Top/Bottom Pattern"
-msgstr "Configurazione dello strato superiore/inferiore"
+msgstr "Configurazione del layer superiore/inferiore"
#: fdmprinter.def.json
msgctxt "top_bottom_pattern description"
msgid "The pattern of the top/bottom layers."
-msgstr "Indica la configurazione degli strati superiori/inferiori."
+msgstr "Indica la configurazione dei layers superiori/inferiori."
#: fdmprinter.def.json
msgctxt "top_bottom_pattern option lines"
@@ -983,12 +923,12 @@ msgstr "Zig Zag"
#: fdmprinter.def.json
msgctxt "top_bottom_pattern_0 label"
msgid "Bottom Pattern Initial Layer"
-msgstr "Strato iniziale configurazione inferiore"
+msgstr "Layer iniziale configurazione inferiore"
#: fdmprinter.def.json
msgctxt "top_bottom_pattern_0 description"
msgid "The pattern on the bottom of the print on the first layer."
-msgstr "La configurazione al fondo della stampa sul primo strato."
+msgstr "La configurazione al fondo della stampa sul primo layer."
#: fdmprinter.def.json
msgctxt "top_bottom_pattern_0 option lines"
@@ -1013,7 +953,7 @@ msgstr "Direzioni delle linee superiori/inferiori"
#: fdmprinter.def.json
msgctxt "skin_angles description"
msgid "A list of integer line directions to use when the top/bottom layers use the lines or zig zag pattern. 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 traditional default angles (45 and 135 degrees)."
-msgstr "Un elenco di direzioni linee intere da usare quando gli strati superiori/inferiori utilizzano le linee o la configurazione zig zag. Gli elementi dall’elenco sono utilizzati in sequenza con il progredire degli strati e, al raggiungimento della fine dell’elenco, la sequenza ricomincia dall’inizio. Le voci elencate sono separate da virgole e l’intero elenco è racchiuso tra parentesi quadre. L’elenco predefinito è vuoto, vale a dire che utilizza i valori angolari predefiniti (45 e 135 gradi)."
+msgstr "Un elenco di direzioni linee intere da usare quando i layers superiori/inferiori utilizzano le linee o la configurazione zig zag. Gli elementi dall’elenco sono utilizzati in sequenza con il progredire dei layers e, al raggiungimento della fine dell’elenco, la sequenza ricomincia dall’inizio. Le voci elencate sono separate da virgole e l’intero elenco è racchiuso tra parentesi quadre. L’elenco predefinito è vuoto, vale a dire che utilizza i valori angolari predefiniti (45 e 135 gradi)."
#: fdmprinter.def.json
msgctxt "wall_0_inset label"
@@ -1025,6 +965,16 @@ msgctxt "wall_0_inset description"
msgid "Inset applied to the path of the outer wall. If the outer wall is smaller than the nozzle, and printed after the inner walls, use this offset to get the hole in the nozzle to overlap with the inner walls instead of the outside of the model."
msgstr "Inserto applicato al percorso della parete esterna. Se la parete esterna è di dimensioni inferiori all’ugello e stampata dopo le pareti interne, utilizzare questo offset per fare in modo che il foro dell’ugello si sovrapponga alle pareti interne anziché all’esterno del modello."
+#: fdmprinter.def.json
+msgctxt "optimize_wall_printing_order label"
+msgid "Optimize Wall Printing Order"
+msgstr "Ottimizzazione sequenza di stampa pareti"
+
+#: fdmprinter.def.json
+msgctxt "optimize_wall_printing_order description"
+msgid "Optimize the order in which walls are printed so as to reduce the number of retractions and the distance travelled. Most parts will benefit from this being enabled but some may actually take longer so please compare the print time estimates with and without optimization."
+msgstr "Ottimizza l'ordine in cui vengono stampate le pareti in modo da ridurre le retrazioni e la distanza percorsa. L'abilitazione di questa funzione porta vantaggi per la maggior parte dei pezzi, ma alcuni potrebbero richiedere un maggior tempo di esecuzione, per cui si consiglia di confrontare i tempi di stampa stimati con e senza ottimizzazione."
+
#: fdmprinter.def.json
msgctxt "outer_inset_first label"
msgid "Outer Before Inner Walls"
@@ -1095,6 +1045,16 @@ msgctxt "fill_perimeter_gaps option everywhere"
msgid "Everywhere"
msgstr "In tutti i possibili punti"
+#: fdmprinter.def.json
+msgctxt "filter_out_tiny_gaps label"
+msgid "Filter Out Tiny Gaps"
+msgstr "Esclusione spazi minimi"
+
+#: fdmprinter.def.json
+msgctxt "filter_out_tiny_gaps description"
+msgid "Filter out tiny gaps to reduce blobs on outside of model."
+msgstr "Esclude gli spazi minimi per ridurre le gocce sull’esterno del modello."
+
#: fdmprinter.def.json
msgctxt "fill_outline_gaps label"
msgid "Print Thin Walls"
@@ -1113,17 +1073,17 @@ msgstr "Espansione orizzontale"
#: fdmprinter.def.json
msgctxt "xy_offset description"
msgid "Amount of offset applied to all polygons in each layer. Positive values can compensate for too big holes; negative values can compensate for too small holes."
-msgstr "Determina l'entità di offset (o estensione dello strato) applicata a tutti i poligoni su ciascuno strato. I valori positivi possono compensare fori troppo estesi; i valori negativi possono compensare fori troppo piccoli."
+msgstr "Determina l'entità di offset (o estensione del layer) applicata a tutti i poligoni su ciascun layer. I valori positivi possono compensare fori troppo estesi; i valori negativi possono compensare fori troppo piccoli."
#: fdmprinter.def.json
msgctxt "xy_offset_layer_0 label"
msgid "Initial Layer Horizontal Expansion"
-msgstr "Espansione orizzontale dello strato iniziale"
+msgstr "Espansione orizzontale del layer iniziale"
#: fdmprinter.def.json
msgctxt "xy_offset_layer_0 description"
msgid "Amount of offset applied to all polygons in the first layer. A negative value can compensate for squishing of the first layer known as \"elephant's foot\"."
-msgstr "È l'entità di offset (estensione dello strato) applicata a tutti i poligoni di supporto in ciascuno strato. Un valore negativo può compensare lo schiacciamento del primo strato noto come \"zampa di elefante\"."
+msgstr "È l'entità di offset (estensione del layer) applicata a tutti i poligoni di supporto in ciascun layer. Un valore negativo può compensare lo schiacciamento del primo layer noto come \"zampa di elefante\"."
#: fdmprinter.def.json
msgctxt "z_seam_type label"
@@ -1133,7 +1093,7 @@ msgstr "Allineamento delle giunzioni a Z"
#: fdmprinter.def.json
msgctxt "z_seam_type description"
msgid "Starting point of each path in a layer. When paths in consecutive layers start at the same point a vertical seam may show on the print. When aligning these near a user specified location, the seam is easiest to remove. When placed randomly the inaccuracies at the paths' start will be less noticeable. When taking the shortest path the print will be quicker."
-msgstr "Punto di partenza di ogni percorso nell'ambito di uno strato. Quando i percorsi in strati consecutivi iniziano nello stesso punto, sulla stampa può apparire una linea di giunzione verticale. Se si allineano in prossimità di una posizione specificata dall’utente, la linea di giunzione può essere rimossa più facilmente. Se disposti in modo casuale, le imprecisioni in corrispondenza dell'inizio del percorso saranno meno evidenti. Prendendo il percorso più breve la stampa sarà più veloce."
+msgstr "Punto di partenza di ogni percorso nell'ambito di un layer. Quando i percorsi in layers consecutivi iniziano nello stesso punto, sulla stampa può apparire una linea di giunzione verticale. Se si allineano in prossimità di una posizione specificata dall’utente, la linea di giunzione può essere rimossa più facilmente. Se disposti in modo casuale, le imprecisioni in corrispondenza dell'inizio del percorso saranno meno evidenti. Prendendo il percorso più breve la stampa sarà più veloce."
#: fdmprinter.def.json
msgctxt "z_seam_type option back"
@@ -1163,7 +1123,7 @@ msgstr "Giunzione Z X"
#: fdmprinter.def.json
msgctxt "z_seam_x description"
msgid "The X coordinate of the position near where to start printing each part in a layer."
-msgstr "La coordinata X della posizione in prossimità della quale si innesca all’avvio della stampa di ciascuna parte in uno strato."
+msgstr "La coordinata X della posizione in prossimità della quale si innesca all’avvio della stampa di ciascuna parte in un layer."
#: fdmprinter.def.json
msgctxt "z_seam_y label"
@@ -1173,7 +1133,7 @@ msgstr "Giunzione Z Y"
#: fdmprinter.def.json
msgctxt "z_seam_y description"
msgid "The Y coordinate of the position near where to start printing each part in a layer."
-msgstr "La coordinata Y della posizione in prossimità della quale si innesca all’avvio della stampa di ciascuna parte in uno strato."
+msgstr "La coordinata Y della posizione in prossimità della quale si innesca all’avvio della stampa di ciascuna parte in un layer."
#: fdmprinter.def.json
msgctxt "z_seam_corner label"
@@ -1248,12 +1208,12 @@ msgstr "Ulteriore passaggio sopra la superficie superiore, senza estrusione di m
#: fdmprinter.def.json
msgctxt "ironing_only_highest_layer label"
msgid "Iron Only Highest Layer"
-msgstr "Stiramento del solo strato più elevato"
+msgstr "Stiramento del solo layer più elevato"
#: fdmprinter.def.json
msgctxt "ironing_only_highest_layer description"
msgid "Only perform ironing on the very last layer of the mesh. This saves time if the lower layers don't need a smooth surface finish."
-msgstr "Effettua lo stiramento solo dell'ultimissimo strato della maglia. È possibile quindi risparmiare tempo se gli strati inferiori non richiedono una finitura con superficie liscia."
+msgstr "Effettua lo stiramento solo dell'ultimissimo layer della maglia. È possibile quindi risparmiare tempo se i layers inferiori non richiedono una finitura con superficie liscia."
#: fdmprinter.def.json
msgctxt "ironing_pattern label"
@@ -1353,7 +1313,7 @@ msgstr "Estrusore riempimento"
#: fdmprinter.def.json
msgctxt "infill_extruder_nr description"
msgid "The extruder train used for printing infill. This is used in multi-extrusion."
-msgstr "Treno estrusore utilizzato per stampare il riempimento. Si utilizza nell'estrusione multipla."
+msgstr "Blocco estrusore utilizzato per stampare il riempimento. Si utilizza nell'estrusione multipla."
#: fdmprinter.def.json
msgctxt "infill_sparse_density label"
@@ -1383,7 +1343,7 @@ 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."
+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 layer. Le configurazioni cubiche, a quarto di cubo e ottagonali variano per ciascun layer per garantire una più uniforme distribuzione della forza in ogni direzione."
#: fdmprinter.def.json
msgctxt "infill_pattern option grid"
@@ -1468,7 +1428,7 @@ msgstr "Direzioni delle linee di riempimento"
#: fdmprinter.def.json
msgctxt "infill_angles description"
msgid "A list of integer line directions to use. Elements from the list are used sequentially as the layers progress and when the end of the list is reached, it starts at the beginning again. The list items are separated by commas and the whole list is contained in square brackets. Default is an empty list which means use the traditional default angles (45 and 135 degrees for the lines and zig zag patterns and 45 degrees for all other patterns)."
-msgstr "Un elenco di direzioni linee intere. Gli elementi dall’elenco sono utilizzati in sequenza con il progredire degli strati e, al raggiungimento della fine dell’elenco, la sequenza ricomincia dall’inizio. Le voci elencate sono separate da virgole e l’intero elenco è racchiuso tra parentesi quadre. L’elenco predefinito è vuoto, vale a dire che utilizza i valori angolari predefiniti (45 e 135 gradi per le linee e la configurazione zig zag e 45 gradi per tutte le altre configurazioni)."
+msgstr "Un elenco di direzioni linee intere. Gli elementi dall’elenco sono utilizzati in sequenza con il progredire dei layers e, al raggiungimento della fine dell’elenco, la sequenza ricomincia dall’inizio. Le voci elencate sono separate da virgole e l’intero elenco è racchiuso tra parentesi quadre. L’elenco predefinito è vuoto, vale a dire che utilizza i valori angolari predefiniti (45 e 135 gradi per le linee e la configurazione zig zag e 45 gradi per tutte le altre configurazioni)."
#: fdmprinter.def.json
msgctxt "infill_offset_x label"
@@ -1477,8 +1437,8 @@ msgstr "Offset X riempimento"
#: fdmprinter.def.json
msgctxt "infill_offset_x description"
-msgid "The infill pattern is offset this distance along the X axis."
-msgstr "Il riempimento si scosta di questa distanza lungo l'asse X."
+msgid "The infill pattern is moved this distance along the X axis."
+msgstr "Il riempimento si sposta di questa distanza lungo l'asse X."
#: fdmprinter.def.json
msgctxt "infill_offset_y label"
@@ -1487,8 +1447,8 @@ msgstr "Offset Y riempimento"
#: fdmprinter.def.json
msgctxt "infill_offset_y description"
-msgid "The infill pattern is offset this distance along the Y axis."
-msgstr "Il riempimento si scosta di questa distanza lungo l'asse Y."
+msgid "The infill pattern is moved this distance along the Y axis."
+msgstr "Il riempimento si sposta di questa distanza lungo l'asse Y."
#: fdmprinter.def.json
msgctxt "sub_div_rad_add label"
@@ -1507,8 +1467,8 @@ msgstr "Percentuale di sovrapposizione del riempimento"
#: fdmprinter.def.json
msgctxt "infill_overlap description"
-msgid "The amount of overlap between the infill and the walls. A slight overlap allows the walls to connect firmly to the infill."
-msgstr "Indica la quantità di sovrapposizione tra il riempimento e le pareti. Una leggera sovrapposizione consente il saldo collegamento delle pareti al riempimento."
+msgid "The amount of overlap between the infill and the walls as a percentage of the infill line width. A slight overlap allows the walls to connect firmly to the infill."
+msgstr "Indica la quantità di sovrapposizione tra il riempimento e le pareti come percentuale della larghezza della linea di riempimento. Una leggera sovrapposizione consente il saldo collegamento delle pareti al riempimento."
#: fdmprinter.def.json
msgctxt "infill_overlap_mm label"
@@ -1527,8 +1487,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 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. 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 "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."
#: fdmprinter.def.json
msgctxt "skin_overlap_mm label"
@@ -1553,12 +1513,12 @@ msgstr "Indica la distanza di uno spostamento inserito dopo ogni linea di riempi
#: fdmprinter.def.json
msgctxt "infill_sparse_thickness label"
msgid "Infill Layer Thickness"
-msgstr "Spessore dello strato di riempimento"
+msgstr "Spessore del layer di riempimento"
#: fdmprinter.def.json
msgctxt "infill_sparse_thickness description"
msgid "The thickness per layer of infill material. This value should always be a multiple of the layer height and is otherwise rounded."
-msgstr "Indica lo spessore per strato di materiale di riempimento. Questo valore deve sempre essere un multiplo dell’altezza dello strato e in caso contrario viene arrotondato."
+msgstr "Indica lo spessore per layer di materiale di riempimento. Questo valore deve sempre essere un multiplo dell’altezza del layer e in caso contrario viene arrotondato."
#: fdmprinter.def.json
msgctxt "gradual_infill_steps label"
@@ -1633,7 +1593,7 @@ msgstr "Larghezza massima delle aree di rivestimento inferiore che è possibile
#: fdmprinter.def.json
msgctxt "expand_skins_expand_distance label"
msgid "Skin Expand Distance"
-msgstr "Distanza prolunga rivestimento esterno"
+msgstr "Distanza espansione rivestimento esterno"
#: fdmprinter.def.json
msgctxt "expand_skins_expand_distance description"
@@ -1643,7 +1603,7 @@ msgstr "Distanza per cui i rivestimenti si estendono nel riempimento. Valori mag
#: fdmprinter.def.json
msgctxt "top_skin_expand_distance label"
msgid "Top Skin Expand Distance"
-msgstr "Distanza prolunga rivestimento superiore"
+msgstr "Distanza espansione rivestimento superiore"
#: fdmprinter.def.json
msgctxt "top_skin_expand_distance description"
@@ -1653,7 +1613,7 @@ msgstr "Distanza per cui i rivestimenti superiori si estendono nel riempimento.
#: fdmprinter.def.json
msgctxt "bottom_skin_expand_distance label"
msgid "Bottom Skin Expand Distance"
-msgstr "Distanza prolunga rivestimento inferiore"
+msgstr "Distanza espansione rivestimento inferiore"
#: fdmprinter.def.json
msgctxt "bottom_skin_expand_distance description"
@@ -1663,7 +1623,7 @@ msgstr "Distanza per cui i rivestimenti inferiori si estendono nel riempimento.
#: fdmprinter.def.json
msgctxt "max_skin_angle_for_expansion label"
msgid "Maximum Skin Angle for Expansion"
-msgstr "Angolo massimo rivestimento esterno per prolunga"
+msgstr "Angolo massimo rivestimento esterno per espansione"
#: fdmprinter.def.json
msgctxt "max_skin_angle_for_expansion description"
@@ -1673,7 +1633,7 @@ msgstr "Per le superfici inferiori e/o superiori dell’oggetto con un angolo ma
#: fdmprinter.def.json
msgctxt "min_skin_width_for_expansion label"
msgid "Minimum Skin Width for Expansion"
-msgstr "Larghezza minima rivestimento esterno per prolunga"
+msgstr "Larghezza minima rivestimento esterno per espansione"
#: fdmprinter.def.json
msgctxt "min_skin_width_for_expansion description"
@@ -1690,16 +1650,6 @@ msgctxt "material description"
msgid "Material"
msgstr "Materiale"
-#: fdmprinter.def.json
-msgctxt "material_flow_dependent_temperature label"
-msgid "Auto Temperature"
-msgstr "Temperatura automatica"
-
-#: fdmprinter.def.json
-msgctxt "material_flow_dependent_temperature description"
-msgid "Change the temperature for each layer automatically with the average flow speed of that layer."
-msgstr "Modifica automaticamente la temperatura per ciascuno strato con la velocità media del flusso per tale strato."
-
#: fdmprinter.def.json
msgctxt "default_material_print_temperature label"
msgid "Default Printing Temperature"
@@ -1723,12 +1673,12 @@ msgstr "Indica la temperatura usata per la stampa."
#: fdmprinter.def.json
msgctxt "material_print_temperature_layer_0 label"
msgid "Printing Temperature Initial Layer"
-msgstr "Temperatura di stampa Strato iniziale"
+msgstr "Temperatura di stampa layer iniziale"
#: fdmprinter.def.json
msgctxt "material_print_temperature_layer_0 description"
msgid "The temperature used for printing the first layer. Set at 0 to disable special handling of the initial layer."
-msgstr "Indica la temperatura usata per la stampa del primo strato. Impostare a 0 per disabilitare la manipolazione speciale dello strato iniziale."
+msgstr "Indica la temperatura usata per la stampa del primo layer. Impostare a 0 per disabilitare la manipolazione speciale del layer iniziale."
#: fdmprinter.def.json
msgctxt "material_initial_print_temperature label"
@@ -1750,16 +1700,6 @@ msgctxt "material_final_print_temperature description"
msgid "The temperature to which to already start cooling down just before the end of printing."
msgstr "La temperatura alla quale può già iniziare il raffreddamento prima della fine della stampa."
-#: fdmprinter.def.json
-msgctxt "material_flow_temp_graph label"
-msgid "Flow Temperature Graph"
-msgstr "Grafico della temperatura del flusso"
-
-#: fdmprinter.def.json
-msgctxt "material_flow_temp_graph description"
-msgid "Data linking material flow (in mm3 per second) to temperature (degrees Celsius)."
-msgstr "Collegamento dei dati di flusso del materiale (in mm3 al secondo) alla temperatura (in °C)."
-
#: fdmprinter.def.json
msgctxt "material_extrusion_cool_down_speed label"
msgid "Extrusion Cool Down Speed Modifier"
@@ -1777,18 +1717,18 @@ msgstr "Temperatura piano di stampa"
#: fdmprinter.def.json
msgctxt "material_bed_temperature description"
-msgid "The temperature used for the heated build plate. If this is 0, the bed will not heat up for this print."
-msgstr "Indica la temperatura usata per il piano di stampa riscaldato. Se è 0, il piano non si riscalda per questa stampa."
+msgid "The temperature used for the heated build plate. If this is 0, the bed temperature will not be adjusted."
+msgstr "Indica la temperatura usata per il piano di stampa riscaldato. Se è 0, la temperatura del piano non si regola."
#: fdmprinter.def.json
msgctxt "material_bed_temperature_layer_0 label"
msgid "Build Plate Temperature Initial Layer"
-msgstr "Temperatura piano di stampa Strato iniziale"
+msgstr "Temperatura piano di stampa Layer iniziale"
#: fdmprinter.def.json
msgctxt "material_bed_temperature_layer_0 description"
msgid "The temperature used for the heated build plate at the first layer."
-msgstr "Indica la temperatura usata per il piano di stampa riscaldato per il primo strato."
+msgstr "Indica la temperatura usata per il piano di stampa riscaldato per il primo layer."
#: fdmprinter.def.json
msgctxt "material_diameter label"
@@ -1843,12 +1783,12 @@ msgstr "Ritrae il filamento quando l'ugello si sta muovendo su un'area non stamp
#: fdmprinter.def.json
msgctxt "retract_at_layer_change label"
msgid "Retract at Layer Change"
-msgstr "Retrazione al cambio strato"
+msgstr "Retrazione al cambio layer"
#: fdmprinter.def.json
msgctxt "retract_at_layer_change description"
msgid "Retract the filament when the nozzle is moving to the next layer."
-msgstr "Ritrae il filamento quando l'ugello si sta muovendo allo strato successivo. "
+msgstr "Ritrae il filamento quando l'ugello si sta muovendo al layer successivo. "
#: fdmprinter.def.json
msgctxt "retraction_amount label"
@@ -2113,12 +2053,12 @@ msgstr "Velocità alla quale viene stampata la parte inferiore del supporto. La
#: fdmprinter.def.json
msgctxt "speed_prime_tower label"
msgid "Prime Tower Speed"
-msgstr "Velocità della torre di innesco"
+msgstr "Velocità della Prime Tower"
#: fdmprinter.def.json
msgctxt "speed_prime_tower description"
msgid "The speed at which the prime tower is printed. Printing the prime tower slower can make it more stable when the adhesion between the different filaments is suboptimal."
-msgstr "Indica la velocità alla quale è stampata la torre di innesco. La stampa della torre di innesco a una velocità inferiore può renderla maggiormente stabile quando l’adesione tra i diversi filamenti non è ottimale."
+msgstr "Indica la velocità alla quale è stampata la Prime Tower. La stampa della Prime Tower a una velocità inferiore può renderla maggiormente stabile quando l’adesione tra i diversi filamenti non è ottimale."
#: fdmprinter.def.json
msgctxt "speed_travel label"
@@ -2133,32 +2073,32 @@ msgstr "Indica la velocità alla quale vengono effettuati gli spostamenti."
#: fdmprinter.def.json
msgctxt "speed_layer_0 label"
msgid "Initial Layer Speed"
-msgstr "Velocità di stampa dello strato iniziale"
+msgstr "Velocità di stampa del layer iniziale"
#: fdmprinter.def.json
msgctxt "speed_layer_0 description"
msgid "The speed for the initial layer. A lower value is advised to improve adhesion to the build plate."
-msgstr "Indica la velocità per lo strato iniziale. Un valore inferiore è consigliabile per migliorare l’adesione al piano di stampa."
+msgstr "Indica la velocità per il layer iniziale. Un valore inferiore è consigliabile per migliorare l’adesione al piano di stampa."
#: fdmprinter.def.json
msgctxt "speed_print_layer_0 label"
msgid "Initial Layer Print Speed"
-msgstr "Velocità di stampa strato iniziale"
+msgstr "Velocità di stampa layer iniziale"
#: fdmprinter.def.json
msgctxt "speed_print_layer_0 description"
msgid "The speed of printing for the initial layer. A lower value is advised to improve adhesion to the build plate."
-msgstr "Indica la velocità di stampa per lo strato iniziale. Un valore inferiore è consigliabile per migliorare l’adesione al piano di stampa."
+msgstr "Indica la velocità di stampa per il layer iniziale. Un valore inferiore è consigliabile per migliorare l’adesione al piano di stampa."
#: fdmprinter.def.json
msgctxt "speed_travel_layer_0 label"
msgid "Initial Layer Travel Speed"
-msgstr "Velocità di spostamento dello strato iniziale"
+msgstr "Velocità di spostamento del layer iniziale"
#: fdmprinter.def.json
msgctxt "speed_travel_layer_0 description"
msgid "The speed of travel moves in the initial layer. A lower value is advised to prevent pulling previously printed parts away from the build plate. The value of this setting can automatically be calculated from the ratio between the Travel Speed and the Print Speed."
-msgstr "Indica la velocità di spostamento per lo strato iniziale. Un valore inferiore è consigliabile per evitare di rimuovere le parti precedentemente stampate dal piano di stampa. Il valore di questa impostazione può essere calcolato automaticamente dal rapporto tra la velocità di spostamento e la velocità di stampa."
+msgstr "Indica la velocità di spostamento del layer iniziale. Un valore inferiore è consigliabile per evitare di rimuovere le parti precedentemente stampate dal piano di stampa. Il valore di questa impostazione può essere calcolato automaticamente dal rapporto tra la velocità di spostamento e la velocità di stampa."
#: fdmprinter.def.json
msgctxt "skirt_brim_speed label"
@@ -2183,12 +2123,12 @@ msgstr "Indica la velocità massima di spostamento del piano di stampa. L’impo
#: fdmprinter.def.json
msgctxt "speed_slowdown_layers label"
msgid "Number of Slower Layers"
-msgstr "Numero di strati stampati a velocità inferiore"
+msgstr "Numero di layers stampati a velocità inferiore"
#: fdmprinter.def.json
msgctxt "speed_slowdown_layers description"
msgid "The first few layers are printed slower than the rest of the model, to get better adhesion to the build plate and improve the overall success rate of prints. The speed is gradually increased over these layers."
-msgstr "I primi strati vengono stampati più lentamente rispetto al resto del modello, per ottenere una migliore adesione al piano di stampa ed ottimizzare nel complesso la percentuale di successo delle stampe. La velocità aumenta gradualmente nel corso di esecuzione degli strati successivi."
+msgstr "I primi layers vengono stampati più lentamente rispetto al resto del modello, per ottenere una migliore adesione al piano di stampa ed ottimizzare nel complesso la percentuale di successo delle stampe. La velocità aumenta gradualmente nel corso di esecuzione dei layers successivi."
#: fdmprinter.def.json
msgctxt "speed_equalize_flow_enabled label"
@@ -2343,12 +2283,12 @@ msgstr "Accelerazione alla quale vengono stampate le parti inferiori del support
#: fdmprinter.def.json
msgctxt "acceleration_prime_tower label"
msgid "Prime Tower Acceleration"
-msgstr "Accelerazione della torre di innesco"
+msgstr "Accelerazione della Prime Tower"
#: fdmprinter.def.json
msgctxt "acceleration_prime_tower description"
msgid "The acceleration with which the prime tower is printed."
-msgstr "Indica l’accelerazione con cui viene stampata la torre di innesco."
+msgstr "Indica l’accelerazione con cui viene stampata la Prime Tower."
#: fdmprinter.def.json
msgctxt "acceleration_travel label"
@@ -2363,32 +2303,32 @@ msgstr "Indica l’accelerazione alla quale vengono effettuati gli spostamenti."
#: fdmprinter.def.json
msgctxt "acceleration_layer_0 label"
msgid "Initial Layer Acceleration"
-msgstr "Accelerazione dello strato iniziale"
+msgstr "Accelerazione del layer iniziale"
#: fdmprinter.def.json
msgctxt "acceleration_layer_0 description"
msgid "The acceleration for the initial layer."
-msgstr "Indica l’accelerazione dello strato iniziale."
+msgstr "Indica l’accelerazione del layer iniziale."
#: fdmprinter.def.json
msgctxt "acceleration_print_layer_0 label"
msgid "Initial Layer Print Acceleration"
-msgstr "Accelerazione di stampa strato iniziale"
+msgstr "Accelerazione di stampa layer iniziale"
#: fdmprinter.def.json
msgctxt "acceleration_print_layer_0 description"
msgid "The acceleration during the printing of the initial layer."
-msgstr "Indica l’accelerazione durante la stampa dello strato iniziale."
+msgstr "Indica l’accelerazione durante la stampa del layer iniziale."
#: fdmprinter.def.json
msgctxt "acceleration_travel_layer_0 label"
msgid "Initial Layer Travel Acceleration"
-msgstr "Accelerazione spostamenti dello strato iniziale"
+msgstr "Accelerazione spostamenti del layer iniziale"
#: fdmprinter.def.json
msgctxt "acceleration_travel_layer_0 description"
msgid "The acceleration for travel moves in the initial layer."
-msgstr "Indica l’accelerazione degli spostamenti dello strato iniziale."
+msgstr "Indica l’accelerazione degli spostamenti del layer iniziale."
#: fdmprinter.def.json
msgctxt "acceleration_skirt_brim label"
@@ -2398,7 +2338,7 @@ msgstr "Accelerazione skirt/brim"
#: fdmprinter.def.json
msgctxt "acceleration_skirt_brim description"
msgid "The acceleration with which the skirt and brim are printed. Normally this is done with the initial layer acceleration, but sometimes you might want to print the skirt or brim at a different acceleration."
-msgstr "Indica l’accelerazione alla quale sono stampati lo skirt ed il brim. Normalmente questa operazione viene svolta all’accelerazione dello strato iniziale, ma a volte è possibile che si desideri stampare lo skirt o il brim ad un’accelerazione diversa."
+msgstr "Indica l’accelerazione alla quale sono stampati lo skirt ed il brim. Normalmente questa operazione viene svolta all’accelerazione del layer iniziale, ma a volte è possibile che si desideri stampare lo skirt o il brim ad un’accelerazione diversa."
#: fdmprinter.def.json
msgctxt "jerk_enabled label"
@@ -2408,7 +2348,7 @@ msgstr "Abilita controllo jerk"
#: fdmprinter.def.json
msgctxt "jerk_enabled description"
msgid "Enables adjusting the jerk of print head when the velocity in the X or Y axis changes. Increasing the jerk can reduce printing time at the cost of print quality."
-msgstr "Abilita la regolazione del jerk della testina di stampa quando la velocità nell’asse X o Y cambia. Aumentando il jerk il tempo di stampa si riduce a discapito della qualità di stampa."
+msgstr "Abilita la regolazione del jerk della testa di stampa quando la velocità nell’asse X o Y cambia. Aumentando il jerk il tempo di stampa si riduce a discapito della qualità di stampa."
#: fdmprinter.def.json
msgctxt "jerk_print label"
@@ -2418,7 +2358,7 @@ msgstr "Jerk stampa"
#: fdmprinter.def.json
msgctxt "jerk_print description"
msgid "The maximum instantaneous velocity change of the print head."
-msgstr "Indica il cambio della velocità istantanea massima della testina di stampa."
+msgstr "Indica il cambio della velocità istantanea massima della testa di stampa."
#: fdmprinter.def.json
msgctxt "jerk_infill label"
@@ -2468,7 +2408,7 @@ msgstr "Jerk del rivestimento superficie superiore"
#: fdmprinter.def.json
msgctxt "jerk_roofing description"
msgid "The maximum instantaneous velocity change with which top surface skin layers are printed."
-msgstr "Indica la variazione di velocità istantanea massima con cui vengono stampati gli strati rivestimento superficie superiore."
+msgstr "Indica la variazione di velocità istantanea massima con cui vengono stampati i layers rivestimento superficie superiore."
#: fdmprinter.def.json
msgctxt "jerk_topbottom label"
@@ -2478,7 +2418,7 @@ msgstr "Jerk strato superiore/inferiore"
#: fdmprinter.def.json
msgctxt "jerk_topbottom description"
msgid "The maximum instantaneous velocity change with which top/bottom layers are printed."
-msgstr "Indica il cambio della velocità istantanea massima con cui vengono stampati gli strati superiore/inferiore."
+msgstr "Indica il cambio della velocità istantanea massima con cui vengono stampati i layers superiore/inferiore."
#: fdmprinter.def.json
msgctxt "jerk_support label"
@@ -2533,12 +2473,12 @@ msgstr "Indica la variazione della velocità istantanea massima con cui vengono
#: fdmprinter.def.json
msgctxt "jerk_prime_tower label"
msgid "Prime Tower Jerk"
-msgstr "Jerk della torre di innesco"
+msgstr "Jerk della Prime Tower"
#: fdmprinter.def.json
msgctxt "jerk_prime_tower description"
msgid "The maximum instantaneous velocity change with which the prime tower is printed."
-msgstr "Indica il cambio della velocità istantanea massima con cui viene stampata la torre di innesco del supporto."
+msgstr "Indica il cambio della velocità istantanea massima con cui viene stampata la Prime Tower del supporto."
#: fdmprinter.def.json
msgctxt "jerk_travel label"
@@ -2553,32 +2493,32 @@ msgstr "Indica il cambio della velocità istantanea massima con cui vengono effe
#: fdmprinter.def.json
msgctxt "jerk_layer_0 label"
msgid "Initial Layer Jerk"
-msgstr "Jerk dello strato iniziale"
+msgstr "Jerk del layer iniziale"
#: fdmprinter.def.json
msgctxt "jerk_layer_0 description"
msgid "The print maximum instantaneous velocity change for the initial layer."
-msgstr "Indica il cambio della velocità istantanea massima dello strato iniziale."
+msgstr "Indica il cambio della velocità istantanea massima del layer iniziale."
#: fdmprinter.def.json
msgctxt "jerk_print_layer_0 label"
msgid "Initial Layer Print Jerk"
-msgstr "Jerk di stampa strato iniziale"
+msgstr "Jerk di stampa layer iniziale"
#: fdmprinter.def.json
msgctxt "jerk_print_layer_0 description"
msgid "The maximum instantaneous velocity change during the printing of the initial layer."
-msgstr "Indica il cambio della velocità istantanea massima durante la stampa dello strato iniziale."
+msgstr "Indica il cambio della velocità istantanea massima durante la stampa del layer iniziale."
#: fdmprinter.def.json
msgctxt "jerk_travel_layer_0 label"
msgid "Initial Layer Travel Jerk"
-msgstr "Jerk spostamenti dello strato iniziale"
+msgstr "Jerk spostamenti del layer iniziale"
#: fdmprinter.def.json
msgctxt "jerk_travel_layer_0 description"
msgid "The acceleration for travel moves in the initial layer."
-msgstr "Indica l’accelerazione degli spostamenti dello strato iniziale."
+msgstr "Indica l’accelerazione degli spostamenti del layer iniziale."
#: fdmprinter.def.json
msgctxt "jerk_skirt_brim label"
@@ -2658,22 +2598,22 @@ msgstr "La distanza tra l’ugello e le parti già stampate quando si effettua l
#: fdmprinter.def.json
msgctxt "start_layers_at_same_position label"
msgid "Start Layers with the Same Part"
-msgstr "Avvio strati con la stessa parte"
+msgstr "Avvio layers con la stessa parte"
#: fdmprinter.def.json
msgctxt "start_layers_at_same_position description"
msgid "In each layer start with printing the object near the same point, so that we don't start a new layer with printing the piece which the previous layer ended with. This makes for better overhangs and small parts, but increases printing time."
-msgstr "In ciascuno strato inizia la stampa dell’oggetto vicino allo stesso punto, in modo che non si inizia un nuovo strato con la stampa del pezzo con cui è terminato lo strato precedente. Questo consente di ottenere migliori sovrapposizioni e parti piccole, ma aumenta il tempo di stampa."
+msgstr "In ciascun layer inizia la stampa dell’oggetto vicino allo stesso punto, in modo che non si inizi un nuovo layer con la stampa del pezzo con cui è terminato il layer precedente. Questo consente di ottenere migliori sovrapposizioni e parti piccole, ma aumenta il tempo di stampa."
#: fdmprinter.def.json
msgctxt "layer_start_x label"
msgid "Layer Start X"
-msgstr "Avvio strato X"
+msgstr "Avvio layer X"
#: fdmprinter.def.json
msgctxt "layer_start_x description"
msgid "The X coordinate of the position near where to find the part to start printing each layer."
-msgstr "La coordinata X della posizione in prossimità della quale si trova la parte per avviare la stampa di ciascuno strato."
+msgstr "La coordinata X della posizione in prossimità della quale si trova la parte per avviare la stampa di ciascun layer."
#: fdmprinter.def.json
msgctxt "layer_start_y label"
@@ -2683,7 +2623,7 @@ msgstr "Avvio strato Y"
#: fdmprinter.def.json
msgctxt "layer_start_y description"
msgid "The Y coordinate of the position near where to find the part to start printing each layer."
-msgstr "La coordinata Y della posizione in prossimità della quale si trova la parte per avviare la stampa di ciascuno strato."
+msgstr "La coordinata Y della posizione in prossimità della quale si trova la parte per avviare la stampa di ciascun layer."
#: fdmprinter.def.json
msgctxt "retraction_hop_enabled label"
@@ -2743,7 +2683,7 @@ msgstr "Abilitazione raffreddamento stampa"
#: fdmprinter.def.json
msgctxt "cool_fan_enabled description"
msgid "Enables the print cooling fans while printing. The fans improve print quality on layers with short layer times and bridging / overhangs."
-msgstr "Abilita le ventole di raffreddamento durante la stampa. Le ventole migliorano la qualità di stampa sugli strati con tempi per strato più brevi e ponti/sbalzi."
+msgstr "Abilita le ventole di raffreddamento durante la stampa. Le ventole migliorano la qualità di stampa sui layers con tempi per layer più brevi e ponti/sbalzi."
#: fdmprinter.def.json
msgctxt "cool_fan_speed label"
@@ -2763,7 +2703,7 @@ msgstr "Velocità regolare della ventola"
#: fdmprinter.def.json
msgctxt "cool_fan_speed_min description"
msgid "The speed at which the fans spin before hitting the threshold. When a layer prints faster than the threshold, the fan speed gradually inclines towards the maximum fan speed."
-msgstr "Indica la velocità alla quale ruotano le ventole prima di raggiungere la soglia. Quando uno strato viene stampato a una velocità superiore alla soglia, la velocità della ventola tende gradualmente verso la velocità massima della ventola."
+msgstr "Indica la velocità alla quale ruotano le ventole prima di raggiungere la soglia. Quando un layer viene stampato a una velocità superiore alla soglia, la velocità della ventola tende gradualmente verso la velocità massima della ventola."
#: fdmprinter.def.json
msgctxt "cool_fan_speed_max label"
@@ -2773,7 +2713,7 @@ msgstr "Velocità massima della ventola"
#: fdmprinter.def.json
msgctxt "cool_fan_speed_max description"
msgid "The speed at which the fans spin on the minimum layer time. The fan speed gradually increases between the regular fan speed and maximum fan speed when the threshold is hit."
-msgstr "Indica la velocità di rotazione della ventola al tempo minimo per strato. La velocità della ventola aumenta gradualmente tra la velocità regolare della ventola e la velocità massima della ventola quando viene raggiunta la soglia."
+msgstr "Indica la velocità di rotazione della ventola al tempo minimo per layer. La velocità della ventola aumenta gradualmente tra la velocità regolare della ventola e la velocità massima della ventola quando viene raggiunta la soglia."
#: fdmprinter.def.json
msgctxt "cool_min_layer_time_fan_speed_max label"
@@ -2783,7 +2723,7 @@ msgstr "Soglia velocità regolare/massima della ventola"
#: fdmprinter.def.json
msgctxt "cool_min_layer_time_fan_speed_max description"
msgid "The layer time which sets the threshold between regular fan speed and maximum fan speed. Layers that print slower than this time use regular fan speed. For faster layers the fan speed gradually increases towards the maximum fan speed."
-msgstr "Indica il tempo per strato che definisce la soglia tra la velocità regolare e quella massima della ventola. Gli strati che vengono stampati a una velocità inferiore a questo valore utilizzano una velocità regolare della ventola. Per gli strati stampati più velocemente la velocità della ventola aumenta gradualmente verso la velocità massima della ventola."
+msgstr "Indica il tempo per layer che definisce la soglia tra la velocità regolare e quella massima della ventola. Gli strati che vengono stampati a una velocità inferiore a questo valore utilizzano una velocità regolare della ventola. Per i layers stampati più velocemente la velocità della ventola aumenta gradualmente verso la velocità massima della ventola."
#: fdmprinter.def.json
msgctxt "cool_fan_speed_0 label"
@@ -2793,7 +2733,7 @@ msgstr "Velocità iniziale della ventola"
#: fdmprinter.def.json
msgctxt "cool_fan_speed_0 description"
msgid "The speed at which the fans spin at the start of the print. In subsequent layers the fan speed is gradually increased up to the layer corresponding to Regular Fan Speed at Height."
-msgstr "La velocità di rotazione della ventola all’inizio della stampa. Negli strati successivi la velocità della ventola aumenta gradualmente da zero fino allo strato corrispondente alla velocità regolare in altezza."
+msgstr "La velocità di rotazione della ventola all’inizio della stampa. Nei layers successivi la velocità della ventola aumenta gradualmente da zero fino allo strato corrispondente alla velocità regolare in altezza."
#: fdmprinter.def.json
msgctxt "cool_fan_full_at_height label"
@@ -2803,27 +2743,27 @@ msgstr "Velocità regolare della ventola in altezza"
#: fdmprinter.def.json
msgctxt "cool_fan_full_at_height description"
msgid "The height at which the fans spin on regular fan speed. At the layers below the fan speed gradually increases from Initial Fan Speed to Regular Fan Speed."
-msgstr "Indica l’altezza alla quale la ventola ruota alla velocità regolare. Agli strati stampati a velocità inferiore la velocità della ventola aumenta gradualmente dalla velocità iniziale a quella regolare."
+msgstr "Indica l’altezza alla quale la ventola ruota alla velocità regolare. ai layers stampati a velocità inferiore la velocità della ventola aumenta gradualmente dalla velocità iniziale a quella regolare."
#: fdmprinter.def.json
msgctxt "cool_fan_full_layer label"
msgid "Regular Fan Speed at Layer"
-msgstr "Velocità regolare della ventola in corrispondenza dello strato"
+msgstr "Velocità regolare della ventola in corrispondenza del layer"
#: fdmprinter.def.json
msgctxt "cool_fan_full_layer description"
msgid "The layer at which the fans spin on regular fan speed. If regular fan speed at height is set, this value is calculated and rounded to a whole number."
-msgstr "Indica lo strato in corrispondenza del quale la ventola ruota alla velocità regolare. Se è impostata la velocità regolare in altezza, questo valore viene calcolato e arrotondato a un numero intero."
+msgstr "Indica il layer in corrispondenza del quale la ventola ruota alla velocità regolare. Se è impostata la velocità regolare in altezza, questo valore viene calcolato e arrotondato a un numero intero."
#: fdmprinter.def.json
msgctxt "cool_min_layer_time label"
msgid "Minimum Layer Time"
-msgstr "Tempo minimo per strato"
+msgstr "Tempo minimo per layer"
#: fdmprinter.def.json
msgctxt "cool_min_layer_time description"
msgid "The minimum time spent in a layer. This forces the printer to slow down, to at least spend the time set here in one layer. This allows the printed material to cool down properly before printing the next layer. Layers may still take shorter than the minimal layer time if Lift Head is disabled and if the Minimum Speed would otherwise be violated."
-msgstr "Indica il tempo minimo dedicato a uno strato. Questo forza la stampante a rallentare, per impiegare almeno il tempo impostato qui per uno strato. Questo consente il corretto raffreddamento del materiale stampato prima di procedere alla stampa dello strato successivo. La stampa degli strati potrebbe richiedere un tempo inferiore al minimo se la funzione Sollevamento della testina è disabilitata e se la velocità minima non viene rispettata."
+msgstr "Indica il tempo minimo dedicato a un layer. Questo forza la stampante a rallentare, per impiegare almeno il tempo impostato qui per un layer. Questo consente il corretto raffreddamento del materiale stampato prima di procedere alla stampa del layer successivo. La stampa dei layers potrebbe richiedere un tempo inferiore al minimo se la funzione Sollevamento della testina è disabilitata e se la velocità minima non viene rispettata."
#: fdmprinter.def.json
msgctxt "cool_min_speed label"
@@ -2833,7 +2773,7 @@ msgstr "Velocità minima"
#: fdmprinter.def.json
msgctxt "cool_min_speed description"
msgid "The minimum print speed, despite slowing down due to the minimum layer time. When the printer would slow down too much, the pressure in the nozzle would be too low and result in bad print quality."
-msgstr "Indica la velocità minima di stampa, a prescindere dal rallentamento per il tempo minimo per strato. Quando la stampante rallenta eccessivamente, la pressione nell’ugello risulta insufficiente con conseguente scarsa qualità di stampa."
+msgstr "Indica la velocità minima di stampa, a prescindere dal rallentamento per il tempo minimo per layer. Quando la stampante rallenta eccessivamente, la pressione nell’ugello risulta insufficiente con conseguente scarsa qualità di stampa."
#: fdmprinter.def.json
msgctxt "cool_lift_head label"
@@ -2843,7 +2783,7 @@ msgstr "Sollevamento della testina"
#: fdmprinter.def.json
msgctxt "cool_lift_head description"
msgid "When the minimum speed is hit because of minimum layer time, lift the head away from the print and wait the extra time until the minimum layer time is reached."
-msgstr "Quando viene raggiunta la velocità minima per il tempo minimo per strato, sollevare la testina dalla stampa e attendere il tempo supplementare fino al raggiungimento del valore per tempo minimo per strato."
+msgstr "Quando viene raggiunta la velocità minima per il tempo minimo per layer, sollevare la testina dalla stampa e attendere il tempo supplementare fino al raggiungimento del valore per tempo minimo per layer."
#: fdmprinter.def.json
msgctxt "support label"
@@ -2873,7 +2813,7 @@ msgstr "Estrusore del supporto"
#: fdmprinter.def.json
msgctxt "support_extruder_nr description"
msgid "The extruder train to use for printing the support. This is used in multi-extrusion."
-msgstr "Il treno estrusore utilizzato per la stampa del supporto. Utilizzato nell’estrusione multipla."
+msgstr "Il blocco estrusore utilizzato per la stampa del supporto. Utilizzato nell’estrusione multipla."
#: fdmprinter.def.json
msgctxt "support_infill_extruder_nr label"
@@ -2883,17 +2823,17 @@ msgstr "Estrusore riempimento del supporto"
#: fdmprinter.def.json
msgctxt "support_infill_extruder_nr description"
msgid "The extruder train to use for printing the infill of the support. This is used in multi-extrusion."
-msgstr "Il treno estrusore utilizzato per la stampa del riempimento del supporto. Utilizzato nell’estrusione multipla."
+msgstr "Il blocco estrusore utilizzato per la stampa del riempimento del supporto. Utilizzato nell’estrusione multipla."
#: fdmprinter.def.json
msgctxt "support_extruder_nr_layer_0 label"
msgid "First Layer Support Extruder"
-msgstr "Estrusore del supporto primo strato"
+msgstr "Estrusore del supporto primo layer"
#: fdmprinter.def.json
msgctxt "support_extruder_nr_layer_0 description"
msgid "The extruder train to use for printing the first layer of support infill. This is used in multi-extrusion."
-msgstr "Il treno estrusore utilizzato per la stampa del primo strato del riempimento del supporto. Utilizzato nell’estrusione multipla."
+msgstr "Il blocco estrusore utilizzato per la stampa del primo layer del riempimento del supporto. Utilizzato nell’estrusione multipla."
#: fdmprinter.def.json
msgctxt "support_interface_extruder_nr label"
@@ -2903,7 +2843,7 @@ msgstr "Estrusore interfaccia del supporto"
#: fdmprinter.def.json
msgctxt "support_interface_extruder_nr description"
msgid "The extruder train to use for printing the roofs and floors of the support. This is used in multi-extrusion."
-msgstr "Treno estrusore utilizzato per la stampa delle parti superiori e inferiori del supporto. Utilizzato nell’estrusione multipla."
+msgstr "Blocco estrusore utilizzato per la stampa delle parti superiori e inferiori del supporto. Utilizzato nell’estrusione multipla."
#: fdmprinter.def.json
msgctxt "support_roof_extruder_nr label"
@@ -2913,7 +2853,7 @@ msgstr "Estrusore parte superiore del supporto"
#: fdmprinter.def.json
msgctxt "support_roof_extruder_nr description"
msgid "The extruder train to use for printing the roofs of the support. This is used in multi-extrusion."
-msgstr "Treno estrusore utilizzato per la stampa delle parti superiori del supporto. Utilizzato nell’estrusione multipla."
+msgstr "Blocco estrusore utilizzato per la stampa delle parti superiori del supporto. Utilizzato nell’estrusione multipla."
#: fdmprinter.def.json
msgctxt "support_bottom_extruder_nr label"
@@ -2923,7 +2863,7 @@ msgstr "Estrusore parte inferiore del supporto"
#: fdmprinter.def.json
msgctxt "support_bottom_extruder_nr description"
msgid "The extruder train to use for printing the floors of the support. This is used in multi-extrusion."
-msgstr "Treno estrusore utilizzato per la stampa delle parti inferiori del supporto. Utilizzato nell’estrusione multipla."
+msgstr "Blocco estrusore utilizzato per la stampa delle parti inferiori del supporto. Utilizzato nell’estrusione multipla."
#: fdmprinter.def.json
msgctxt "support_type label"
@@ -3143,12 +3083,12 @@ msgstr "È l'entità di offset (estensione dello strato) applicato a tutti i pol
#: fdmprinter.def.json
msgctxt "support_infill_sparse_thickness label"
msgid "Support Infill Layer Thickness"
-msgstr "Spessore dello strato di riempimento di supporto"
+msgstr "Spessore dello layer di riempimento di supporto"
#: fdmprinter.def.json
msgctxt "support_infill_sparse_thickness description"
msgid "The thickness per layer of support infill material. This value should always be a multiple of the layer height and is otherwise rounded."
-msgstr "Indica lo spessore per strato del materiale di riempimento del supporto. Questo valore deve sempre essere un multiplo dell’altezza dello strato e in caso contrario viene arrotondato."
+msgstr "Indica lo spessore per layer del materiale di riempimento del supporto. Questo valore deve sempre essere un multiplo dell’altezza del layer e in caso contrario viene arrotondato."
#: fdmprinter.def.json
msgctxt "gradual_support_infill_steps label"
@@ -3228,7 +3168,7 @@ msgstr "Spessore parte inferiore del supporto"
#: fdmprinter.def.json
msgctxt "support_bottom_height description"
msgid "The thickness of the support floors. This controls the number of dense layers that are printed on top of places of a model on which support rests."
-msgstr "Indica lo spessore delle parti inferiori del supporto. Questo controlla il numero di strati fitti stampati sulla sommità dei punti di un modello su cui appoggia un supporto."
+msgstr "Indica lo spessore delle parti inferiori del supporto. Questo controlla il numero di layers fitti stampati sulla sommità dei punti di un modello su cui appoggia un supporto."
#: fdmprinter.def.json
msgctxt "support_interface_skip_height label"
@@ -3450,6 +3390,16 @@ msgctxt "support_tower_roof_angle description"
msgid "The angle of a rooftop of a tower. A higher value results in pointed tower roofs, a lower value results in flattened tower roofs."
msgstr "L’angolo della parte superiore di una torre. Un valore superiore genera parti superiori appuntite, un valore inferiore, parti superiori piatte."
+#: fdmprinter.def.json
+msgctxt "support_mesh_drop_down label"
+msgid "Drop Down Support Mesh"
+msgstr "Maglia supporto di discesa"
+
+#: fdmprinter.def.json
+msgctxt "support_mesh_drop_down description"
+msgid "Make support everywhere below the support mesh, so that there's no overhang in the support mesh."
+msgstr "Genera supporti ovunque sotto la maglia di supporto, in modo che in questa non vi siano punti a sbalzo."
+
#: fdmprinter.def.json
msgctxt "platform_adhesion label"
msgid "Build Plate Adhesion"
@@ -3528,7 +3478,7 @@ msgstr "Estrusore adesione piano di stampa"
#: fdmprinter.def.json
msgctxt "adhesion_extruder_nr description"
msgid "The extruder train to use for printing the skirt/brim/raft. This is used in multi-extrusion."
-msgstr "Il treno estrusore utilizzato per la stampa dello skirt/brim/raft. Utilizzato nell’estrusione multipla."
+msgstr "Il blocco estrusore utilizzato per la stampa dello skirt/brim/raft. Utilizzato nell’estrusione multipla."
#: fdmprinter.def.json
msgctxt "skirt_line_count label"
@@ -3620,37 +3570,37 @@ msgstr "Traferro del raft"
#: fdmprinter.def.json
msgctxt "raft_airgap description"
msgid "The gap between the final raft layer and the first layer of the model. Only the first layer is raised by this amount to lower the bonding between the raft layer and the model. Makes it easier to peel off the raft."
-msgstr "È l'interstizio tra lo strato di raft finale ed il primo strato del modello. Solo il primo strato viene sollevato di questo valore per ridurre l'adesione fra lo strato di raft e il modello. Ciò rende più facile rimuovere il raft."
+msgstr "È l'interstizio tra il layer del raft finale ed il primo layer del modello. Solo il primo layer viene sollevato di questo valore per ridurre l'adesione fra lo strato di raft e il modello. Ciò rende più facile rimuovere il raft."
#: fdmprinter.def.json
msgctxt "layer_0_z_overlap label"
msgid "Initial Layer Z Overlap"
-msgstr "Z Sovrapposizione Primo Strato"
+msgstr "Z Sovrapposizione Primo Layer"
#: fdmprinter.def.json
msgctxt "layer_0_z_overlap description"
msgid "Make the first and second layer of the model overlap in the Z direction to compensate for the filament lost in the airgap. All models above the first model layer will be shifted down by this amount."
-msgstr "Effettua il primo e secondo strato di sovrapposizione modello nella direzione Z per compensare il filamento perso nel traferro. Tutti i modelli sopra il primo strato del modello saranno spostati verso il basso di questa quantità."
+msgstr "Effettua il primo e secondo layer di sovrapposizione modello nella direzione Z per compensare il filamento perso nel vuoto. Tutti i modelli sopra il primo layer del modello saranno spostati verso il basso di questa quantità."
#: fdmprinter.def.json
msgctxt "raft_surface_layers label"
msgid "Raft Top Layers"
-msgstr "Strati superiori del raft"
+msgstr "Layers superiori del raft"
#: fdmprinter.def.json
msgctxt "raft_surface_layers description"
msgid "The number of top layers on top of the 2nd raft layer. These are fully filled layers that the model sits on. 2 layers result in a smoother top surface than 1."
-msgstr "Numero di strati sulla parte superiore del secondo strato del raft. Si tratta di strati completamente riempiti su cui poggia il modello. 2 strati danno come risultato una superficie superiore più levigata rispetto ad 1 solo strato."
+msgstr "Numero di layers sulla parte superiore del secondo layer del raft. Si tratta di layers completamente riempiti su cui poggia il modello. 2 layers danno come risultato una superficie superiore più levigata rispetto ad 1 solo layer."
#: fdmprinter.def.json
msgctxt "raft_surface_thickness label"
msgid "Raft Top Layer Thickness"
-msgstr "Spessore dello strato superiore del raft"
+msgstr "Spessore del layer superiore del raft"
#: fdmprinter.def.json
msgctxt "raft_surface_thickness description"
msgid "Layer thickness of the top raft layers."
-msgstr "È lo spessore degli strati superiori del raft."
+msgstr "È lo spessore dei layers superiori del raft."
#: fdmprinter.def.json
msgctxt "raft_surface_line_width label"
@@ -3675,17 +3625,17 @@ msgstr "Indica la distanza tra le linee che costituiscono la maglia superiore de
#: fdmprinter.def.json
msgctxt "raft_interface_thickness label"
msgid "Raft Middle Thickness"
-msgstr "Spessore dello strato intermedio del raft"
+msgstr "Spessore del layer intermedio del raft"
#: fdmprinter.def.json
msgctxt "raft_interface_thickness description"
msgid "Layer thickness of the middle raft layer."
-msgstr "È lo spessore dello strato intermedio del raft."
+msgstr "È lo spessore del layer intermedio del raft."
#: fdmprinter.def.json
msgctxt "raft_interface_line_width label"
msgid "Raft Middle Line Width"
-msgstr "Larghezza delle linee dello strato intermedio del raft"
+msgstr "Larghezza delle linee del layer intermedio del raft"
#: fdmprinter.def.json
msgctxt "raft_interface_line_width description"
@@ -3695,12 +3645,12 @@ msgstr "Indica la larghezza delle linee dello strato intermedio del raft. Una ma
#: fdmprinter.def.json
msgctxt "raft_interface_line_spacing label"
msgid "Raft Middle Spacing"
-msgstr "Spaziatura dello strato intermedio del raft"
+msgstr "Spaziatura del layer intermedio del raft"
#: fdmprinter.def.json
msgctxt "raft_interface_line_spacing description"
msgid "The distance between the raft lines for the middle raft layer. The spacing of the middle should be quite wide, while being dense enough to support the top raft layers."
-msgstr "Indica la distanza fra le linee dello strato intermedio del raft. La spaziatura dello strato intermedio deve essere abbastanza ampia, ma al tempo stesso sufficientemente fitta da sostenere gli strati superiori del raft."
+msgstr "Indica la distanza fra le linee del layer intermedio del raft. La spaziatura del layer intermedio deve essere abbastanza ampia, ma al tempo stesso sufficientemente fitta da sostenere i layers superiori del raft."
#: fdmprinter.def.json
msgctxt "raft_base_thickness label"
@@ -3710,17 +3660,17 @@ msgstr "Spessore della base del raft"
#: fdmprinter.def.json
msgctxt "raft_base_thickness description"
msgid "Layer thickness of the base raft layer. This should be a thick layer which sticks firmly to the printer build plate."
-msgstr "Indica lo spessore dello strato di base del raft. Questo strato deve essere spesso per aderire saldamente al piano di stampa."
+msgstr "Indica lo spessore del layer di base del raft. Questo layer deve essere spesso per aderire saldamente al piano di stampa."
#: fdmprinter.def.json
msgctxt "raft_base_line_width label"
msgid "Raft Base Line Width"
-msgstr "Larghezza delle linee dello strato di base del raft"
+msgstr "Larghezza delle linee del layer di base del raft"
#: fdmprinter.def.json
msgctxt "raft_base_line_width description"
msgid "Width of the lines in the base raft layer. These should be thick lines to assist in build plate adhesion."
-msgstr "Indica la larghezza delle linee dello strato di base del raft. Le linee di questo strato devono essere spesse per favorire l'adesione al piano di stampa."
+msgstr "Indica la larghezza delle linee del layer di base del raft. Le linee di questo layer devono essere spesse per favorire l'adesione al piano di stampa."
#: fdmprinter.def.json
msgctxt "raft_base_line_spacing label"
@@ -3730,7 +3680,7 @@ msgstr "Spaziatura delle linee del raft"
#: fdmprinter.def.json
msgctxt "raft_base_line_spacing description"
msgid "The distance between the raft lines for the base raft layer. Wide spacing makes for easy removal of the raft from the build plate."
-msgstr "Indica la distanza tra le linee che costituiscono lo strato di base del raft. Un'ampia spaziatura favorisce la rimozione del raft dal piano di stampa."
+msgstr "Indica la distanza tra le linee che costituiscono il layer di base del raft. Un'ampia spaziatura favorisce la rimozione del raft dal piano di stampa."
#: fdmprinter.def.json
msgctxt "raft_speed label"
@@ -3750,7 +3700,7 @@ msgstr "Velocità di stampa parte superiore del raft"
#: fdmprinter.def.json
msgctxt "raft_surface_speed description"
msgid "The speed at which the top raft layers are printed. These should be printed a bit slower, so that the nozzle can slowly smooth out adjacent surface lines."
-msgstr "Indica la velocità alla quale sono stampati gli strati superiori del raft. La stampa di questi strati deve avvenire un po' più lentamente, in modo da consentire all'ugello di levigare lentamente le linee superficiali adiacenti."
+msgstr "Indica la velocità alla quale sono stampati i layers superiori del raft. La stampa di questi layers deve avvenire un po' più lentamente, in modo da consentire all'ugello di levigare lentamente le linee superficiali adiacenti."
#: fdmprinter.def.json
msgctxt "raft_interface_speed label"
@@ -3760,7 +3710,7 @@ msgstr "Velocità di stampa raft intermedio"
#: fdmprinter.def.json
msgctxt "raft_interface_speed description"
msgid "The speed at which the middle raft layer is printed. This should be printed quite slowly, as the volume of material coming out of the nozzle is quite high."
-msgstr "Indica la velocità alla quale viene stampato lo strato intermedio del raft. La sua stampa deve avvenire molto lentamente, considerato che il volume di materiale che fuoriesce dall'ugello è piuttosto elevato."
+msgstr "Indica la velocità alla quale viene stampato il layer intermedio del raft. La sua stampa deve avvenire molto lentamente, considerato che il volume di materiale che fuoriesce dall'ugello è piuttosto elevato."
#: fdmprinter.def.json
msgctxt "raft_base_speed label"
@@ -3790,7 +3740,7 @@ msgstr "Accelerazione di stampa parte superiore del raft"
#: fdmprinter.def.json
msgctxt "raft_surface_acceleration description"
msgid "The acceleration with which the top raft layers are printed."
-msgstr "Indica l’accelerazione alla quale vengono stampati gli strati superiori del raft."
+msgstr "Indica l’accelerazione alla quale vengono stampati i layers superiori del raft."
#: fdmprinter.def.json
msgctxt "raft_interface_acceleration label"
@@ -3800,7 +3750,7 @@ msgstr "Accelerazione di stampa raft intermedio"
#: fdmprinter.def.json
msgctxt "raft_interface_acceleration description"
msgid "The acceleration with which the middle raft layer is printed."
-msgstr "Indica l’accelerazione con cui viene stampato lo strato intermedio del raft."
+msgstr "Indica l’accelerazione con cui viene stampato il layer intermedio del raft."
#: fdmprinter.def.json
msgctxt "raft_base_acceleration label"
@@ -3810,7 +3760,7 @@ msgstr "Accelerazione di stampa della base del raft"
#: fdmprinter.def.json
msgctxt "raft_base_acceleration description"
msgid "The acceleration with which the base raft layer is printed."
-msgstr "Indica l’accelerazione con cui viene stampato lo strato di base del raft."
+msgstr "Indica l’accelerazione con cui viene stampato il layer di base del raft."
#: fdmprinter.def.json
msgctxt "raft_jerk label"
@@ -3830,7 +3780,7 @@ msgstr "Jerk di stampa parte superiore del raft"
#: fdmprinter.def.json
msgctxt "raft_surface_jerk description"
msgid "The jerk with which the top raft layers are printed."
-msgstr "Indica il jerk al quale vengono stampati gli strati superiori del raft."
+msgstr "Indica il jerk al quale vengono stampati i layers superiori del raft."
#: fdmprinter.def.json
msgctxt "raft_interface_jerk label"
@@ -3840,7 +3790,7 @@ msgstr "Jerk di stampa raft intermedio"
#: fdmprinter.def.json
msgctxt "raft_interface_jerk description"
msgid "The jerk with which the middle raft layer is printed."
-msgstr "Indica il jerk con cui viene stampato lo strato intermedio del raft."
+msgstr "Indica il jerk con cui viene stampato il layer intermedio del raft."
#: fdmprinter.def.json
msgctxt "raft_base_jerk label"
@@ -3850,7 +3800,7 @@ msgstr "Jerk di stampa della base del raft"
#: fdmprinter.def.json
msgctxt "raft_base_jerk description"
msgid "The jerk with which the base raft layer is printed."
-msgstr "Indica il jerk con cui viene stampato lo strato di base del raft."
+msgstr "Indica il jerk con cui viene stampato il layer di base del raft."
#: fdmprinter.def.json
msgctxt "raft_fan_speed label"
@@ -3870,7 +3820,7 @@ msgstr "Velocità della ventola per la parte superiore del raft"
#: fdmprinter.def.json
msgctxt "raft_surface_fan_speed description"
msgid "The fan speed for the top raft layers."
-msgstr "Indica la velocità di rotazione della ventola per gli strati superiori del raft."
+msgstr "Indica la velocità di rotazione della ventola per i layers superiori del raft."
#: fdmprinter.def.json
msgctxt "raft_interface_fan_speed label"
@@ -3880,7 +3830,7 @@ msgstr "Velocità della ventola per il raft intermedio"
#: fdmprinter.def.json
msgctxt "raft_interface_fan_speed description"
msgid "The fan speed for the middle raft layer."
-msgstr "Indica la velocità di rotazione della ventola per gli strati intermedi del raft."
+msgstr "Indica la velocità di rotazione della ventola per i layers intermedi del raft."
#: fdmprinter.def.json
msgctxt "raft_base_fan_speed label"
@@ -3890,7 +3840,7 @@ msgstr "Velocità della ventola per la base del raft"
#: fdmprinter.def.json
msgctxt "raft_base_fan_speed description"
msgid "The fan speed for the base raft layer."
-msgstr "Indica la velocità di rotazione della ventola per lo strato di base del raft."
+msgstr "Indica la velocità di rotazione della ventola per il layer di base del raft."
#: fdmprinter.def.json
msgctxt "dual label"
@@ -3905,7 +3855,7 @@ msgstr "Indica le impostazioni utilizzate per la stampa con estrusori multipli."
#: fdmprinter.def.json
msgctxt "prime_tower_enable label"
msgid "Enable Prime Tower"
-msgstr "Abilitazione torre di innesco"
+msgstr "Abilitazione Prime Tower"
#: fdmprinter.def.json
msgctxt "prime_tower_enable description"
@@ -3915,57 +3865,57 @@ msgstr "Stampa una torre accanto alla stampa che serve per innescare il material
#: fdmprinter.def.json
msgctxt "prime_tower_size label"
msgid "Prime Tower Size"
-msgstr "Dimensioni torre di innesco"
+msgstr "Dimensioni Prime Tower"
#: fdmprinter.def.json
msgctxt "prime_tower_size description"
msgid "The width of the prime tower."
-msgstr "Indica la larghezza della torre di innesco."
+msgstr "Indica la larghezza della Prime Tower."
#: fdmprinter.def.json
msgctxt "prime_tower_min_volume label"
msgid "Prime Tower Minimum Volume"
-msgstr "Volume minimo torre di innesco"
+msgstr "Volume minimo Prime Tower"
#: fdmprinter.def.json
msgctxt "prime_tower_min_volume description"
msgid "The minimum volume for each layer of the prime tower in order to purge enough material."
-msgstr "Il volume minimo per ciascuno strato della torre di innesco per scaricare materiale a sufficienza."
+msgstr "Il volume minimo per ciascun layer della Prime Tower per scaricare materiale a sufficienza."
#: fdmprinter.def.json
msgctxt "prime_tower_wall_thickness label"
msgid "Prime Tower Thickness"
-msgstr "Spessore torre di innesco"
+msgstr "Spessore Prime Tower"
#: fdmprinter.def.json
msgctxt "prime_tower_wall_thickness description"
msgid "The thickness of the hollow prime tower. A thickness larger than half the Prime Tower Minimum Volume will result in a dense prime tower."
-msgstr "Lo spessore della torre di innesco cava. Uno spessore superiore alla metà del volume minimo della torre di innesco genera una torre di innesco densa."
+msgstr "Lo spessore della Prime Tower cava. Uno spessore superiore alla metà del volume minimo della Prime Tower genera una torre di innesco densa."
#: fdmprinter.def.json
msgctxt "prime_tower_position_x label"
msgid "Prime Tower X Position"
-msgstr "Posizione X torre di innesco"
+msgstr "Posizione X Prime Tower"
#: fdmprinter.def.json
msgctxt "prime_tower_position_x description"
msgid "The x coordinate of the position of the prime tower."
-msgstr "Indica la coordinata X della posizione della torre di innesco."
+msgstr "Indica la coordinata X della posizione della Prime Tower."
#: fdmprinter.def.json
msgctxt "prime_tower_position_y label"
msgid "Prime Tower Y Position"
-msgstr "Posizione Y torre di innesco"
+msgstr "Posizione Y Prime Tower"
#: fdmprinter.def.json
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."
+msgstr "Indica la coordinata Y della posizione della Prime Tower."
#: fdmprinter.def.json
msgctxt "prime_tower_flow label"
msgid "Prime Tower Flow"
-msgstr "Flusso torre di innesco"
+msgstr "Flusso Prime Tower"
#: fdmprinter.def.json
msgctxt "prime_tower_flow description"
@@ -3975,17 +3925,17 @@ msgstr "Determina la compensazione del flusso: la quantità di materiale estruso
#: fdmprinter.def.json
msgctxt "prime_tower_wipe_enabled label"
msgid "Wipe Inactive Nozzle on Prime Tower"
-msgstr "Ugello pulitura inattiva sulla torre di innesco"
+msgstr "Ugello pulitura inattiva sulla Prime Tower"
#: fdmprinter.def.json
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."
+msgstr "Dopo la stampa della Prime Tower con un ugello, pulisce il materiale fuoriuscito dall’altro ugello sulla Prime Tower."
#: fdmprinter.def.json
msgctxt "dual_pre_wipe label"
msgid "Wipe Nozzle After Switch"
-msgstr "Ugello pulitura dopo commutazione"
+msgstr "Pulitura ugello dopo commutazione"
#: fdmprinter.def.json
msgctxt "dual_pre_wipe description"
@@ -3995,12 +3945,12 @@ msgstr "Dopo la commutazione dell’estrusore, pulire il materiale fuoriuscito d
#: fdmprinter.def.json
msgctxt "prime_tower_purge_volume label"
msgid "Prime Tower Purge Volume"
-msgstr "Volume di scarico torre di innesco"
+msgstr "Volume di scarico Prime Tower"
#: fdmprinter.def.json
msgctxt "prime_tower_purge_volume description"
msgid "Amount of filament to be purged when wiping on the prime tower. Purging is useful for compensating the filament lost by oozing during inactivity of the nozzle."
-msgstr "Quantità di filamento da scaricare durante la pulizia della torre di innesco. Lo scarico è utile per compensare il filamento perso per colatura durante l'inattività dell'ugello."
+msgstr "Quantità di filamento da scaricare durante la pulizia della Prime Tower. Lo scarico è utile per compensare il filamento perso per colatura durante l'inattività dell'ugello."
#: fdmprinter.def.json
msgctxt "ooze_shield_enabled label"
@@ -4082,16 +4032,6 @@ msgctxt "meshfix_keep_open_polygons description"
msgid "Normally Cura tries to stitch up small holes in the mesh and remove parts of a layer with big holes. Enabling this option keeps those parts which cannot be stitched. This option should be used as a last resort option when everything else fails to produce proper GCode."
msgstr "Di norma Cura cerca di \"ricucire\" piccoli fori nella maglia e di rimuovere le parti di uno strato che presentano grossi fori. Abilitando questa opzione, Cura mantiene quelle parti che non possono essere 'ricucite'. Questa opzione deve essere utilizzata come ultima risorsa quando non sia stato possibile produrre un corretto GCode in nessun altro modo."
-#: fdmprinter.def.json
-msgctxt "meshfix_maximum_resolution label"
-msgid "Maximum Resolution"
-msgstr "Risoluzione massima"
-
-#: fdmprinter.def.json
-msgctxt "meshfix_maximum_resolution description"
-msgid "The minimum size of a line segment after slicing. If you increase this, the mesh will have a lower resolution. This may allow the printer to keep up with the speed it has to process g-code and will increase slice speed by removing details of the mesh that it can't process anyway."
-msgstr "La dimensione minima di un segmento di linea dopo il sezionamento. Se tale dimensione aumenta, la maglia avrà una risoluzione inferiore. Questo può consentire alla stampante di mantenere la velocità per processare il g-code ed aumenterà la velocità di sezionamento eliminando i dettagli della maglia che non è comunque in grado di processare."
-
#: fdmprinter.def.json
msgctxt "multiple_mesh_overlap label"
msgid "Merged Meshes Overlap"
@@ -4150,7 +4090,7 @@ msgstr "Sequenza di stampa"
#: fdmprinter.def.json
msgctxt "print_sequence description"
msgid "Whether to print all models one layer at a time or to wait for one model to finish, before moving on to the next. One at a time mode is only possible if all models are separated in such a way that the whole print head can move in between and all models are lower than the distance between the nozzle and the X/Y axes."
-msgstr "Indica se stampare tutti i modelli uno strato alla volta o se attendere di terminare un modello prima di passare al successivo. La modalità 'uno per volta' è possibile solo se tutti i modelli sono separati in modo tale che l'intera testina di stampa possa muoversi tra di essi e se tutti i modelli sono più bassi della distanza tra l'ugello e gli assi X/Y."
+msgstr "Indica se stampare tutti i modelli uno layer alla volta o se attendere di terminare un modello prima di passare al successivo. La modalità 'uno per volta' è possibile solo se tutti i modelli sono separati in modo tale che l'intera testa di stampa possa muoversi tra di essi e se tutti i modelli sono più bassi della distanza tra l'ugello e gli assi X/Y."
#: fdmprinter.def.json
msgctxt "print_sequence option all_at_once"
@@ -4242,16 +4182,6 @@ msgctxt "support_mesh description"
msgid "Use this mesh to specify support areas. This can be used to generate support structure."
msgstr "Utilizzare questa maglia per specificare le aree di supporto. Può essere usata per generare una struttura di supporto."
-#: fdmprinter.def.json
-msgctxt "support_mesh_drop_down label"
-msgid "Drop Down Support Mesh"
-msgstr "Maglia supporto di discesa"
-
-#: fdmprinter.def.json
-msgctxt "support_mesh_drop_down description"
-msgid "Make support everywhere below the support mesh, so that there's no overhang in the support mesh."
-msgstr "Rappresenta il supporto ovunque sotto la maglia di supporto, in modo che in questa non vi siano punti a sbalzo."
-
#: fdmprinter.def.json
msgctxt "anti_overhang_mesh label"
msgid "Anti Overhang Mesh"
@@ -4315,7 +4245,7 @@ msgstr "Estrusione relativa"
#: fdmprinter.def.json
msgctxt "relative_extrusion description"
msgid "Use relative extrusion rather than absolute extrusion. Using relative E-steps makes for easier post-processing of the Gcode. However, it's not supported by all printers and it may produce very slight deviations in the amount of deposited material compared to absolute E-steps. Irrespective of this setting, the extrusion mode will always be set to absolute before any Gcode script is output."
-msgstr "Utilizza l'estrusione relativa invece di quella assoluta. L'utilizzo di fasi E relative facilita la post-elaborazione del codice G. Tuttavia, questa impostazione non è supportata da tutte le stampanti e può causare deviazioni molto piccole nella quantità di materiale depositato rispetto alle fasi E assolute. Indipendentemente da questa impostazione, la modalità estrusione sarà sempre impostata su assoluta prima che venga generato uno script in codice G."
+msgstr "Utilizza l'estrusione relativa invece di quella assoluta. L'utilizzo di fasi E relative facilita la post-elaborazione del Gcode. Tuttavia, questa impostazione non è supportata da tutte le stampanti e può causare deviazioni molto piccole nella quantità di materiale depositato rispetto agli E-steps assoluti. Indipendentemente da questa impostazione, la modalità estrusione sarà sempre impostata su assoluta prima che venga generato uno script Gcode."
#: fdmprinter.def.json
msgctxt "experimental label"
@@ -4328,14 +4258,194 @@ msgid "experimental!"
msgstr "sperimentale!"
#: fdmprinter.def.json
-msgctxt "optimize_wall_printing_order label"
-msgid "Optimize Wall Printing Order"
-msgstr "Ottimizzazione sequenza di stampa pareti"
+msgctxt "support_tree_enable label"
+msgid "Tree Support"
+msgstr "Supporto ad albero"
#: fdmprinter.def.json
-msgctxt "optimize_wall_printing_order description"
-msgid "Optimize the order in which walls are printed so as to reduce the number of retractions and the distance travelled. Most parts will benefit from this being enabled but some may actually take longer so please compare the print time estimates with and without optimization."
-msgstr "Ottimizza l'ordine in cui vengono stampate le pareti in modo da ridurre le retrazioni e la distanza percorsa. L'abilitazione di questa funzione porta vantaggi per la maggior parte dei pezzi, ma alcuni potrebbero richiedere un maggior tempo di esecuzione, per cui si consiglia di confrontare i tempi di stampa stimati con e senza ottimizzazione."
+msgctxt "support_tree_enable description"
+msgid "Generate a tree-like support with branches that support your print. This may reduce material usage and print time, but greatly increases slicing time."
+msgstr "Genera un supporto tipo albero con rami di sostegno della stampa. Questo può ridurre l’impiego di materiale e il tempo di stampa, ma aumenta notevolmente il tempo di sezionamento."
+
+#: fdmprinter.def.json
+msgctxt "support_tree_angle label"
+msgid "Tree Support Branch Angle"
+msgstr "Angolo ramo supporto ad albero"
+
+#: fdmprinter.def.json
+msgctxt "support_tree_angle description"
+msgid "The angle of the branches. Use a lower angle to make them more vertical and more stable. Use a higher angle to be able to have more reach."
+msgstr "L’angolo dei rami. Utilizzare un angolo minore per renderli più verticali e più stabili. Utilizzare un angolo maggiore per avere una portata maggiore."
+
+#: fdmprinter.def.json
+msgctxt "support_tree_branch_distance label"
+msgid "Tree Support Branch Distance"
+msgstr "Distanza ramo supporto ad albero"
+
+#: fdmprinter.def.json
+msgctxt "support_tree_branch_distance description"
+msgid "How far apart the branches need to be when they touch the model. Making this distance small will cause the tree support to touch the model at more points, causing better overhang but making support harder to remove."
+msgstr "La distanza tra i rami necessaria quando toccano il modello. Una distanza ridotta causa il contatto del supporto ad albero con il modello in più punti, generando migliore sovrapposizione ma rendendo più difficoltosa la rimozione del supporto."
+
+#: fdmprinter.def.json
+msgctxt "support_tree_branch_diameter label"
+msgid "Tree Support Branch Diameter"
+msgstr "Diametro ramo supporto ad albero"
+
+#: fdmprinter.def.json
+msgctxt "support_tree_branch_diameter description"
+msgid "The diameter of the thinnest branches of tree support. Thicker branches are more sturdy. Branches towards the base will be thicker than this."
+msgstr "Il diametro dei rami più sottili del supporto. I rami più spessi sono più resistenti. I rami verso la base avranno spessore maggiore."
+
+#: fdmprinter.def.json
+msgctxt "support_tree_branch_diameter_angle label"
+msgid "Tree Support Branch Diameter Angle"
+msgstr "Angolo diametro ramo supporto ad albero"
+
+#: fdmprinter.def.json
+msgctxt "support_tree_branch_diameter_angle description"
+msgid "The angle of the branches' diameter as they gradually become thicker towards the bottom. An angle of 0 will cause the branches to have uniform thickness over their length. A bit of an angle can increase stability of the tree support."
+msgstr "L’angolo del diametro dei rami con il graduale ispessimento verso il fondo. Un angolo pari a 0 genera rami con spessore uniforme sull’intera lunghezza. Un angolo minimo può aumentare la stabilità del supporto ad albero."
+
+#: fdmprinter.def.json
+msgctxt "support_tree_collision_resolution label"
+msgid "Tree Support Collision Resolution"
+msgstr "Risoluzione collisione supporto ad albero"
+
+#: fdmprinter.def.json
+msgctxt "support_tree_collision_resolution description"
+msgid "Resolution to compute collisions with to avoid hitting the model. Setting this lower will produce more accurate trees that fail less often, but increases slicing time dramatically."
+msgstr "Risoluzione per calcolare le collisioni per evitare di colpire il modello. L’impostazione a un valore basso genera alberi più accurati che si rompono meno sovente, ma aumenta notevolmente il tempo di sezionamento."
+
+#: fdmprinter.def.json
+msgctxt "support_tree_wall_thickness label"
+msgid "Tree Support Wall Thickness"
+msgstr "Spessore delle pareti supporto ad albero"
+
+#: fdmprinter.def.json
+msgctxt "support_tree_wall_thickness description"
+msgid "The thickness of the walls of the branches of tree support. Thicker walls take longer to print but don't fall over as easily."
+msgstr "Lo spessore delle pareti dei rami del supporto ad albero. Le pareti più spesse hanno un tempo di stampa superiore ma non cadono facilmente."
+
+#: fdmprinter.def.json
+msgctxt "support_tree_wall_count label"
+msgid "Tree Support Wall Line Count"
+msgstr "Numero delle linee perimetrali supporto ad albero"
+
+#: fdmprinter.def.json
+msgctxt "support_tree_wall_count description"
+msgid "The number of walls of the branches of tree support. Thicker walls take longer to print but don't fall over as easily."
+msgstr "Il numero di pareti dei rami del supporto ad albero. Le pareti più spesse hanno un tempo di stampa superiore ma non cadono facilmente."
+
+#: fdmprinter.def.json
+msgctxt "slicing_tolerance label"
+msgid "Slicing Tolerance"
+msgstr "Tolleranza di sezionamento"
+
+#: fdmprinter.def.json
+msgctxt "slicing_tolerance description"
+msgid "How to slice layers with diagonal surfaces. The areas of a layer can be generated based on where the middle of the layer intersects the surface (Middle). Alternatively each layer can have the areas which fall inside of the volume throughout the height of the layer (Exclusive) or a layer has the areas which fall inside anywhere within the layer (Inclusive). Exclusive retains the most details, Inclusive makes for the best fit and Middle takes the least time to process."
+msgstr "Modalità di sezionamento di strati con superfici diagonali. Le aree di uno strato possono essere generate in base al punto in cui la parte intermedia dello strato interseca la superficie (intermedia). In alternativa le aree di ciascuno strato possono ricadere all'interno del volume per tutta l'altezza dello strato (Esclusiva) ovvero possono cadere in qualsiasi punto all'interno dello strato (Inclusiva). La tolleranza esclusiva mantiene il maggior numero di dettagli, la tolleranza inclusiva è la più idonea, mentre la tolleranza intermedia richiede il minor tempo di processo."
+
+#: fdmprinter.def.json
+msgctxt "slicing_tolerance option middle"
+msgid "Middle"
+msgstr "Intermedia"
+
+#: fdmprinter.def.json
+msgctxt "slicing_tolerance option exclusive"
+msgid "Exclusive"
+msgstr "Esclusiva"
+
+#: fdmprinter.def.json
+msgctxt "slicing_tolerance option inclusive"
+msgid "Inclusive"
+msgstr "Inclusiva"
+
+#: fdmprinter.def.json
+msgctxt "roofing_line_width label"
+msgid "Top Surface Skin Line Width"
+msgstr "Larghezza linea rivestimento superficie superiore"
+
+#: fdmprinter.def.json
+msgctxt "roofing_line_width description"
+msgid "Width of a single line of the areas at the top of the print."
+msgstr "Larghezza di un singola linea delle aree nella parte superiore della stampa"
+
+#: fdmprinter.def.json
+msgctxt "roofing_pattern label"
+msgid "Top Surface Skin Pattern"
+msgstr "Configurazione del rivestimento superficie superiore"
+
+#: fdmprinter.def.json
+msgctxt "roofing_pattern description"
+msgid "The pattern of the top most layers."
+msgstr "Configurazione dei layers superiori."
+
+#: fdmprinter.def.json
+msgctxt "roofing_pattern option lines"
+msgid "Lines"
+msgstr "Linee"
+
+#: fdmprinter.def.json
+msgctxt "roofing_pattern option concentric"
+msgid "Concentric"
+msgstr "Concentrica"
+
+#: fdmprinter.def.json
+msgctxt "roofing_pattern option zigzag"
+msgid "Zig Zag"
+msgstr "Zig Zag"
+
+#: fdmprinter.def.json
+msgctxt "roofing_angles label"
+msgid "Top Surface Skin Line Directions"
+msgstr "Direzioni linea rivestimento superficie superiore"
+
+#: fdmprinter.def.json
+msgctxt "roofing_angles description"
+msgid "A list of integer line directions to use when the top surface skin layers use the lines or zig zag pattern. 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 traditional default angles (45 and 135 degrees)."
+msgstr "Un elenco di direzioni linee intere da usare quando i layers rivestimento superficie superiore utilizzano le linee o la configurazione zig zag. Gli elementi dall’elenco sono utilizzati in sequenza con il progredire dei layers e, al raggiungimento della fine dell’elenco, la sequenza ricomincia dall’inizio. Le voci elencate sono separate da virgole e l’intero elenco è racchiuso tra parentesi quadre. L’elenco predefinito è vuoto, vale a dire che utilizza i valori angolari predefiniti (45 e 135 gradi)."
+
+#: fdmprinter.def.json
+msgctxt "infill_enable_travel_optimization label"
+msgid "Infill Travel Optimization"
+msgstr "Ottimizzazione spostamenti riempimento"
+
+#: fdmprinter.def.json
+msgctxt "infill_enable_travel_optimization description"
+msgid "When enabled, the order in which the infill lines are printed is optimized to reduce the distance travelled. The reduction in travel time achieved very much depends on the model being sliced, infill pattern, density, etc. Note that, for some models that have many small areas of infill, the time to slice the model may be greatly increased."
+msgstr "Quando abilitato, l’ordine di stampa delle linee di riempimento viene ottimizzato per ridurre la distanza percorsa. La riduzione del tempo di spostamento ottenuta dipende in particolare dal modello sezionato, dalla configurazione di riempimento, dalla densità, ecc. Si noti che, per alcuni modelli che hanno piccole aree di riempimento, il tempo di sezionamento del modello può aumentare notevolmente."
+
+#: fdmprinter.def.json
+msgctxt "material_flow_dependent_temperature label"
+msgid "Auto Temperature"
+msgstr "Temperatura automatica"
+
+#: fdmprinter.def.json
+msgctxt "material_flow_dependent_temperature description"
+msgid "Change the temperature for each layer automatically with the average flow speed of that layer."
+msgstr "Modifica automaticamente la temperatura per ciascun layer con la velocità media del flusso per tale strato."
+
+#: fdmprinter.def.json
+msgctxt "material_flow_temp_graph label"
+msgid "Flow Temperature Graph"
+msgstr "Grafico della temperatura del flusso"
+
+#: fdmprinter.def.json
+msgctxt "material_flow_temp_graph description"
+msgid "Data linking material flow (in mm3 per second) to temperature (degrees Celsius)."
+msgstr "Collegamento dei dati di flusso del materiale (in mm3 al secondo) alla temperatura (in °C)."
+
+#: fdmprinter.def.json
+msgctxt "meshfix_maximum_resolution label"
+msgid "Maximum Resolution"
+msgstr "Risoluzione massima"
+
+#: fdmprinter.def.json
+msgctxt "meshfix_maximum_resolution description"
+msgid "The minimum size of a line segment after slicing. If you increase this, the mesh will have a lower resolution. This may allow the printer to keep up with the speed it has to process g-code and will increase slice speed by removing details of the mesh that it can't process anyway."
+msgstr "La dimensione minima di un segmento di linea dopo il sezionamento. Se tale dimensione aumenta, la maglia avrà una risoluzione inferiore. Questo può consentire alla stampante di mantenere la velocità per processare il g-code ed aumenterà la velocità di sezionamento eliminando i dettagli della maglia che non è comunque in grado di processare."
#: fdmprinter.def.json
msgctxt "support_skip_some_zags label"
@@ -4815,7 +4925,7 @@ msgstr "Ritardo tra due segmenti orizzontali WP"
#: fdmprinter.def.json
msgctxt "wireframe_flat_delay description"
msgid "Delay time between two horizontal segments. Introducing such a delay can cause better adhesion to previous layers at the connection points, while too long delays cause sagging. Only applies to Wire Printing."
-msgstr "Indica il tempo di ritardo tra due segmenti orizzontali. Introducendo un tale ritardo si può ottenere una migliore adesione agli strati precedenti in corrispondenza dei punti di collegamento, mentre ritardi troppo prolungati provocano cedimenti. Applicabile solo alla funzione Wire Printing."
+msgstr "Indica il tempo di ritardo tra due segmenti orizzontali. Introducendo un tale ritardo si può ottenere una migliore adesione ai layers precedenti in corrispondenza dei punti di collegamento, mentre ritardi troppo prolungati provocano cedimenti. Applicabile solo alla funzione Wire Printing."
#: fdmprinter.def.json
msgctxt "wireframe_up_half_speed label"
@@ -4837,7 +4947,7 @@ msgstr "Dimensione dei nodi WP"
#: fdmprinter.def.json
msgctxt "wireframe_top_jump description"
msgid "Creates a small knot at the top of an upward line, so that the consecutive horizontal layer has a better chance to connect to it. Only applies to Wire Printing."
-msgstr "Crea un piccolo nodo alla sommità di una linea verticale verso l'alto, in modo che lo strato orizzontale consecutivo abbia una migliore possibilità di collegarsi ad essa. Applicabile solo alla funzione Wire Printing."
+msgstr "Crea un piccolo nodo alla sommità di una linea verticale verso l'alto, in modo che il layer orizzontale consecutivo abbia una migliore possibilità di collegarsi ad essa. Applicabile solo alla funzione Wire Printing."
#: fdmprinter.def.json
msgctxt "wireframe_fall_down label"
@@ -4867,7 +4977,7 @@ msgstr "Strategia WP"
#: fdmprinter.def.json
msgctxt "wireframe_strategy description"
msgid "Strategy for making sure two consecutive layers connect at each connection point. Retraction lets the upward lines harden in the right position, but may cause filament grinding. A knot can be made at the end of an upward line to heighten the chance of connecting to it and to let the line cool; however, it may require slow printing speeds. Another strategy is to compensate for the sagging of the top of an upward line; however, the lines won't always fall down as predicted."
-msgstr "Strategia per garantire il collegamento di due strati consecutivi ad ogni punto di connessione. La retrazione consente l'indurimento delle linee verticali verso l'alto nella giusta posizione, ma può causare la deformazione del filamento. È possibile realizzare un nodo all'estremità di una linea verticale verso l'alto per accrescere la possibilità di collegamento e lasciarla raffreddare; tuttavia ciò può richiedere velocità di stampa ridotte. Un'altra strategia consiste nel compensare il cedimento della parte superiore di una linea verticale verso l'alto; tuttavia le linee non sempre ricadono come previsto."
+msgstr "Strategia per garantire il collegamento di due layers consecutivi ad ogni punto di connessione. La retrazione consente l'indurimento delle linee verticali verso l'alto nella giusta posizione, ma può causare la deformazione del filamento. È possibile realizzare un nodo all'estremità di una linea verticale verso l'alto per accrescere la possibilità di collegamento e lasciarla raffreddare; tuttavia ciò può richiedere velocità di stampa ridotte. Un'altra strategia consiste nel compensare il cedimento della parte superiore di una linea verticale verso l'alto; tuttavia le linee non sempre ricadono come previsto."
#: fdmprinter.def.json
msgctxt "wireframe_strategy option compensate"
@@ -4934,6 +5044,46 @@ msgctxt "wireframe_nozzle_clearance description"
msgid "Distance between the nozzle and horizontally downward lines. Larger clearance results in diagonally downward lines with a less steep angle, which in turn results in less upward connections with the next layer. Only applies to Wire Printing."
msgstr "Indica la distanza tra l'ugello e le linee diagonali verso il basso. Un maggior gioco risulta in linee diagonali verso il basso con un minor angolo di inclinazione, cosa che a sua volta si traduce in meno collegamenti verso l'alto con lo strato successivo. Applicabile solo alla funzione Wire Printing."
+#: fdmprinter.def.json
+msgctxt "adaptive_layer_height_enabled label"
+msgid "Use adaptive layers"
+msgstr "Uso di layers adattivi"
+
+#: fdmprinter.def.json
+msgctxt "adaptive_layer_height_enabled description"
+msgid "Adaptive layers computes the layer heights depending on the shape of the model."
+msgstr "I layers adattivi calcolano l’altezza dei layers in base alla forma del modello."
+
+#: fdmprinter.def.json
+msgctxt "adaptive_layer_height_variation label"
+msgid "Adaptive layers maximum variation"
+msgstr "Variazione massima layers adattivi"
+
+#: fdmprinter.def.json
+msgctxt "adaptive_layer_height_variation description"
+msgid "The maximum allowed height different from the base layer height in mm."
+msgstr "La differenza di altezza massima rispetto all’altezza del layer di base in mm."
+
+#: fdmprinter.def.json
+msgctxt "adaptive_layer_height_variation_step label"
+msgid "Adaptive layers variation step size"
+msgstr "Dimensione variazione layers adattivi"
+
+#: fdmprinter.def.json
+msgctxt "adaptive_layer_height_variation_step description"
+msgid "The difference in height of the next layer height compared to the previous one."
+msgstr "La differenza in altezza del layer successivo rispetto al precedente."
+
+#: fdmprinter.def.json
+msgctxt "adaptive_layer_height_threshold label"
+msgid "Adaptive layers threshold"
+msgstr "Soglia layers adattivi"
+
+#: fdmprinter.def.json
+msgctxt "adaptive_layer_height_threshold description"
+msgid "Threshold whether to use a smaller layer or not. This number is compared to the tan of the steepest slope in a layer."
+msgstr "Soglia per l’utilizzo o meno di un layer di dimensioni minori. Questo numero è confrontato al valore dell’inclinazione più ripida di un layer."
+
#: fdmprinter.def.json
msgctxt "command_line_settings label"
msgid "Command Line Settings"
@@ -4942,7 +5092,7 @@ msgstr "Impostazioni riga di comando"
#: fdmprinter.def.json
msgctxt "command_line_settings description"
msgid "Settings which are only used if CuraEngine isn't called from the Cura frontend."
-msgstr "Impostazioni utilizzate solo se CuraEngine non è chiamato dalla parte anteriore di Cura."
+msgstr "Impostazioni utilizzate solo se CuraEngine non è chiamato dal frontend di Cura."
#: fdmprinter.def.json
msgctxt "center_object label"
@@ -4994,13 +5144,33 @@ 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 "infill_offset_x description"
+#~ msgid "The infill pattern is offset this distance along the X axis."
+#~ msgstr "Il riempimento si scosta di questa distanza lungo l'asse X."
+
+#~ msgctxt "infill_offset_y description"
+#~ msgid "The infill pattern is offset this distance along the Y axis."
+#~ msgstr "Il riempimento si scosta di questa distanza lungo l'asse Y."
+
+#~ msgctxt "infill_overlap description"
+#~ msgid "The amount of overlap between the infill and the walls. A slight overlap allows the walls to connect firmly to the infill."
+#~ msgstr "Indica la quantità di sovrapposizione tra il riempimento e le pareti. Una leggera sovrapposizione consente il saldo collegamento delle pareti al riempimento."
+
+#~ msgctxt "skin_overlap description"
+#~ msgid "The amount of overlap between the skin and the walls as a percentage of the 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. 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 "material_bed_temperature description"
+#~ msgid "The temperature used for the heated build plate. If this is 0, the bed will not heat up for this print."
+#~ msgstr "Indica la temperatura usata per il piano di stampa riscaldato. Se è 0, il piano non si riscalda per questa stampa."
+
#~ msgctxt "wall_x_extruder_nr label"
#~ msgid "Inner Walls Extruder"
#~ msgstr "Estrusore parete interna"
#~ 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, cubic, octet, quarter cubic 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 zig zag su strati alternati riduce il costo del materiale. Le configurazioni a griglia, triangolo, a cubo, ottagonale, a quarto di cubo e concentrica comportano la stampa completa in ogni strato. Il riempimento a cubi, a quarto di cubo e a ottagonale cambia a ogni strato per consentire una distribuzione più uniforme della resistenza in ogni direzione."
+#~ msgstr "Configurazione del materiale di riempimento della stampa. Il riempimento a linea e zig zag su layers alternati riduce il costo del materiale. Le configurazioni a griglia, triangolo, a cubo, ottagonale, a quarto di cubo e concentrica comportano la stampa completa in ogni layer. Il riempimento a cubi, a quarto di cubo e a ottagonale cambia a ogni layer per consentire una distribuzione più uniforme della resistenza in ogni direzione."
#~ msgctxt "zig_zaggify_infill description"
#~ msgid "Connect the ends where the infill pattern meets the inner wall using a lines which follows the shape of the inner wall. Enabling this setting can make the infill adhere to the walls better and reduces the effects on infill on the quality of vertical surfaces. Disabling this setting reduces the amount of material used."
@@ -5016,19 +5186,19 @@ msgstr "Matrice di rotazione da applicare al modello quando caricato dal file."
#~ msgctxt "z_offset_layer_0 label"
#~ msgid "Initial Layer Z Offset"
-#~ msgstr "Scostamento Z strato iniziale"
+#~ msgstr "Scostamento Z layer iniziale"
#~ msgctxt "z_offset_layer_0 description"
#~ msgid "The extruder is offset from the normal height of the first layer by this amount. It can be positive (raised) or negative (lowered). Some filament types adhere to the build plate better if the extruder is raised slightly."
-#~ msgstr "L'estrusore viene posizionato ad una distanza dall'altezza normale del primo strato pari al valore indicato. Questo scostamento può essere positivo (più in alto) o negativo (più in basso). Alcuni tipi di filamento aderiscono meglio al piano di stampa se l'estrusore viene leggermente sollevato."
+#~ msgstr "L'estrusore viene posizionato ad una distanza dall'altezza normale del primo layer pari al valore indicato. Questo scostamento può essere positivo (più in alto) o negativo (più in basso). Alcuni tipi di filamento aderiscono meglio al piano di stampa se l'estrusore viene leggermente sollevato."
#~ msgctxt "z_offset_taper_layers label"
#~ msgid "Z Offset Taper Layers"
-#~ msgstr "Scostamento Z strati di rastremazione"
+#~ msgstr "Scostamento Z layers di rastremazione"
#~ msgctxt "z_offset_taper_layers description"
#~ msgid "When non-zero, the Z offset is reduced to 0 over that many layers. A value of 0 means that the Z offset remains constant for all the layers in the print."
-#~ msgstr "Se diverso da zero, lo scostamento Z viene ridotto a 0 entro il numero di strati indicato. Un valore di 0 indica che lo scostamento Z rimane costante per tutti gli strati di stampa."
+#~ msgstr "Se diverso da zero, lo scostamento Z viene ridotto a 0 entro il numero di layers indicato. Un valore di 0 indica che lo scostamento Z rimane costante per tutti i layers di stampa."
#~ msgctxt "raft_smoothing description"
#~ msgid "This setting control how much inner corners in the raft outline are rounded. Inward corners are rounded to a semi circle with a radius equal to the value given here. This setting also removes holes in the raft outline which are smaller than such a circle."
@@ -5036,7 +5206,7 @@ msgstr "Matrice di rotazione da applicare al modello quando caricato dal file."
#~ 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, cubic, tetrahedral and concentric patterns are fully printed every layer. Cubic and tetrahedral infill change with every layer to provide a more equal distribution of strength over each direction."
-#~ msgstr "Indica la 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, triangolo, cubo, tetraedriche e concentriche sono stampate completamente su ogni strato. Il riempimento delle configurazioni cubiche e tetraedriche cambia ad ogni strato per fornire una distribuzione più uniforme della forza su ciascuna direzione."
+#~ msgstr "Indica la configurazione del materiale di riempimento della stampa. Il riempimento a linea e a zig zag cambia direzione su layers alternati, riducendo il costo del materiale. Le configurazioni a griglia, triangolo, cubo, tetraedriche e concentriche sono stampate completamente su ogni layers. Il riempimento delle configurazioni cubiche e tetraedriche cambia ad ogni strato per fornire una distribuzione più uniforme della forza su ciascuna direzione."
#~ msgctxt "infill_pattern option tetrahedral"
#~ msgid "Tetrahedral"
@@ -5044,27 +5214,27 @@ msgstr "Matrice di rotazione da applicare al modello quando caricato dal file."
#~ msgctxt "expand_skins_into_infill label"
#~ msgid "Expand Skins Into Infill"
-#~ msgstr "Prolunga rivestimenti esterni nel riempimento"
+#~ msgstr "Estende rivestimenti esterni nel riempimento"
#~ msgctxt "expand_skins_into_infill description"
#~ msgid "Expand skin areas of top and/or bottom skin of flat surfaces. By default, skins stop under the wall lines that surround infill but this can lead to holes appearing when the infill density is low. This setting extends the skins beyond the wall lines so that the infill on the next layer rests on skin."
-#~ msgstr "Prolunga le aree di rivestimento esterno superiori e/o inferiori delle superfici piatte. Per default, i rivestimenti esterni si interrompono sotto le linee delle pareti circostanti il riempimento, ma questo può generare la comparsa di fori quando la densità del riempimento è bassa. Questa impostazione prolunga i rivestimenti esterni oltre le linee delle pareti in modo che il riempimento sullo strato successivo appoggi sul rivestimento esterno."
+#~ msgstr "Estende le aree di rivestimento esterno superiori e/o inferiori delle superfici piatte. Per default, i rivestimenti esterni si interrompono sotto le linee delle pareti circostanti il riempimento, ma questo può generare la comparsa di fori quando la densità del riempimento è bassa. Questa impostazione prolunga i rivestimenti esterni oltre le linee delle pareti in modo che il riempimento sullo strato successivo appoggi sul rivestimento esterno."
#~ msgctxt "expand_upper_skins label"
#~ msgid "Expand Top Skins Into Infill"
-#~ msgstr "Prolunga rivestimenti esterni superiori nel riempimento"
+#~ msgstr "Estendi rivestimenti esterni superiori nel riempimento"
#~ msgctxt "expand_upper_skins description"
#~ msgid "Expand the top skin areas (areas with air above) so that they support infill above."
-#~ msgstr "Prolunga le aree di rivestimento esterno superiori (aree con aria al di sopra) in modo che supportino il riempimento sovrastante."
+#~ msgstr "Estendi le aree di rivestimento esterno superiori (aree con aria al di sopra) in modo che supportino il riempimento sovrastante."
#~ msgctxt "expand_lower_skins label"
#~ msgid "Expand Bottom Skins Into Infill"
-#~ msgstr "Prolunga rivestimenti esterni inferiori nel riempimento"
+#~ msgstr "Estendi rivestimenti esterni inferiori nel riempimento"
#~ msgctxt "expand_lower_skins description"
#~ msgid "Expand the bottom skin areas (areas with air below) so that they are anchored by the infill layers above and below."
-#~ msgstr "Prolunga aree rivestimento esterno inferiori (aree con aria al di sotto) in modo che siano ancorate dagli strati di riempimento sovrastanti e sottostanti."
+#~ msgstr "Estendi aree rivestimento esterno inferiori (aree con aria al di sotto) in modo che siano ancorate dai layers di riempimento sovrastanti e sottostanti."
#~ msgctxt "expand_skins_expand_distance description"
#~ msgid "The distance the skins are expanded into the infill. The default distance is enough to bridge the gap between the infill lines and will stop holes appearing in the skin where it meets the wall when the infill density is low. A smaller distance will often be sufficient."
@@ -5160,19 +5330,19 @@ msgstr "Matrice di rotazione da applicare al modello quando caricato dal file."
#~ msgctxt "expand_upper_skins label"
#~ msgid "Expand Upper Skins"
-#~ msgstr "Prolunga rivestimenti esterni superiori"
+#~ msgstr "Estendi rivestimenti esterni superiori"
#~ msgctxt "expand_upper_skins description"
#~ msgid "Expand upper skin areas (areas with air above) so that they support infill above."
-#~ msgstr "Prolunga le aree di rivestimento esterno superiori (aree con aria al di sopra) in modo che supportino il riempimento sovrastante."
+#~ msgstr "Estendi le aree di rivestimento esterno superiori (aree con aria al di sopra) in modo che supportino il riempimento sovrastante."
#~ msgctxt "expand_lower_skins label"
#~ msgid "Expand Lower Skins"
-#~ msgstr "Prolunga rivestimenti esterni inferiori"
+#~ msgstr "Estendi rivestimenti esterni inferiori"
#~ msgctxt "expand_lower_skins description"
#~ msgid "Expand lower skin areas (areas with air below) so that they are anchored by the infill layers above and below."
-#~ msgstr "Prolunga aree rivestimento esterno inferiori (aree con aria al di sotto) in modo che siano ancorate dagli strati di riempimento sovrastanti e sottostanti."
+#~ msgstr "Estendi aree rivestimento esterno inferiori (aree con aria al di sotto) in modo che siano ancorate dagli strati di riempimento sovrastanti e sottostanti."
#~ msgctxt "speed_support_interface description"
#~ msgid "The speed at which the roofs and bottoms of support are printed. Printing the them at lower speeds can improve overhang quality."
@@ -5196,7 +5366,7 @@ msgstr "Matrice di rotazione da applicare al modello quando caricato dal file."
#~ msgctxt "support_interface_extruder_nr description"
#~ msgid "The extruder train to use for printing the roofs and bottoms of the support. This is used in multi-extrusion."
-#~ msgstr "Il treno estrusore utilizzato per la stampa delle parti superiori e inferiori del supporto. Utilizzato nell’estrusione multipla."
+#~ msgstr "Il blocco estrusore utilizzato per la stampa delle parti superiori e inferiori del supporto. Utilizzato nell’estrusione multipla."
#~ msgctxt "support_bottom_stair_step_height description"
#~ msgid "The height of the steps of the stair-like bottom of support resting on the model. A low value makes the support harder to remove, but too high values can lead to unstable support structures."
@@ -5204,11 +5374,11 @@ msgstr "Matrice di rotazione da applicare al modello quando caricato dal file."
#~ msgctxt "support_bottom_height label"
#~ msgid "Support Bottom Thickness"
-#~ msgstr "Spessore degli strati inferiori del supporto"
+#~ msgstr "Spessore dei layers inferiori del supporto"
#~ msgctxt "support_bottom_height description"
#~ msgid "The thickness of the support bottoms. This controls the number of dense layers are printed on top of places of a model on which support rests."
-#~ msgstr "Indica lo spessore degli strati inferiori del supporto. Questo controlla il numero di strati fitti stampati sulla sommità dei punti di un modello su cui appoggia un supporto."
+#~ msgstr "Indica lo spessore dei layers inferiori del supporto. Questo controlla il numero di slayers fitti stampati sulla sommità dei punti di un modello su cui appoggia un supporto."
#~ msgctxt "support_interface_skip_height description"
#~ msgid "When checking where there's model above the support, take steps of the given height. Lower values will slice slower, while higher values may cause normal support to be printed in some places where there should have been support interface."
diff --git a/resources/i18n/ja_JP/cura.po b/resources/i18n/ja_JP/cura.po
index 01b39b3229..11e6f08883 100644
--- a/resources/i18n/ja_JP/cura.po
+++ b/resources/i18n/ja_JP/cura.po
@@ -1,24 +1,24 @@
# Cura
-# Copyright (C) 2017 Ultimaker
+# Copyright (C) 2018 Ultimaker
# This file is distributed under the same license as the Cura package.
-# Ruben Dulek , 2017.
-#
+# Ruben Dulek , 2018.
+#
msgid ""
msgstr ""
-"Project-Id-Version: Cura 3.0\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2017-11-21 16:58+0100\n"
-"PO-Revision-Date: 2017-11-30 13:05+0100\n"
-"Last-Translator: \n"
-"Language-Team: TEAM\n"
-"Language: xx_XX\n"
+"Project-Id-Version: Cura 3.2\n"
+"Report-Msgid-Bugs-To: r.dulek@ultimaker.com\n"
+"POT-Creation-Date: 2018-01-29 09:48+0000\n"
+"PO-Revision-Date: 2018-02-10 04:58+0900\n"
+"Last-Translator: Brule \n"
+"Language-Team: 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 1.8.7.1\n"
+"X-Generator: Poedit 2.0.4\n"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.py:29
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.py:26
msgctxt "@action"
msgid "Machine Settings"
msgstr "プリンターの設定"
@@ -55,12 +55,11 @@ msgstr "Doodle3D Connectに接続する"
#: /home/ruben/Projects/Cura/plugins/Doodle3D-cura-plugin/Doodle3D/D3DCloudPrintOutputDevicePlugin.py:87
#: /home/ruben/Projects/Cura/plugins/Doodle3D-cura-plugin/Doodle3D/D3DCloudPrintOutputDevicePlugin.py:155
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:874
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:646
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:875
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:659
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/DiscoverUM3Action.qml:370
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/PrintWindow.qml:78
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/ConfigDialog.qml:104
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/ExportSTLUI.qml:99
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:355
#: /home/ruben/Projects/Cura/plugins/ImageReader/ConfigUI.qml:188
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:376
#: /home/ruben/Projects/Cura/plugins/PluginBrowser/PluginBrowser.qml:139
@@ -100,7 +99,7 @@ msgctxt "@info:tooltip"
msgid "Open the Doodle3D Connect web interface"
msgstr "Doodle3D Connect web interfaceを開く"
-#: /home/ruben/Projects/Cura/plugins/ChangeLogPlugin/ChangeLog.py:34
+#: /home/ruben/Projects/Cura/plugins/ChangeLogPlugin/ChangeLog.py:33
msgctxt "@item:inmenu"
msgid "Show Changelog"
msgstr "Changelogの表示"
@@ -117,78 +116,83 @@ msgctxt "@info:status"
msgid "Profile has been flattened & activated."
msgstr "プロファイルが平らになり、アクティベートされました。"
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:26
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:27
msgctxt "@item:inmenu"
msgid "USB printing"
msgstr "USBプリンティング"
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:27
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:28
msgctxt "@action:button Preceded by 'Ready to'."
msgid "Print via USB"
msgstr "USBを使ってプリントする"
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:28
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:29
msgctxt "@info:tooltip"
msgid "Print via USB"
msgstr "USBを使ってプリントする"
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:30
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:31
msgctxt "@info:status"
msgid "Connected via USB"
msgstr "USBにて接続する"
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:154
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:183
msgctxt "@info:status"
msgid "Unable to start a new job because the printer is busy or not connected."
msgstr "新しいプリントジョブをはじめることができません。プリンターが使用中または接続できていません。"
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:154
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:183
msgctxt "@info:title"
msgid "Printer Unavailable"
msgstr "プリンターが利用できません"
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:457
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:485
msgctxt "@info:status"
msgid "This printer does not support USB printing because it uses UltiGCode flavor."
msgstr "UltiGCodeを使用中のため、USBからのプリントができません。"
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:457
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:485
msgctxt "@info:title"
msgid "USB Printing"
msgstr "USBプリント"
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:461
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:489
msgctxt "@info:status"
msgid "Unable to start a new job because the printer does not support usb printing."
msgstr "USBでの印刷ができないため、新しいプリントジョブができません。"
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:461
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDeviceManager.py:108
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:489
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDeviceManager.py:103
#: /home/ruben/Projects/Cura/plugins/RemovableDriveOutputDevice/RemovableDriveOutputDevice.py:146
#: /home/ruben/Projects/Cura/plugins/RemovableDriveOutputDevice/RemovableDriveOutputDevice.py:158
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:945
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1349
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1417
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:946
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1418
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1496
msgctxt "@info:title"
msgid "Warning"
msgstr "警告"
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDeviceManager.py:108
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDeviceManager.py:103
msgctxt "@info"
msgid "Unable to update firmware because there are no printers connected."
msgstr "プリンターが未接続のため、ファームウェアをアップデートできません。"
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDeviceManager.py:122
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDeviceManager.py:117
#, python-format
msgctxt "@info"
msgid "Could not find firmware required for the printer at %s."
msgstr "プリンター(%s)に必要なファームウェアを探せませんでした。"
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDeviceManager.py:122
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDeviceManager.py:117
msgctxt "@info:title"
msgid "Printer Firmware"
msgstr "ファームウェア"
+#: /home/ruben/Projects/Cura/plugins/PrepareStage/__init__.py:12
+msgctxt "@item:inmenu"
+msgid "Prepare"
+msgstr "準備する"
+
#: /home/ruben/Projects/Cura/plugins/RemovableDriveOutputDevice/RemovableDriveOutputDevice.py:23
msgctxt "@action:button Preceded by 'Ready to'."
msgid "Save to Removable Drive"
@@ -232,11 +236,11 @@ msgid "Could not save to removable drive {0}: {1}"
msgstr "リムーバブルドライブ{0}に保存することができませんでした: {1}"
#: /home/ruben/Projects/Cura/plugins/RemovableDriveOutputDevice/RemovableDriveOutputDevice.py:132
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:692
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:700
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:146
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:693
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:701
#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:153
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1358
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:160
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1427
msgctxt "@info:title"
msgid "Error"
msgstr "エラー"
@@ -286,7 +290,7 @@ msgid "Removable Drive"
msgstr "リムーバブルドライブ"
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:109
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:53
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:51
msgctxt "@action:button Preceded by 'Ready to'."
msgid "Print over network"
msgstr "ネットワーク上のプリント"
@@ -400,110 +404,110 @@ msgctxt "@info:title"
msgid "Printer Status"
msgstr "プリンターのステータス"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:691
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:692
#, python-brace-format
msgctxt "@info:status"
msgid "Unable to start a new print job. No Printcore loaded in slot {0}"
msgstr "プリントコアがスロット{0}に入っていません。プリントジョブを開始できません。"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:699
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:700
#, python-brace-format
msgctxt "@info:status"
msgid "Unable to start a new print job. No material loaded in slot {0}"
msgstr "フィラメントがスロット{0}に入っていません。プリントジョブを開始できません。"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:709
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:710
#, python-brace-format
msgctxt "@label"
msgid "Not enough material for spool {0}."
msgstr "フィラメント{0}の残量が足りません。"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:719
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:720
#, python-brace-format
msgctxt "@label"
msgid "Different PrintCore (Cura: {0}, Printer: {1}) selected for extruder {2}"
msgstr "異なるプリントコアが入っています(Cura:{0}, プリンター{1})エクストルーダー{2}"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:733
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:734
#, python-brace-format
msgctxt "@label"
msgid "Different material (Cura: {0}, Printer: {1}) selected for extruder {2}"
msgstr "異なるフィラメントが入っています(Cura:{0}, プリンター{1})エクストルーダー{2}"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:741
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:742
#, python-brace-format
msgctxt "@label"
msgid "PrintCore {0} is not properly calibrated. XY calibration needs to be performed on the printer."
msgstr "プリントコア{0}が適切にキャリブレーションできていません。XYキャリブレーションをプリンターで行ってください。"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:746
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:747
msgctxt "@label"
msgid "Are you sure you wish to print with the selected configuration?"
msgstr "選択された構成にてプリントを開始してもいいですか。"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:747
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:748
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 "プリンターの設定、キャリブレーションとCuraの構成にミスマッチがあります。プリンターに設置されたプリントコア及びフィラメントを元にCuraをスライスすることで最良の印刷結果を出すことができます。"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:753
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:754
msgctxt "@window:title"
msgid "Mismatched configuration"
msgstr "ミスマッチの構成"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:864
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:262
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:865
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:258
msgctxt "@info:status"
msgid "Sending new jobs (temporarily) blocked, still sending the previous print job."
msgstr "新しいデータの送信 (temporarily) をブロックします、前のプリントジョブが送信中です。"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:873
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:874
msgctxt "@info:status"
msgid "Sending data to printer"
msgstr "プリンターにプリントデータを送信中"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:873
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:874
msgctxt "@info:title"
msgid "Sending Data"
msgstr "プリントデータを送信中"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:944
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:945
msgctxt "@info:status"
msgid "Unable to send data to printer. Is another job still active?"
msgstr "データをプリンターに送ることができません。他のプリントジョブは進行中ですか?"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:1085
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:1087
#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:196
msgctxt "@label:MonitorStatus"
msgid "Aborting print..."
msgstr "プリントを停止します…"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:1091
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:1093
msgctxt "@label:MonitorStatus"
msgid "Print aborted. Please check the printer"
msgstr "プリントを中止しました。プリンターを確認してください。"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:1097
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:1099
msgctxt "@label:MonitorStatus"
msgid "Pausing print..."
msgstr "プリントを一時停止します…"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:1099
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:1101
msgctxt "@label:MonitorStatus"
msgid "Resuming print..."
msgstr "プリント再開します…"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:1289
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:1291
msgctxt "@window:title"
msgid "Sync with your printer"
msgstr "プリンターと同期する"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:1291
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:1293
msgctxt "@label"
msgid "Would you like to use your current printer configuration in Cura?"
msgstr "Curaで設定しているプリンタ構成を使用されますか?"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:1293
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:1295
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 "プリンターのプリントコア及びフィラメントが現在のプロジェクトと異なります。最善な印刷結果のために、プリンタに装着しているプリントコア、フィラメントに合わせてスライスして頂くことをお勧めします。"
@@ -524,145 +528,204 @@ msgid "{printer_name} has finished printing '{job_name}'. Please collect the pri
msgstr "{printer_name}は ‘{job_name}’印刷を終了しました。造形物を確認し、ビルドプレートから取り出してください。"
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:115
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:520
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:533
#, python-brace-format
msgid "{printer_name} is reserved to print '{job_name}'. Please change the printer's configuration to match the job, for it to start printing."
msgstr "{printer_name} は '{job_name}'.を印刷予定です。印刷を開始するためにジョブに合わせた構成に変更してください。"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:278
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:277
msgctxt "@info:status"
msgid "Unable to send new print job: this 3D printer is not (yet) set up to host a group of connected Ultimaker 3 printers."
msgstr "新しいプリントジョブをお送りできません。この3Dプリンターは繋がっているUltimaker3のグループをホストするために設定されていません。"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:410
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:423
#, python-brace-format
msgctxt "@info:status"
msgid "Unable to send print job to group {cluster_name}."
msgstr "プリントジョブをグループに送ることができません。{cluster_name}."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:418
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:431
#, python-brace-format
msgctxt "@info:status"
msgid "Sent {file_name} to group {cluster_name}."
msgstr "グループに送信完了{file_name} {cluster_name}."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:423
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:436
msgctxt "@action:button"
msgid "Show print jobs"
msgstr "プリントジョブを見る"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:424
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:437
msgctxt "@info:tooltip"
msgid "Opens the print jobs interface in your browser."
msgstr "プリントジョブのインターフェイスをブラウザーで開く"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:489
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:502
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/DiscoverUM3Action.qml:239
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/PrinterInfoBlock.qml:47
-msgctxt "@label"
+msgctxt "@label Printer name"
msgid "Unknown"
msgstr "不明"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:492
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:505
#, python-brace-format
msgctxt "@info:status"
msgid "Printer '{printer_name}' has finished printing '{job_name}'."
msgstr "プリンター’{printer_name}’が’{job_name}’のプリントを終了しました。"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:494
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:497
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:507
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:510
msgctxt "@info:status"
msgid "Print finished"
msgstr "プリント終了"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:522
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:525
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:535
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:538
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/PrinterInfoBlock.qml:282
msgctxt "@label:status"
msgid "Action required"
msgstr "アクションが必要です。"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:643
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:656
#, python-brace-format
msgctxt "@info:progress"
msgid "Sending {file_name} to group {cluster_name}"
msgstr "グループに送信中{file_name} {cluster_name}"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/DiscoverUM3Action.py:19
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/DiscoverUM3Action.py:17
msgctxt "@action"
msgid "Connect via Network"
msgstr "ネットワーク上にて接続"
-#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py:64
+#: /home/ruben/Projects/Cura/plugins/MonitorStage/__init__.py:12
+msgctxt "@item:inmenu"
+msgid "Monitor"
+msgstr "モニター"
+
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py:66
#, 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 "{machine_name} で利用可能な新しい機能があります。プリンターのファームウェアをアップデートしてください。"
-#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py:65
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py:67
#, python-format
msgctxt "@info:title The %s gets replaced with the printer name."
msgid "New %s firmware available"
msgstr "新しい利用可能な%sファームウェアのアップデートがあります。"
-#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py:66
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py:68
msgctxt "@action:button"
msgid "How to update"
msgstr "アップデートの仕方"
-#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py:77
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py:79
msgctxt "@info"
msgid "Could not access update information."
msgstr "必要なアップデートの情報にアクセスできません。"
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksReader.py:199
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksReader.py:579
msgctxt "@info:status"
-msgid "Errors appeared while opening your SolidWorks file! Please check, whether it is possible to open your file in SolidWorks itself without any problems as well!"
-msgstr "ソリッドワークスのファイルを開く際にエラーが発生しました!ソリッドワークスで、問題なく開くことができるか確認してください。"
+msgid "SolidWorks reported errors, while opening your file. We recommend to solve these issues inside SolidWorks itself."
+msgstr "ソリッドワークスがファイルを開く際にエラーを報告しました。ソリッドワークス内で問題を解決することをお勧めします。"
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/__init__.py:31
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksReader.py:591
+msgctxt "@info:status"
+msgid ""
+"Found no models inside your drawing. Could you please check it's content again and make sure one part or assembly is inside?\n"
+"\n"
+" Thanks!."
+msgstr ""
+"図面の中にモデルが見つかりません。中身を確認し、パートかアセンブリーが中に入っていることを確認してください。\n"
+"\n"
+" 再確認をお願いします。"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksReader.py:595
+msgctxt "@info:status"
+msgid ""
+"Found more then one part or assembly inside your drawing. We currently only support drawings with exactly one part or assembly inside.\n"
+"\n"
+"Sorry!"
+msgstr ""
+"図面の中にパートかアセンブリーが2個以上見つかりました。今のところ、本製品はパートかアセンブリーが1個の図面のみに対応しています。\n"
+"\n"
+"申し訳ありません。"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/__init__.py:25
msgctxt "@item:inlistbox"
msgid "SolidWorks part file"
msgstr "ソリッドワークスパートファイル"
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/__init__.py:35
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/__init__.py:29
msgctxt "@item:inlistbox"
msgid "SolidWorks assembly file"
msgstr "ソリッドワークスアセンブリーファイル"
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/ConfigDialog.py:21
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/__init__.py:33
+msgctxt "@item:inlistbox"
+msgid "SolidWorks drawing file"
+msgstr "ソリッドワークス図面ファイル"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/__init__.py:48
+msgctxt "@info:status"
+msgid ""
+"Dear customer,\n"
+"We could not find a valid installation of SolidWorks on your system. That means that either SolidWorks is not installed or you don't own an valid license. Please make sure that running SolidWorks itself works without issues and/or contact your ICT.\n"
+"\n"
+"With kind regards\n"
+" - Thomas Karl Pietrowski"
+msgstr ""
+"お客様へ\n"
+"システム上に正規のソリッドワークスがインストールされていません。つまり、ソリッドワークスがインストールされていないか、有効なライセンスが存在しません。ソリッドワークスだけを問題なく使用できるようになっているか確認するか、自社のIT部門にご相談ください。\n"
+"\n"
+"お願いいたします。\n"
+" - Thomas Karl Pietrowski"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/__init__.py:57
+msgctxt "@info:status"
+msgid ""
+"Dear customer,\n"
+"You are currently running this plugin on an operating system other than Windows. This plugin will only work on Windows with SolidWorks installed, including an valid license. Please install this plugin on a Windows machine with SolidWorks installed.\n"
+"\n"
+"With kind regards\n"
+" - Thomas Karl Pietrowski"
+msgstr ""
+"お客様へ\n"
+"このプラグインは現在Windows以外のOSで実行されています。このプラグインは、ソリッドワークスがインストールされたWindowsでしか動作しません。有効なライセンスも必要です。ソリッドワークスがインストールされたWindowsマシンにこのプラグインをインストールしてください。\n"
+"\n"
+"お願いいたします。\n"
+" - Thomas Karl Pietrowski"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksDialogHandler.py:70
msgid "Configure"
msgstr "構成"
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/CommonComReader.py:135
-#, python-format
-msgctxt "@info:status"
-msgid "Error while starting %s!"
-msgstr "%sを開始中にエラーが発生"
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksDialogHandler.py:71
+msgid "Installation guide for SolidWorks macro"
+msgstr "ソリッドワークス・マクロのインストールガイド"
#: /home/ruben/Projects/Cura/plugins/SimulationView/__init__.py:14
msgctxt "@item:inlistbox"
-msgid "Simulation view"
-msgstr "シミュレーションビュー"
+msgid "Layer view"
+msgstr "レイヤービュー"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.py:100
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.py:103
msgctxt "@info:status"
msgid "Cura does not accurately display layers when Wire Printing is enabled"
msgstr "Curaはワイヤープリンティング設定中には正確にレイヤーを表示しません。"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.py:101
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.py:104
msgctxt "@info:title"
msgid "Simulation View"
msgstr "シミュレーションビュー"
-#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.py:26
+#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.py:25
msgid "Modify G-Code"
msgstr "G-codeを修正"
#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/SliceInfo.py:43
msgctxt "@info"
-msgid "Cura collects anonymised slicing statistics. You can disable this in the preferences."
-msgstr "Curaが非特定なスライスされた数字を集めました。プレファレンス内で無効にできます。"
+msgid "Cura collects anonymized usage statistics."
+msgstr "Curaは、匿名化した利用統計を収集します。"
#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/SliceInfo.py:46
msgctxt "@info:title"
@@ -671,14 +734,43 @@ msgstr "データを収集中"
#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/SliceInfo.py:48
msgctxt "@action:button"
-msgid "Dismiss"
-msgstr "却下する"
+msgid "Allow"
+msgstr "許可"
+
+#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/SliceInfo.py:49
+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 "Curaが匿名化した利用統計を送信することを許可し、Curaの将来の改善を優先的に行うことに貢献します。プレファレンスと設定の一部、Curaのバージョン、スライスしているモデルのハッシュが送信されます。"
+
+#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/SliceInfo.py:50
+msgctxt "@action:button"
+msgid "Disable"
+msgstr "無効化"
+
+#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/SliceInfo.py:51
+msgctxt "@action:tooltip"
+msgid "Don't allow Cura to send anonymized usage statistics. You can enable it again in the preferences."
+msgstr "Curaが匿名化した利用統計を送信することを許可しません。プレファレンスで許可に変更することができます。"
#: /home/ruben/Projects/Cura/plugins/LegacyProfileReader/__init__.py:14
msgctxt "@item:inlistbox"
msgid "Cura 15.04 profiles"
msgstr "Cura 15.04 プロファイル"
+#: /home/ruben/Projects/Cura/plugins/CuraBlenderPlugin/__init__.py:15
+msgctxt "@item:inlistbox"
+msgid "Blender file"
+msgstr "Blenderファイル"
+
+#: /home/ruben/Projects/Cura/plugins/CuraBlenderPlugin/CadIntegrationUtils/CommonReader.py:199
+msgctxt "@info:status"
+msgid ""
+"Could not export using \"{}\" quality!\n"
+"Felt back to \"{}\"."
+msgstr ""
+"\"{}\"品質を使用したエクスポートができませんでした!\n"
+"\"{}\"になりました。"
+
#: /home/ruben/Projects/Cura/plugins/GCodeProfileReader/__init__.py:14
#: /home/ruben/Projects/Cura/plugins/GCodeReader/__init__.py:14
msgctxt "@item:inlistbox"
@@ -710,49 +802,49 @@ msgctxt "@item:inlistbox"
msgid "GIF Image"
msgstr "GIF画像"
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:269
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:299
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:269
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:297
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:319
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:299
#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:327
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:336
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:349
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:357
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:366
msgctxt "@info:title"
msgid "Unable to slice"
msgstr "スライスできません。"
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:296
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:326
#, python-brace-format
msgctxt "@info:status"
msgid "Unable to slice with the current settings. The following settings have errors: {0}"
msgstr "現在の設定でスライスが完了できません。以下の設定にエラーがあります: {0}"
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:318
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:348
#, 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 "モデル別の設定があるためスライスできません。1つまたは複数のモデルで以下の設定にエラーが発生しました:{error_labels}"
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:326
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:356
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:335
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:365
msgctxt "@info:status"
msgid "Nothing to slice because none of the models fit the build volume. Please scale or rotate models to fit."
msgstr "モデルのデータがビルトボリュームに入っていないためスライスできるものがありません。スケールやローテーションにて合うように設定してください。"
#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py:50
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py:239
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py:242
msgctxt "@info:status"
msgid "Processing Layers"
msgstr "レイヤーを処理しています。"
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py:239
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py:242
msgctxt "@info:title"
msgid "Information"
msgstr "インフォメーション"
@@ -789,14 +881,14 @@ msgstr "Siemens NXプラグインファイルのコピーに失敗しました
msgid "Failed to install Siemens NX plugin. Could not set environment variable UGII_USER_DIR for Siemens NX."
msgstr "Siemens NXプラグインのインストールに失敗しました。Siemens NX用の環境変数UGII_USER_DIRが設定できませんでした。"
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.py:167
-#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:585
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.py:165
+#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:590
msgctxt "@title:tab"
msgid "Recommended"
msgstr "推奨"
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.py:169
-#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:590
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.py:167
+#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:595
msgctxt "@title:tab"
msgid "Custom"
msgstr "カスタム"
@@ -807,24 +899,24 @@ msgctxt "@item:inlistbox"
msgid "3MF File"
msgstr "3MF ファイル"
-#: /home/ruben/Projects/Cura/plugins/3MFReader/ThreeMFWorkspaceReader.py:126
-#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:1142
+#: /home/ruben/Projects/Cura/plugins/3MFReader/ThreeMFWorkspaceReader.py:159
+#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:1185
msgctxt "@label"
msgid "Nozzle"
msgstr "ノズル"
-#: /home/ruben/Projects/Cura/plugins/PluginBrowser/PluginBrowser.py:164
+#: /home/ruben/Projects/Cura/plugins/PluginBrowser/PluginBrowser.py:152
#, python-brace-format
msgctxt "@info:status"
msgid "Failed to get plugin ID from {0}"
msgstr "{0}からプラグインIDを取得することに失敗しました。"
-#: /home/ruben/Projects/Cura/plugins/PluginBrowser/PluginBrowser.py:165
+#: /home/ruben/Projects/Cura/plugins/PluginBrowser/PluginBrowser.py:153
msgctxt "@info:tile"
msgid "Warning"
msgstr "警告"
-#: /home/ruben/Projects/Cura/plugins/PluginBrowser/PluginBrowser.py:203
+#: /home/ruben/Projects/Cura/plugins/PluginBrowser/PluginBrowser.py:191
msgctxt "@window:title"
msgid "Plugin browser"
msgstr "プラグインブラウザー"
@@ -839,18 +931,18 @@ msgctxt "@item:inlistbox"
msgid "G File"
msgstr "Gファイル"
-#: /home/ruben/Projects/Cura/plugins/GCodeReader/GCodeReader.py:314
+#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:321
msgctxt "@info:status"
msgid "Parsing G-code"
msgstr "G-codeを解析"
-#: /home/ruben/Projects/Cura/plugins/GCodeReader/GCodeReader.py:316
-#: /home/ruben/Projects/Cura/plugins/GCodeReader/GCodeReader.py:426
+#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:323
+#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:464
msgctxt "@info:title"
msgid "G-code Details"
msgstr "G-codeの詳細"
-#: /home/ruben/Projects/Cura/plugins/GCodeReader/GCodeReader.py:424
+#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:462
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 "データファイルを送信する前に、プリンターとプリンターの構成設定にそのG-codeが適応しているか確認してください。G-codeの表示が適切でない場合があります。"
@@ -861,6 +953,16 @@ msgctxt "@item:inlistbox"
msgid "Cura Profile"
msgstr "Curaプロファイル"
+#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/__init__.py:12
+msgctxt "@item:inmenu"
+msgid "Profile Assistant"
+msgstr "プロファイルアシスタント"
+
+#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/__init__.py:17
+msgctxt "@item:inlistbox"
+msgid "Profile Assistant"
+msgstr "プロファイルアシスタント"
+
#: /home/ruben/Projects/Cura/plugins/3MFWriter/__init__.py:30
msgctxt "@item:inlistbox"
msgid "3MF file"
@@ -892,142 +994,116 @@ msgctxt "@action"
msgid "Level build plate"
msgstr "ビルドプレートを調整する"
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:89
+#: /home/ruben/Projects/Cura/cura/PrintInformation.py:98
msgctxt "@tooltip"
msgid "Outer Wall"
msgstr "アウターウォール"
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:90
+#: /home/ruben/Projects/Cura/cura/PrintInformation.py:99
msgctxt "@tooltip"
msgid "Inner Walls"
msgstr "インナーウォール"
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:91
+#: /home/ruben/Projects/Cura/cura/PrintInformation.py:100
msgctxt "@tooltip"
msgid "Skin"
msgstr "スキン"
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:92
+#: /home/ruben/Projects/Cura/cura/PrintInformation.py:101
msgctxt "@tooltip"
msgid "Infill"
msgstr "インフィル"
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:93
+#: /home/ruben/Projects/Cura/cura/PrintInformation.py:102
msgctxt "@tooltip"
msgid "Support Infill"
msgstr "サポートイルフィル"
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:94
+#: /home/ruben/Projects/Cura/cura/PrintInformation.py:103
msgctxt "@tooltip"
msgid "Support Interface"
msgstr "サポートインターフェイス"
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:95
+#: /home/ruben/Projects/Cura/cura/PrintInformation.py:104
msgctxt "@tooltip"
msgid "Support"
msgstr "サポート"
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:96
+#: /home/ruben/Projects/Cura/cura/PrintInformation.py:105
msgctxt "@tooltip"
msgid "Skirt"
msgstr "スカート"
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:97
+#: /home/ruben/Projects/Cura/cura/PrintInformation.py:106
msgctxt "@tooltip"
msgid "Travel"
msgstr "移動"
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:98
+#: /home/ruben/Projects/Cura/cura/PrintInformation.py:107
msgctxt "@tooltip"
msgid "Retractions"
msgstr "退却"
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:99
+#: /home/ruben/Projects/Cura/cura/PrintInformation.py:108
msgctxt "@tooltip"
msgid "Other"
msgstr "他"
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:199
+#: /home/ruben/Projects/Cura/cura/PrintInformation.py:231
msgctxt "@label unknown material"
msgid "Unknown"
msgstr "不明"
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:284
+#: /home/ruben/Projects/Cura/cura/PrintInformation.py:318
#, python-brace-format
msgctxt "@label"
msgid "Pre-sliced file {0}"
msgstr "スライス前ファイル {0}"
-#: /home/ruben/Projects/Cura/cura/PrinterOutputDevice.py:469
+#: /home/ruben/Projects/Cura/cura/PrinterOutputDevice.py:440
msgctxt "@item:material"
msgid "No material loaded"
msgstr "フィラメントがロードされていません。"
-#: /home/ruben/Projects/Cura/cura/PrinterOutputDevice.py:476
+#: /home/ruben/Projects/Cura/cura/PrinterOutputDevice.py:447
msgctxt "@item:material"
msgid "Unknown material"
msgstr "未確認のフィラメント"
-#: /home/ruben/Projects/Cura/cura/ArrangeObjectsJob.py:30
-msgctxt "@info:status"
-msgid "Finding new location for objects"
-msgstr "造形物のために新しい位置を探索中"
-
-#: /home/ruben/Projects/Cura/cura/ArrangeObjectsJob.py:34
-msgctxt "@info:title"
-msgid "Finding Location"
-msgstr "位置確認"
-
-#: /home/ruben/Projects/Cura/cura/ArrangeObjectsJob.py:89
-#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:83
-msgctxt "@info:status"
-msgid "Unable to find a location within the build volume for all objects"
-msgstr "全ての造形物の造形サイズに対し、適切な位置が確認できません"
-
-#: /home/ruben/Projects/Cura/cura/ArrangeObjectsJob.py:90
-msgctxt "@info:title"
-msgid "Can't Find Location"
-msgstr "位置を確保できません。"
-
-#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:431
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:113
+#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:437
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:120
msgctxt "@title:window"
msgid "File Already Exists"
msgstr "すでに存在するファイルです。"
-#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:432
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:114
+#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:438
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:121
#, 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 "{0} は既に存在します。ファイルを上書きしますか?"
-#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:815
+#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:872
msgctxt "@label"
msgid "Custom"
msgstr "カスタム"
-#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:819
+#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:876
msgctxt "@label"
msgid "Custom Material"
msgstr "カスタムフィラメント"
-#: /home/ruben/Projects/Cura/cura/Settings/ExtrudersModel.py:182
-msgctxt "@menuitem"
-msgid "Global"
-msgstr "グローバル"
-
-#: /home/ruben/Projects/Cura/cura/Settings/ExtrudersModel.py:229
+#: /home/ruben/Projects/Cura/cura/Settings/ExtrudersModel.py:205
msgctxt "@menuitem"
msgid "Not overridden"
msgstr "上書きできません"
-#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:117
+#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:124
msgctxt "@info:status"
msgid "The selected material is incompatible with the selected machine or configuration."
msgstr "選択されたフィラメントはプリンターとそのプリント構成に適応しておりません。"
-#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:118
+#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:125
#: /home/ruben/Projects/Cura/cura/Settings/MaterialManager.py:24
msgctxt "@info:title"
msgid "Incompatible Material"
@@ -1048,67 +1124,89 @@ msgctxt "@action"
msgid "Undo changing the material diameter."
msgstr "フィラメント直径を変更を取り消す"
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:144
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:151
#, python-brace-format
msgctxt "@info:status Don't translate the XML tags or !"
msgid "Failed to export profile to {0}: {1}"
msgstr "{0}にプロファイルを書き出すのに失敗しました: {1}"
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:151
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:158
#, python-brace-format
msgctxt "@info:status Don't translate the XML tag !"
msgid "Failed to export profile to {0}: Writer plugin reported failure."
msgstr " {0}にプロファイルを書き出すことに失敗しました。:ライタープラグイン失敗の報告"
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:156
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:163
#, python-brace-format
msgctxt "@info:status Don't translate the XML tag !"
msgid "Exported profile to {0}"
msgstr "{0}にプロファイルを書き出しました。"
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:157
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:164
msgctxt "@info:title"
msgid "Export succeeded"
msgstr "書き出し完了"
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:183
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:205
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:214
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:248
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:190
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:211
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:271
#, python-brace-format
msgctxt "@info:status Don't translate the XML tags or !"
msgid "Failed to import profile from {0}: {1}"
msgstr "{0}: {1}からプロファイルを取り込むことに失敗しました。"
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:216
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:252
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:230
+#, python-brace-format
+msgctxt "@info:status Don't translate the XML tags or !"
+msgid "This profile {0} contains incorrect data, could not import it."
+msgstr "このプロファイル{0}には、正しくないデータが含まれていて、インポートできません。"
+
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:240
+#, python-brace-format
+msgctxt "@info:status Don't translate the XML tags or !"
+msgid "The machine defined in profile {0} doesn't match with your current machine, could not import it."
+msgstr "プロファイル{0}の中で定義されているマシンは、現在お使いのマシンと一致しませんので、インポートできませんでした。"
+
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:274
#, python-brace-format
msgctxt "@info:status"
msgid "Successfully imported profile {0}"
msgstr "プロファイル {0}の取り込み完了"
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:255
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:277
+#, python-brace-format
+msgctxt "@info:status"
+msgid "File {0} does not contain any valid profile."
+msgstr "ファイル{0}には、正しいプロファイルが含まれていません。"
+
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:280
#, python-brace-format
msgctxt "@info:status"
msgid "Profile {0} has an unknown file type or is corrupted."
msgstr "プロファイル{0}は不特定なファイルまたは破損があります。"
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:274
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:298
msgctxt "@label"
msgid "Custom profile"
msgstr "カスタムプロファイル"
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:285
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:313
msgctxt "@info:status"
msgid "Profile is missing a quality type."
msgstr "プロファイルはクオリティータイプが不足しています。"
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:321
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:349
#, python-brace-format
msgctxt "@info:status"
msgid "Could not find a quality type {0} for the current configuration."
msgstr "進行中のプリント構成にあったクオリティータイプ{0}が見つかりませんでした。"
+#: /home/ruben/Projects/Cura/cura/ObjectsModel.py:46
+#, python-brace-format
+msgctxt "@label"
+msgid "Group #{group_nr}"
+msgstr "グループ #{group_nr}"
+
#: /home/ruben/Projects/Cura/cura/BuildVolume.py:100
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."
@@ -1119,142 +1217,170 @@ msgctxt "@info:title"
msgid "Build Volume"
msgstr "造形サイズ"
-#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:34
+#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:25
msgctxt "@info:status"
msgid "Multiplying and placing objects"
msgstr "造形データを増やす、配置する。"
-#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:35
-#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:83
+#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:26
+#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:78
msgctxt "@info:title"
msgid "Placing Object"
msgstr "造形データを配置"
-#: /home/ruben/Projects/Cura/cura/CrashHandler.py:80
+#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:78
+#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsJob.py:88
+#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsAllBuildPlatesJob.py:152
+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:29
+#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsAllBuildPlatesJob.py:64
+msgctxt "@info:status"
+msgid "Finding new location for objects"
+msgstr "造形物のために新しい位置を探索中"
+
+#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsJob.py:33
+#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsAllBuildPlatesJob.py:68
+msgctxt "@info:title"
+msgid "Finding Location"
+msgstr "位置確認"
+
+#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsJob.py:89
+#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsAllBuildPlatesJob.py:153
+msgctxt "@info:title"
+msgid "Can't Find Location"
+msgstr "位置を確保できません。"
+
+#: /home/ruben/Projects/Cura/cura/CrashHandler.py:81
msgctxt "@title:window"
msgid "Crash Report"
msgstr "クラッシュ報告"
-#: /home/ruben/Projects/Cura/cura/CrashHandler.py:93
+#: /home/ruben/Projects/Cura/cura/CrashHandler.py:94
msgctxt "@label crash message"
msgid ""
-"
A fatal exception has occurred. Please send us this Crash Report to fix the problem
\n"
+"
A fatal error has occurred. Please send us this Crash Report to fix the problem
\n"
"
Please use the \"Send report\" button to post a bug report automatically to our servers
"
+
+#~ msgctxt "@action:inmenu menubar:view"
+#~ msgid "&Reset camera position"
+#~ msgstr "&カメラ位置のリセット"
+
+#~ msgctxt "@title:menu menubar:file"
+#~ msgid "Save project"
+#~ msgstr "プロジェクトを保存"
+
+#~ msgctxt "@title:tab"
+#~ msgid "Prepare"
+#~ msgstr "準備する"
+
+#~ msgctxt "@title:tab"
+#~ msgid "Monitor"
+#~ msgstr "モニター"
+
+#~ msgctxt "@label"
+#~ msgid "Check compatibility"
+#~ msgstr "互換性の確認"
+
+#~ msgctxt "description"
+#~ msgid "Gives you the possibility to open certain files via SolidWorks itself. These are then converted and loaded into Cura"
+#~ msgstr "ソリッドワークスにて特定のファイルを開くことが可能です。その後変換され、Curaに取り込めます。"
+
#~ msgctxt "@label:status"
#~ msgid "Blocked"
#~ msgstr "ブロックされました"
@@ -4442,13 +5004,9 @@ msgstr "Curaプロファイルリーダー"
#~ msgid "To ensure that your {machine_name} is equipped with the latest features it is recommended to update the firmware regularly. This can be done on the {machine_name} (when connected to the network) or via USB."
#~ msgstr "{machine_name}が最新の機能を得るために、定期的にファームウェアをアップデートすることをお勧めします。{machine_name}(ネットワーク上で接続)またはUSBにて行ってください。 "
-msgctxt "@item:inlistbox"
-msgid "Layer view"
-msgstr "レイヤービュー"
-
-msgctxt "@info:title"
-msgid "Layer View"
-msgstr "レイヤービュー"
+#~ msgctxt "@info:title"
+#~ msgid "Layer View"
+#~ msgstr "レイヤービュー"
#~ msgctxt "@menuitem"
#~ msgid "Browse plugins"
@@ -4550,6 +5108,6 @@ msgstr "レイヤービュー"
#~ msgid "Provides the Layer view."
#~ msgstr "レイヤービューを供給する"
-msgctxt "name"
-msgid "Layer View"
-msgstr "レイヤービュー"
+#~ msgctxt "name"
+#~ msgid "Layer View"
+#~ msgstr "レイヤービュー"
diff --git a/resources/i18n/ja_JP/fdmextruder.def.json.po b/resources/i18n/ja_JP/fdmextruder.def.json.po
index d1ff38fcf2..69c13959bd 100644
--- a/resources/i18n/ja_JP/fdmextruder.def.json.po
+++ b/resources/i18n/ja_JP/fdmextruder.def.json.po
@@ -2,12 +2,12 @@
# Copyright (C) 2017 Ultimaker
# This file is distributed under the same license as the Cura package.
# Ruben Dulek , 2017.
-#
+#
msgid ""
msgstr ""
"Project-Id-Version: Cura 3.0\n"
-"Report-Msgid-Bugs-To: http://github.com/ultimaker/uranium\n"
-"POT-Creation-Date: 2017-11-21 16:58+0000\n"
+"Report-Msgid-Bugs-To: r.dulek@ultimaker.com\n"
+"POT-Creation-Date: 2017-08-02 16:53+0000\n"
"PO-Revision-Date: 2017-11-30 13:05+0100\n"
"Last-Translator: Brule\n"
"Language-Team: Brule\n"
diff --git a/resources/i18n/ja_JP/fdmprinter.def.json.po b/resources/i18n/ja_JP/fdmprinter.def.json.po
index 56ba768bc9..25c3b58fe3 100644
--- a/resources/i18n/ja_JP/fdmprinter.def.json.po
+++ b/resources/i18n/ja_JP/fdmprinter.def.json.po
@@ -1,14 +1,14 @@
-# Cura JSON setting files
-# Copyright (C) 2017 Ultimaker
+# Cura
+# Copyright (C) 2018 Ultimaker
# This file is distributed under the same license as the Cura package.
-# Ruben Dulek , 2017.
-#
+# Ruben Dulek , 2018.
+#
msgid ""
msgstr ""
-"Project-Id-Version: Cura 3.0\n"
-"Report-Msgid-Bugs-To: http://github.com/ultimaker/uranium\n"
-"POT-Creation-Date: 2017-11-21 16:58+0000\n"
-"PO-Revision-Date: 2017-11-30 13:05+0100\n"
+"Project-Id-Version: Cura 3.2\n"
+"Report-Msgid-Bugs-To: r.dulek@ultimaker.com\n"
+"POT-Creation-Date: 2018-01-29 09:48+0000\n"
+"PO-Revision-Date: 2018-02-10 05:04+0900\n"
"Last-Translator: Brule\n"
"Language-Team: Brule\n"
"Language: ja_JP\n"
@@ -62,7 +62,9 @@ msgctxt "machine_start_gcode description"
msgid ""
"Gcode commands to be executed at the very start - separated by \n"
"."
-msgstr "Gcodeのコマンドは −で始まり\nで区切られます。"
+msgstr ""
+"Gcodeのコマンドは −で始まり\n"
+"で区切られます。"
#: fdmprinter.def.json
msgctxt "machine_end_gcode label"
@@ -75,7 +77,9 @@ msgctxt "machine_end_gcode description"
msgid ""
"Gcode commands to be executed at the very end - separated by \n"
"."
-msgstr "Gcodeのコマンドは −で始まり\nで区切られます。"
+msgstr ""
+"Gcodeのコマンドは −で始まり\n"
+"で区切られます。"
#: fdmprinter.def.json
msgctxt "material_guid label"
@@ -377,6 +381,16 @@ msgctxt "machine_gcode_flavor option Repetier"
msgid "Repetier"
msgstr "Repetier"
+#: fdmprinter.def.json
+msgctxt "machine_firmware_retract label"
+msgid "Firmware Retraction"
+msgstr "ファームウェア引き戻し"
+
+#: fdmprinter.def.json
+msgctxt "machine_firmware_retract description"
+msgid "Whether to use firmware retract commands (G10/G11) instead of using the E property in G1 commands to retract the material."
+msgstr "材料を引き戻すためにG1コマンドのEプロパティーを使用する代わりにファームウェア引き戻しコマンド (G10/G11) を使用するかどうか。"
+
# msgstr "Repetier"
#: fdmprinter.def.json
msgctxt "machine_disallowed_areas label"
@@ -641,31 +655,6 @@ msgctxt "layer_height_0 description"
msgid "The height of the initial layer in mm. A thicker initial layer makes adhesion to the build plate easier."
msgstr "初期レイヤーの高さ(mm)。厚い初期層はビルドプレートへの接着を容易にする。"
-#: fdmprinter.def.json
-msgctxt "slicing_tolerance label"
-msgid "Slicing Tolerance"
-msgstr "スライス公差"
-
-#: fdmprinter.def.json
-msgctxt "slicing_tolerance description"
-msgid "How to slice layers with diagonal surfaces. The areas of a layer can be generated based on where the middle of the layer intersects the surface (Middle). Alternatively each layer can have the areas which fall inside of the volume throughout the height of the layer (Exclusive) or a layer has the areas which fall inside anywhere within the layer (Inclusive). Exclusive retains the most details, Inclusive makes for the best fit and Middle takes the least time to process."
-msgstr "表面を斜めにスライスする方法を指定します。レイヤーの領域は、レイヤーの中央がサーフェス(中央)と交差する位置に基づいて生成できます。また、各層は、レイヤーの高さを通してボリュームの内側に収まる領域を持つ(排他)か、またはレイヤー内の任意の場所内に収まる領域を持っています(包括)。排他は最も細かく、包括は最もフィットし、中間は時間がかかります。"
-
-#: fdmprinter.def.json
-msgctxt "slicing_tolerance option middle"
-msgid "Middle"
-msgstr "中間"
-
-#: fdmprinter.def.json
-msgctxt "slicing_tolerance option exclusive"
-msgid "Exclusive"
-msgstr "排他"
-
-#: fdmprinter.def.json
-msgctxt "slicing_tolerance option inclusive"
-msgid "Inclusive"
-msgstr "包括"
-
#: fdmprinter.def.json
msgctxt "line_width label"
msgid "Line Width"
@@ -706,17 +695,6 @@ msgctxt "wall_line_width_x description"
msgid "Width of a single wall line for all wall lines except the outermost one."
msgstr "一番外側のウォールラインを除くすべてのウォールラインのラインの幅。"
-#: fdmprinter.def.json
-msgctxt "roofing_line_width label"
-msgid "Top Surface Skin Line Width"
-msgstr "最上面のライン幅"
-
-# msgstr "上表面スキンの線幅"
-#: fdmprinter.def.json
-msgctxt "roofing_line_width description"
-msgid "Width of a single line of the areas at the top of the print."
-msgstr "プリントの上部の 線の幅。"
-
#: fdmprinter.def.json
msgctxt "skin_line_width label"
msgid "Top/Bottom Line Width"
@@ -907,46 +885,6 @@ msgctxt "roofing_layer_count description"
msgid "The number of top most skin layers. Usually only one top most layer is sufficient to generate higher quality top surfaces."
msgstr "上部表面のレイヤー数。通常一層で綺麗に出来上がります"
-#: fdmprinter.def.json
-msgctxt "roofing_pattern label"
-msgid "Top Surface Skin Pattern"
-msgstr "上部表面パターン"
-
-# msgstr "上層表面スキンパターン"
-#: fdmprinter.def.json
-msgctxt "roofing_pattern description"
-msgid "The pattern of the top most layers."
-msgstr "上層のパターン"
-
-#: fdmprinter.def.json
-msgctxt "roofing_pattern option lines"
-msgid "Lines"
-msgstr "直線"
-
-# msgstr "線"
-#: fdmprinter.def.json
-msgctxt "roofing_pattern option concentric"
-msgid "Concentric"
-msgstr "同心円"
-
-# msgstr "同心"
-#: fdmprinter.def.json
-msgctxt "roofing_pattern option zigzag"
-msgid "Zig Zag"
-msgstr "ジグザグ"
-
-# msgstr "ジグザグ"
-#: fdmprinter.def.json
-msgctxt "roofing_angles label"
-msgid "Top Surface Skin Line Directions"
-msgstr "最上面のラインの向き"
-
-# msgstr "上層表面スキンラインの方向"
-#: fdmprinter.def.json
-msgctxt "roofing_angles description"
-msgid "A list of integer line directions to use when the top surface skin layers use the lines or zig zag pattern. 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 traditional default angles (45 and 135 degrees)."
-msgstr "トップ表面層に縦かジグザグパターンを利用する時に使用する整数の行方向のリスト。リスト内から順番に使われていき、リストの最後に達するとまた最初の設定値に戻ります。リストアイテムはカンマで区切られ、全体はカッコで括られています。デフォルトでは何も入っておらず、設定角度は (45 度と 135 度)になっています。"
-
#: fdmprinter.def.json
msgctxt "top_bottom_extruder_nr label"
msgid "Top/Bottom Extruder"
@@ -1079,6 +1017,17 @@ msgctxt "wall_0_inset description"
msgid "Inset applied to the path of the outer wall. If the outer wall is smaller than the nozzle, and printed after the inner walls, use this offset to get the hole in the nozzle to overlap with the inner walls instead of the outside of the model."
msgstr "外壁の経路にはめ込む。外壁がノズルよりも小さく、内壁の後に造形されている場合は、オフセットを使用して、ノズルの穴をモデルの外側ではなく内壁と重なるようにします。"
+#: fdmprinter.def.json
+msgctxt "optimize_wall_printing_order label"
+msgid "Optimize Wall Printing Order"
+msgstr "壁印刷順序の最適化"
+
+# msgstr "壁のプリントの順番を最適化する"
+#: fdmprinter.def.json
+msgctxt "optimize_wall_printing_order description"
+msgid "Optimize the order in which walls are printed so as to reduce the number of retractions and the distance travelled. Most parts will benefit from this being enabled but some may actually take longer so please compare the print time estimates with and without optimization."
+msgstr "撤回と移動距離を減らすために、壁のプリント順序を最適化します。ほとんどの部品がこの設定を有効にしている方が良い印刷結果につながりますが、実際には時間がかかることがありますので、最適化の有無に関わらず印刷時間を比較してください。"
+
#: fdmprinter.def.json
msgctxt "outer_inset_first label"
msgid "Outer Before Inner Walls"
@@ -1149,6 +1098,16 @@ msgctxt "fill_perimeter_gaps option everywhere"
msgid "Everywhere"
msgstr "全対象"
+#: fdmprinter.def.json
+msgctxt "filter_out_tiny_gaps label"
+msgid "Filter Out Tiny Gaps"
+msgstr "小さなギャップのフィルターアウト"
+
+#: fdmprinter.def.json
+msgctxt "filter_out_tiny_gaps description"
+msgid "Filter out tiny gaps to reduce blobs on outside of model."
+msgstr "モデル外部の塊を減らすために小さなギャップをフィルターアウトします。"
+
#: fdmprinter.def.json
msgctxt "fill_outline_gaps label"
msgid "Print Thin Walls"
@@ -1220,7 +1179,9 @@ msgstr "ZシームX"
#: fdmprinter.def.json
msgctxt "z_seam_x description"
msgid "The X coordinate of the position near where to start printing each part in a layer."
-msgstr "レイヤー内の各印刷を開始するX座\n標の位置。"
+msgstr ""
+"レイヤー内の各印刷を開始するX座\n"
+"標の位置。"
#: fdmprinter.def.json
msgctxt "z_seam_y label"
@@ -1561,7 +1522,7 @@ msgstr "インフィルXオフセット"
#: fdmprinter.def.json
msgctxt "infill_offset_x description"
-msgid "The infill pattern is offset this distance along the X axis."
+msgid "The infill pattern is moved this distance along the X axis."
msgstr "インフィルパターンはX軸に沿ってこの距離を移動します。"
#: fdmprinter.def.json
@@ -1571,7 +1532,7 @@ msgstr "インフィルYオフセット"
#: fdmprinter.def.json
msgctxt "infill_offset_y description"
-msgid "The infill pattern is offset this distance along the Y axis."
+msgid "The infill pattern is moved this distance along the Y axis."
msgstr "インフィルパターンはY軸に沿ってこの距離を移動します。"
#: fdmprinter.def.json
@@ -1589,11 +1550,10 @@ msgctxt "infill_overlap label"
msgid "Infill Overlap Percentage"
msgstr "インフィル公差量"
-# msgstr "インフィルのオーバーラップ率"
#: fdmprinter.def.json
msgctxt "infill_overlap description"
-msgid "The amount of overlap between the infill and the walls. A slight overlap allows the walls to connect firmly to the infill."
-msgstr "インフィルと壁が交差する量、わずかな交差によって壁がインフィルにしっかりつながります。"
+msgid "The amount of overlap between the infill and the walls as a percentage of the infill line width. A slight overlap allows the walls to connect firmly to the infill."
+msgstr "インフィルと壁のオーバーラップ量 (インフィルライン幅に対する%)。少しのオーバーラップによって壁がインフィルにしっかりつながります。"
#: fdmprinter.def.json
msgctxt "infill_overlap_mm label"
@@ -1613,8 +1573,8 @@ msgstr "表面公差量"
#: fdmprinter.def.json
msgctxt "skin_overlap description"
-msgid "The amount of overlap between the skin and the walls as a percentage of the 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 "表面と壁の交わる量。ラインの幅の%で設定。少しの接触でしっかりと繋がります。表面と内壁の交わる量の平均値になります。"
+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 "スキンと壁のオーバーラップ量 (スキンライン幅に対する%)。少しのオーバーラップによって壁がスキンにしっかりつながります。これは、スキンライン幅の平均ライン幅と最内壁の%です。"
#: fdmprinter.def.json
msgctxt "skin_overlap_mm label"
@@ -1676,7 +1636,9 @@ msgstr "インフィル優先"
#: fdmprinter.def.json
msgctxt "infill_before_walls description"
msgid "Print the infill before printing the walls. Printing the walls first may lead to more accurate walls, but overhangs print worse. Printing the infill first leads to sturdier walls, but the infill pattern might sometimes show through the surface."
-msgstr "壁より前にインフィルをプリントします はじめに壁をプリントするとより精密な壁になりますが、オーバーハングのプリントは悪化します\nはじめにインフィルをプリントすると丈夫な壁になりますが、インフィルの模様が時折表面から透けて表れます"
+msgstr ""
+"壁より前にインフィルをプリントします はじめに壁をプリントするとより精密な壁になりますが、オーバーハングのプリントは悪化します\n"
+"はじめにインフィルをプリントすると丈夫な壁になりますが、インフィルの模様が時折表面から透けて表れます"
#: fdmprinter.def.json
msgctxt "min_infill_area label"
@@ -1783,16 +1745,6 @@ msgctxt "material description"
msgid "Material"
msgstr "マテリアル"
-#: fdmprinter.def.json
-msgctxt "material_flow_dependent_temperature label"
-msgid "Auto Temperature"
-msgstr "自動温度"
-
-#: fdmprinter.def.json
-msgctxt "material_flow_dependent_temperature description"
-msgid "Change the temperature for each layer automatically with the average flow speed of that layer."
-msgstr "その画層の平均流速で自動的にレイヤーごとに温度を変更します。"
-
#: fdmprinter.def.json
msgctxt "default_material_print_temperature label"
msgid "Default Printing Temperature"
@@ -1843,16 +1795,6 @@ msgctxt "material_final_print_temperature description"
msgid "The temperature to which to already start cooling down just before the end of printing."
msgstr "印刷終了直前に冷却を開始する温度。"
-#: fdmprinter.def.json
-msgctxt "material_flow_temp_graph label"
-msgid "Flow Temperature Graph"
-msgstr "フロー温度グラフ"
-
-#: fdmprinter.def.json
-msgctxt "material_flow_temp_graph description"
-msgid "Data linking material flow (in mm3 per second) to temperature (degrees Celsius)."
-msgstr "マテリアルフロー(毎秒 3mm) と温度 (° c) をリンクします。"
-
#: fdmprinter.def.json
msgctxt "material_extrusion_cool_down_speed label"
msgid "Extrusion Cool Down Speed Modifier"
@@ -1870,8 +1812,8 @@ msgstr "ビルドプレート温度"
#: fdmprinter.def.json
msgctxt "material_bed_temperature description"
-msgid "The temperature used for the heated build plate. If this is 0, the bed will not heat up for this print."
-msgstr "加熱式ビルドプレート温度。これが 0 の場合、ベッドは加熱しません。"
+msgid "The temperature used for the heated build plate. If this is 0, the bed temperature will not be adjusted."
+msgstr "加熱式ビルドプレート温度。これが 0 の場合、ベッド温度は調整されません。"
#: fdmprinter.def.json
msgctxt "material_bed_temperature_layer_0 label"
@@ -3586,6 +3528,17 @@ msgctxt "support_tower_roof_angle description"
msgid "The angle of a rooftop of a tower. A higher value results in pointed tower roofs, a lower value results in flattened tower roofs."
msgstr "タワーの屋上の角度。値が高いほど尖った屋根が得られ、値が低いほど屋根が平らになります。"
+#: fdmprinter.def.json
+msgctxt "support_mesh_drop_down label"
+msgid "Drop Down Support Mesh"
+msgstr "サポートメッシュの下処理"
+
+# msgstr "ドロップダウンサポートメッシュ"
+#: fdmprinter.def.json
+msgctxt "support_mesh_drop_down description"
+msgid "Make support everywhere below the support mesh, so that there's no overhang in the support mesh."
+msgstr "サポートメッシュの下のサポート材を全箇所に作ります、これはサポートメッシュ下にてオーバーハングしないようにするためです。"
+
#: fdmprinter.def.json
msgctxt "platform_adhesion label"
msgid "Build Plate Adhesion"
@@ -3599,7 +3552,7 @@ msgstr "密着性"
#: fdmprinter.def.json
msgctxt "prime_blob_enable label"
msgid "Enable Prime Blob"
-msgstr "プライムボルブを有効にする"
+msgstr "プライムブロブを有効にする"
# msgstr "プライムブロブを有効にする"
#: fdmprinter.def.json
@@ -3691,7 +3644,9 @@ msgctxt "skirt_gap description"
msgid ""
"The horizontal distance between the skirt and the first layer of the print.\n"
"This is the minimum distance. Multiple skirt lines will extend outwards from this distance."
-msgstr "スカートと印刷の最初の層の間の水平距離。\nこれは最小距離です。複数のスカートラインがこの距離から外側に展開されます。"
+msgstr ""
+"スカートと印刷の最初の層の間の水平距離。\n"
+"これは最小距離です。複数のスカートラインがこの距離から外側に展開されます。"
#: fdmprinter.def.json
msgctxt "skirt_brim_minimal_length label"
@@ -4224,16 +4179,6 @@ msgctxt "meshfix_keep_open_polygons description"
msgid "Normally Cura tries to stitch up small holes in the mesh and remove parts of a layer with big holes. Enabling this option keeps those parts which cannot be stitched. This option should be used as a last resort option when everything else fails to produce proper GCode."
msgstr "通常、Curaはメッシュ内の小さな穴をスティッチし、大きな穴のあるレイヤーの部分を削除しようとします。このオプションを有効にすると、スティッチできない部分が保持されます。このオプションは、他のすべてが適切なGCodeを生成できない場合の最後の手段として使用する必要があります。"
-#: fdmprinter.def.json
-msgctxt "meshfix_maximum_resolution label"
-msgid "Maximum Resolution"
-msgstr "最大解像度"
-
-#: fdmprinter.def.json
-msgctxt "meshfix_maximum_resolution description"
-msgid "The minimum size of a line segment after slicing. If you increase this, the mesh will have a lower resolution. This may allow the printer to keep up with the speed it has to process g-code and will increase slice speed by removing details of the mesh that it can't process anyway."
-msgstr "スライス後の線分の最小サイズ。これを増やすと、メッシュの解像度が低くなります。これにより、プリンタが g コードの処理速度に追いつくことができ、処理できないメッシュの詳細を取り除いてスライス速度を速めます。"
-
#: fdmprinter.def.json
msgctxt "multiple_mesh_overlap label"
msgid "Merged Meshes Overlap"
@@ -4389,17 +4334,6 @@ msgctxt "support_mesh description"
msgid "Use this mesh to specify support areas. This can be used to generate support structure."
msgstr "このメッシュを使用してサポート領域を指定します。これは、サポート構造を生成するために使用できます。"
-#: fdmprinter.def.json
-msgctxt "support_mesh_drop_down label"
-msgid "Drop Down Support Mesh"
-msgstr "サポートメッシュの下処理"
-
-# msgstr "ドロップダウンサポートメッシュ"
-#: fdmprinter.def.json
-msgctxt "support_mesh_drop_down description"
-msgid "Make support everywhere below the support mesh, so that there's no overhang in the support mesh."
-msgstr "サポートメッシュの下のサポート材を全箇所に作ります、これはサポートメッシュ下にてオーバーハングしないようにするためです。"
-
#: fdmprinter.def.json
msgctxt "anti_overhang_mesh label"
msgid "Anti Overhang Mesh"
@@ -4478,15 +4412,200 @@ msgid "experimental!"
msgstr "実験的"
#: fdmprinter.def.json
-msgctxt "optimize_wall_printing_order label"
-msgid "Optimize Wall Printing Order"
-msgstr "壁印刷順序の最適化"
+msgctxt "support_tree_enable label"
+msgid "Tree Support"
+msgstr "ツリーサポート"
-# msgstr "壁のプリントの順番を最適化する"
#: fdmprinter.def.json
-msgctxt "optimize_wall_printing_order description"
-msgid "Optimize the order in which walls are printed so as to reduce the number of retractions and the distance travelled. Most parts will benefit from this being enabled but some may actually take longer so please compare the print time estimates with and without optimization."
-msgstr "撤回と移動距離を減らすために、壁のプリント順序を最適化します。ほとんどの部品がこの設定を有効にしている方が良い印刷結果につながりますが、実際には時間がかかることがありますので、最適化の有無に関わらず印刷時間を比較してください。"
+msgctxt "support_tree_enable description"
+msgid "Generate a tree-like support with branches that support your print. This may reduce material usage and print time, but greatly increases slicing time."
+msgstr "プリントを支えるために枝のついた木のようなサポートを生成します。材料とプリント時間が減る可能性がありますが、スライス時間が大きく増加します。"
+
+#: fdmprinter.def.json
+msgctxt "support_tree_angle label"
+msgid "Tree Support Branch Angle"
+msgstr "ツリーサポート枝角度"
+
+#: fdmprinter.def.json
+msgctxt "support_tree_angle description"
+msgid "The angle of the branches. Use a lower angle to make them more vertical and more stable. Use a higher angle to be able to have more reach."
+msgstr "枝の角度。枝を垂直で安定したものにするためには小さい角度を使用します。高さを得るためには大きい角度を使用します。"
+
+#: fdmprinter.def.json
+msgctxt "support_tree_branch_distance label"
+msgid "Tree Support Branch Distance"
+msgstr "ツリーサポート枝間隔"
+
+#: fdmprinter.def.json
+msgctxt "support_tree_branch_distance description"
+msgid "How far apart the branches need to be when they touch the model. Making this distance small will cause the tree support to touch the model at more points, causing better overhang but making support harder to remove."
+msgstr "枝がモデルに接触するところで確保する枝の間隔。この間隔を小さくするとツリーサポートがモデルに接触する点が増え、支える効果が高まりますが、サポートの取り外しが難しくなります。"
+
+#: fdmprinter.def.json
+msgctxt "support_tree_branch_diameter label"
+msgid "Tree Support Branch Diameter"
+msgstr "ツリーサポート枝直径"
+
+#: fdmprinter.def.json
+msgctxt "support_tree_branch_diameter description"
+msgid "The diameter of the thinnest branches of tree support. Thicker branches are more sturdy. Branches towards the base will be thicker than this."
+msgstr "ツリーサポートの最も細い枝の直径。枝は太いほど丈夫です。基部に近いところでは、枝はこれよりも太くなります。"
+
+#: fdmprinter.def.json
+msgctxt "support_tree_branch_diameter_angle label"
+msgid "Tree Support Branch Diameter Angle"
+msgstr "ツリーサポート枝直径角度"
+
+#: fdmprinter.def.json
+msgctxt "support_tree_branch_diameter_angle description"
+msgid "The angle of the branches' diameter as they gradually become thicker towards the bottom. An angle of 0 will cause the branches to have uniform thickness over their length. A bit of an angle can increase stability of the tree support."
+msgstr "基部に向かって徐々に太くなる枝の直径の角度。角度が0の場合、枝の太さは全長にわたって同じになります。少し角度を付けると、ツリーサポートの安定性が高まります。"
+
+#: fdmprinter.def.json
+msgctxt "support_tree_collision_resolution label"
+msgid "Tree Support Collision Resolution"
+msgstr "ツリーサポート衝突精細度"
+
+#: fdmprinter.def.json
+msgctxt "support_tree_collision_resolution description"
+msgid "Resolution to compute collisions with to avoid hitting the model. Setting this lower will produce more accurate trees that fail less often, but increases slicing time dramatically."
+msgstr "モデルに干渉しないようにする衝突計算の精細度。小さい値を設定すると、失敗の少ない正確なツリーが生成されますが、スライス時間は大きく増加します。"
+
+#: fdmprinter.def.json
+msgctxt "support_tree_wall_thickness label"
+msgid "Tree Support Wall Thickness"
+msgstr "ツリーサポート壁厚"
+
+#: fdmprinter.def.json
+msgctxt "support_tree_wall_thickness description"
+msgid "The thickness of the walls of the branches of tree support. Thicker walls take longer to print but don't fall over as easily."
+msgstr "ツリーサポートの枝の壁の厚さ。壁が厚いほどプリント時間が長くなりますが、崩れにくくなります。"
+
+#: fdmprinter.def.json
+msgctxt "support_tree_wall_count label"
+msgid "Tree Support Wall Line Count"
+msgstr "ツリーサポートウォールライン数"
+
+#: fdmprinter.def.json
+msgctxt "support_tree_wall_count description"
+msgid "The number of walls of the branches of tree support. Thicker walls take longer to print but don't fall over as easily."
+msgstr "ツリーサポートの枝の壁の数。壁が厚いほどプリント時間が長くなりますが、崩れにくくなります。"
+
+#: fdmprinter.def.json
+msgctxt "slicing_tolerance label"
+msgid "Slicing Tolerance"
+msgstr "スライス公差"
+
+#: fdmprinter.def.json
+msgctxt "slicing_tolerance description"
+msgid "How to slice layers with diagonal surfaces. The areas of a layer can be generated based on where the middle of the layer intersects the surface (Middle). Alternatively each layer can have the areas which fall inside of the volume throughout the height of the layer (Exclusive) or a layer has the areas which fall inside anywhere within the layer (Inclusive). Exclusive retains the most details, Inclusive makes for the best fit and Middle takes the least time to process."
+msgstr "表面を斜めにスライスする方法を指定します。レイヤーの領域は、レイヤーの中央がサーフェス(中央)と交差する位置に基づいて生成できます。また、各層は、レイヤーの高さを通してボリュームの内側に収まる領域を持つ(排他)か、またはレイヤー内の任意の場所内に収まる領域を持っています(包括)。排他は最も細かく、包括は最もフィットし、中間は時間がかかります。"
+
+#: fdmprinter.def.json
+msgctxt "slicing_tolerance option middle"
+msgid "Middle"
+msgstr "中間"
+
+#: fdmprinter.def.json
+msgctxt "slicing_tolerance option exclusive"
+msgid "Exclusive"
+msgstr "排他"
+
+#: fdmprinter.def.json
+msgctxt "slicing_tolerance option inclusive"
+msgid "Inclusive"
+msgstr "包括"
+
+#: fdmprinter.def.json
+msgctxt "roofing_line_width label"
+msgid "Top Surface Skin Line Width"
+msgstr "最上面のライン幅"
+
+# msgstr "上表面スキンの線幅"
+#: fdmprinter.def.json
+msgctxt "roofing_line_width description"
+msgid "Width of a single line of the areas at the top of the print."
+msgstr "プリントの上部の 線の幅。"
+
+#: fdmprinter.def.json
+msgctxt "roofing_pattern label"
+msgid "Top Surface Skin Pattern"
+msgstr "上部表面パターン"
+
+# msgstr "上層表面スキンパターン"
+#: fdmprinter.def.json
+msgctxt "roofing_pattern description"
+msgid "The pattern of the top most layers."
+msgstr "上層のパターン"
+
+#: fdmprinter.def.json
+msgctxt "roofing_pattern option lines"
+msgid "Lines"
+msgstr "直線"
+
+# msgstr "線"
+#: fdmprinter.def.json
+msgctxt "roofing_pattern option concentric"
+msgid "Concentric"
+msgstr "同心円"
+
+# msgstr "同心"
+#: fdmprinter.def.json
+msgctxt "roofing_pattern option zigzag"
+msgid "Zig Zag"
+msgstr "ジグザグ"
+
+# msgstr "ジグザグ"
+#: fdmprinter.def.json
+msgctxt "roofing_angles label"
+msgid "Top Surface Skin Line Directions"
+msgstr "最上面のラインの向き"
+
+# msgstr "上層表面スキンラインの方向"
+#: fdmprinter.def.json
+msgctxt "roofing_angles description"
+msgid "A list of integer line directions to use when the top surface skin layers use the lines or zig zag pattern. 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 traditional default angles (45 and 135 degrees)."
+msgstr "トップ表面層に縦かジグザグパターンを利用する時に使用する整数の行方向のリスト。リスト内から順番に使われていき、リストの最後に達するとまた最初の設定値に戻ります。リストアイテムはカンマで区切られ、全体はカッコで括られています。デフォルトでは何も入っておらず、設定角度は (45 度と 135 度)になっています。"
+
+#: fdmprinter.def.json
+msgctxt "infill_enable_travel_optimization label"
+msgid "Infill Travel Optimization"
+msgstr "インフィル移動最適化"
+
+#: fdmprinter.def.json
+msgctxt "infill_enable_travel_optimization description"
+msgid "When enabled, the order in which the infill lines are printed is optimized to reduce the distance travelled. The reduction in travel time achieved very much depends on the model being sliced, infill pattern, density, etc. Note that, for some models that have many small areas of infill, the time to slice the model may be greatly increased."
+msgstr "有効化すると、移動距離が減少するようにインフィルラインをプリントする順序が最適化されます。移動時間の削減は、スライスするモデル、インフィルパターン、密度などに大きく依存します。特に、インフィルを行う小さなエリアが多数あるモデルの場合、モデルをスライスする時間が大きく増えることがあります。"
+
+#: fdmprinter.def.json
+msgctxt "material_flow_dependent_temperature label"
+msgid "Auto Temperature"
+msgstr "自動温度"
+
+#: fdmprinter.def.json
+msgctxt "material_flow_dependent_temperature description"
+msgid "Change the temperature for each layer automatically with the average flow speed of that layer."
+msgstr "その画層の平均流速で自動的にレイヤーごとに温度を変更します。"
+
+#: fdmprinter.def.json
+msgctxt "material_flow_temp_graph label"
+msgid "Flow Temperature Graph"
+msgstr "フロー温度グラフ"
+
+#: fdmprinter.def.json
+msgctxt "material_flow_temp_graph description"
+msgid "Data linking material flow (in mm3 per second) to temperature (degrees Celsius)."
+msgstr "マテリアルフロー(毎秒 3mm) と温度 (° c) をリンクします。"
+
+#: fdmprinter.def.json
+msgctxt "meshfix_maximum_resolution label"
+msgid "Maximum Resolution"
+msgstr "最大解像度"
+
+#: fdmprinter.def.json
+msgctxt "meshfix_maximum_resolution description"
+msgid "The minimum size of a line segment after slicing. If you increase this, the mesh will have a lower resolution. This may allow the printer to keep up with the speed it has to process g-code and will increase slice speed by removing details of the mesh that it can't process anyway."
+msgstr "スライス後の線分の最小サイズ。これを増やすと、メッシュの解像度が低くなります。これにより、プリンタが g コードの処理速度に追いつくことができ、処理できないメッシュの詳細を取り除いてスライス速度を速めます。"
#: fdmprinter.def.json
msgctxt "support_skip_some_zags label"
@@ -5097,6 +5216,46 @@ msgctxt "wireframe_nozzle_clearance description"
msgid "Distance between the nozzle and horizontally downward lines. Larger clearance results in diagonally downward lines with a less steep angle, which in turn results in less upward connections with the next layer. Only applies to Wire Printing."
msgstr "ノズルと水平方向に下向きの線間の距離。大きな隙間がある場合、急な角度で斜め下方線となり、次の層が上方接続しずらくなる。ワイヤ印刷にのみ適用されます。"
+#: fdmprinter.def.json
+msgctxt "adaptive_layer_height_enabled label"
+msgid "Use adaptive layers"
+msgstr "適応レイヤーの使用"
+
+#: fdmprinter.def.json
+msgctxt "adaptive_layer_height_enabled description"
+msgid "Adaptive layers computes the layer heights depending on the shape of the model."
+msgstr "適応レイヤーは、レイヤーの高さをモデルの形状に合わせて計算します。"
+
+#: fdmprinter.def.json
+msgctxt "adaptive_layer_height_variation label"
+msgid "Adaptive layers maximum variation"
+msgstr "適応レイヤー最大差分"
+
+#: fdmprinter.def.json
+msgctxt "adaptive_layer_height_variation description"
+msgid "The maximum allowed height different from the base layer height in mm."
+msgstr "基準レイヤー高さと比較して許容される最大の高さ (mm)。"
+
+#: fdmprinter.def.json
+msgctxt "adaptive_layer_height_variation_step label"
+msgid "Adaptive layers variation step size"
+msgstr "適応レイヤー差分ステップサイズ"
+
+#: fdmprinter.def.json
+msgctxt "adaptive_layer_height_variation_step description"
+msgid "The difference in height of the next layer height compared to the previous one."
+msgstr "次のレイヤーの高さを前のレイヤーの高さと比べた差。"
+
+#: fdmprinter.def.json
+msgctxt "adaptive_layer_height_threshold label"
+msgid "Adaptive layers threshold"
+msgstr "適応レイヤー閾値"
+
+#: fdmprinter.def.json
+msgctxt "adaptive_layer_height_threshold description"
+msgid "Threshold whether to use a smaller layer or not. This number is compared to the tan of the steepest slope in a layer."
+msgstr "小さいレイヤーを使用するかどうかの閾値。この値が、レイヤー中の最も急な斜面のタンジェントと比較されます。"
+
#: fdmprinter.def.json
msgctxt "command_line_settings label"
msgid "Command Line Settings"
@@ -5157,6 +5316,27 @@ msgctxt "mesh_rotation_matrix description"
msgid "Transformation matrix to be applied to the model when loading it from file."
msgstr "ファイルから読み込むときに、モデルに適用するトランスフォーメーションマトリックス。"
+#~ msgctxt "infill_offset_x description"
+#~ msgid "The infill pattern is offset this distance along the X axis."
+#~ msgstr "インフィルパターンはX軸に沿ってこの距離を移動します。"
+
+#~ msgctxt "infill_offset_y description"
+#~ msgid "The infill pattern is offset this distance along the Y axis."
+#~ msgstr "インフィルパターンはY軸に沿ってこの距離を移動します。"
+
+# msgstr "インフィルのオーバーラップ率"
+#~ msgctxt "infill_overlap description"
+#~ msgid "The amount of overlap between the infill and the walls. A slight overlap allows the walls to connect firmly to the infill."
+#~ msgstr "インフィルと壁が交差する量、わずかな交差によって壁がインフィルにしっかりつながります。"
+
+#~ msgctxt "skin_overlap description"
+#~ msgid "The amount of overlap between the skin and the walls as a percentage of the 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 "表面と壁の交わる量。ラインの幅の%で設定。少しの接触でしっかりと繋がります。表面と内壁の交わる量の平均値になります。"
+
+#~ msgctxt "material_bed_temperature description"
+#~ msgid "The temperature used for the heated build plate. If this is 0, the bed will not heat up for this print."
+#~ msgstr "加熱式ビルドプレート温度。これが 0 の場合、ベッドは加熱しません。"
+
#~ 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, cubic, octet, quarter cubic 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 "印刷物のインフィルのパターン。線とジグザグのインフィルはレイヤーごとに交互に方向を変え、材料費を削減します。グリッド、三角形、キュービック、オクテット、クォーターキュービック、同心円のパターンは、すべてのレイヤーにて完全に印刷されます。キュービック、クォーターキュービック、オクテットのインフィルは各レイヤーごとに変化し、各方向の強度が均等になるように分布します。"
diff --git a/resources/i18n/ko_KR/cura.po b/resources/i18n/ko_KR/cura.po
index a72274dc2c..f63d7ba64f 100644
--- a/resources/i18n/ko_KR/cura.po
+++ b/resources/i18n/ko_KR/cura.po
@@ -1,16 +1,16 @@
# Cura
-# Copyright (C) 2017 Ultimaker
+# Copyright (C) 2018 Ultimaker
# This file is distributed under the same license as the Cura package.
-# Ruben Dulek , 2017.
-#
+# Ruben Dulek , 2018.
+#
msgid ""
msgstr ""
-"Project-Id-Version: Cura 3.1\n"
+"Project-Id-Version: Cura 3.2\n"
"Report-Msgid-Bugs-To: r.dulek@ultimaker.com\n"
-"POT-Creation-Date: 2017-11-21 16:58+0100\n"
-"PO-Revision-Date: 2017-11-30 13:05+0100\n"
-"Last-Translator: Brule\n"
-"Language-Team: Brule\n"
+"POT-Creation-Date: 2018-01-29 09:48+0000\n"
+"PO-Revision-Date: 2018-02-05 13:25+0100\n"
+"Last-Translator: Bothof \n"
+"Language-Team: Korean\n"
"Language: ko_KR\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
@@ -18,7 +18,7 @@ msgstr ""
"Plural-Forms: nplurals=1; plural=0;\n"
"X-Generator: Poedit 2.0.4\n"
-#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.py:29
+#: /home/ruben/Projects/Cura/plugins/MachineSettingsAction/MachineSettingsAction.py:26
msgctxt "@action"
msgid "Machine Settings"
msgstr "기계 설정"
@@ -55,12 +55,11 @@ msgstr "Doodle3D Connect에 연결"
#: /home/ruben/Projects/Cura/plugins/Doodle3D-cura-plugin/Doodle3D/D3DCloudPrintOutputDevicePlugin.py:87
#: /home/ruben/Projects/Cura/plugins/Doodle3D-cura-plugin/Doodle3D/D3DCloudPrintOutputDevicePlugin.py:155
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:874
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:646
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:875
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:659
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/DiscoverUM3Action.qml:370
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/PrintWindow.qml:78
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/ConfigDialog.qml:104
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/ExportSTLUI.qml:99
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksConfiguration.qml:355
#: /home/ruben/Projects/Cura/plugins/ImageReader/ConfigUI.qml:188
#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.qml:376
#: /home/ruben/Projects/Cura/plugins/PluginBrowser/PluginBrowser.qml:139
@@ -100,7 +99,7 @@ msgctxt "@info:tooltip"
msgid "Open the Doodle3D Connect web interface"
msgstr "Doodle3D Connect 웹 인터페이스 열기"
-#: /home/ruben/Projects/Cura/plugins/ChangeLogPlugin/ChangeLog.py:34
+#: /home/ruben/Projects/Cura/plugins/ChangeLogPlugin/ChangeLog.py:33
msgctxt "@item:inmenu"
msgid "Show Changelog"
msgstr "변경 내역 표시"
@@ -115,78 +114,83 @@ msgctxt "@info:status"
msgid "Profile has been flattened & activated."
msgstr "프로필이 병합되고 활성화되었습니다."
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:26
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:27
msgctxt "@item:inmenu"
msgid "USB printing"
msgstr "USB 인쇄"
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:27
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:28
msgctxt "@action:button Preceded by 'Ready to'."
msgid "Print via USB"
msgstr "USB를 통해 인쇄"
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:28
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:29
msgctxt "@info:tooltip"
msgid "Print via USB"
msgstr "USB를 통해 인쇄"
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:30
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:31
msgctxt "@info:status"
msgid "Connected via USB"
msgstr "USB를 통해 연결"
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:154
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:183
msgctxt "@info:status"
msgid "Unable to start a new job because the printer is busy or not connected."
msgstr "프린터가 사용 중이거나 연결되어 있지 않아 새 작업을 시작할 수 없습니다."
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:154
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:183
msgctxt "@info:title"
msgid "Printer Unavailable"
msgstr "프린터 사용 불가"
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:457
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:485
msgctxt "@info:status"
msgid "This printer does not support USB printing because it uses UltiGCode flavor."
msgstr "이 프린터는 UltiGCode flavor를 사용하기 때문에 USB 인쇄를 지원하지 않습니다."
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:457
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:485
msgctxt "@info:title"
msgid "USB Printing"
msgstr "USB 인쇄"
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:461
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:489
msgctxt "@info:status"
msgid "Unable to start a new job because the printer does not support usb printing."
msgstr "프린터가 USB 인쇄를 지원하지 않기 때문에 새 작업을 시작할 수 없습니다."
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:461
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDeviceManager.py:108
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDevice.py:489
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDeviceManager.py:103
#: /home/ruben/Projects/Cura/plugins/RemovableDriveOutputDevice/RemovableDriveOutputDevice.py:146
#: /home/ruben/Projects/Cura/plugins/RemovableDriveOutputDevice/RemovableDriveOutputDevice.py:158
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:945
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1349
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1417
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:946
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1418
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1496
msgctxt "@info:title"
msgid "Warning"
msgstr "경고"
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDeviceManager.py:108
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDeviceManager.py:103
msgctxt "@info"
msgid "Unable to update firmware because there are no printers connected."
msgstr "프린터가 연결되어 있지 않으므로 펌웨어를 업데이트 할 수 없습니다."
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDeviceManager.py:122
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDeviceManager.py:117
#, python-format
msgctxt "@info"
msgid "Could not find firmware required for the printer at %s."
msgstr "프린터에 필요한 펌웨어를 찾을 수 없습니다."
-#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDeviceManager.py:122
+#: /home/ruben/Projects/Cura/plugins/USBPrinting/USBPrinterOutputDeviceManager.py:117
msgctxt "@info:title"
msgid "Printer Firmware"
msgstr "프린터 펌웨어"
+#: /home/ruben/Projects/Cura/plugins/PrepareStage/__init__.py:12
+msgctxt "@item:inmenu"
+msgid "Prepare"
+msgstr "준비"
+
#: /home/ruben/Projects/Cura/plugins/RemovableDriveOutputDevice/RemovableDriveOutputDevice.py:23
msgctxt "@action:button Preceded by 'Ready to'."
msgid "Save to Removable Drive"
@@ -230,11 +234,11 @@ msgid "Could not save to removable drive {0}: {1}"
msgstr "이동식 드라이브에 저장할 수 없습니다 :"
#: /home/ruben/Projects/Cura/plugins/RemovableDriveOutputDevice/RemovableDriveOutputDevice.py:132
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:692
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:700
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:146
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:693
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:701
#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:153
-#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1358
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:160
+#: /home/ruben/Projects/Cura/cura/CuraApplication.py:1427
msgctxt "@info:title"
msgid "Error"
msgstr "에러"
@@ -284,7 +288,7 @@ msgid "Removable Drive"
msgstr "이동식 드라이브"
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:109
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:53
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:51
msgctxt "@action:button Preceded by 'Ready to'."
msgid "Print over network"
msgstr "네트워크를 통해 인쇄"
@@ -398,110 +402,110 @@ msgctxt "@info:title"
msgid "Printer Status"
msgstr "프린터 상태"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:691
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:692
#, python-brace-format
msgctxt "@info:status"
msgid "Unable to start a new print job. No Printcore loaded in slot {0}"
msgstr "새 인쇄 작업을 시작할 수 없습니다. 슬롯 {0}에로드 된 Printcore가 없습니다."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:699
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:700
#, python-brace-format
msgctxt "@info:status"
msgid "Unable to start a new print job. No material loaded in slot {0}"
msgstr "새 인쇄 작업을 시작할 수 없습니다. 슬롯 {0}에로드 된 자료 없음"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:709
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:710
#, python-brace-format
msgctxt "@label"
msgid "Not enough material for spool {0}."
msgstr "스풀 {0}의 재료가 충분하지 않습니다."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:719
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:720
#, python-brace-format
msgctxt "@label"
msgid "Different PrintCore (Cura: {0}, Printer: {1}) selected for extruder {2}"
msgstr "압출기 {2}에 대해 선택된 다른 PrintCore (Cura : {0}, Printer : {1})"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:733
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:734
#, python-brace-format
msgctxt "@label"
msgid "Different material (Cura: {0}, Printer: {1}) selected for extruder {2}"
msgstr "압출기 {2}에 대해 선택된 다른 재료 (Cura : {0}, Printer : {1})"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:741
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:742
#, python-brace-format
msgctxt "@label"
msgid "PrintCore {0} is not properly calibrated. XY calibration needs to be performed on the printer."
msgstr "PrintCore가 올바르게 조정되지 않았습니다. XY 교정은 프린터에서 수행해야합니다."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:746
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:747
msgctxt "@label"
msgid "Are you sure you wish to print with the selected configuration?"
msgstr "선택한 구성으로 인쇄 하시겠습니까?"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:747
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:748
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 "프린터 및 Cura의 구성 또는 교정간에 불일치가 있습니다. 최상의 결과를 얻으려면 프린터에 삽입 된 PrintCores 및 재료를 항상 슬라이스하십시오."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:753
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:754
msgctxt "@window:title"
msgid "Mismatched configuration"
msgstr "일치하지 않는 구성"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:864
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:262
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:865
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:258
msgctxt "@info:status"
msgid "Sending new jobs (temporarily) blocked, still sending the previous print job."
msgstr "새 작업 전송 (일시적)이 차단되어 이전 인쇄 작업을 계속 보냅니다."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:873
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:874
msgctxt "@info:status"
msgid "Sending data to printer"
msgstr "프린터로 데이터 보내기"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:873
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:874
msgctxt "@info:title"
msgid "Sending Data"
msgstr "데이터 전송 중"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:944
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:945
msgctxt "@info:status"
msgid "Unable to send data to printer. Is another job still active?"
msgstr "프린터로 데이터를 보낼 수 없습니다. 다른 작업이 여전히 작동중인가요?"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:1085
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:1087
#: /home/ruben/Projects/Cura/resources/qml/Preferences/MachinesPage.qml:196
msgctxt "@label:MonitorStatus"
msgid "Aborting print..."
msgstr "인쇄 중단 중 ..."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:1091
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:1093
msgctxt "@label:MonitorStatus"
msgid "Print aborted. Please check the printer"
msgstr "인쇄가 중단되었습니다. 프린터를 확인하십시오"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:1097
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:1099
msgctxt "@label:MonitorStatus"
msgid "Pausing print..."
msgstr "인쇄 일시 중지 중 ..."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:1099
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:1101
msgctxt "@label:MonitorStatus"
msgid "Resuming print..."
msgstr "인쇄 재개 중 ..."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:1289
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:1291
msgctxt "@window:title"
msgid "Sync with your printer"
msgstr "프린터와 동기화"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:1291
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:1293
msgctxt "@label"
msgid "Would you like to use your current printer configuration in Cura?"
msgstr "Cura에서 현재 프린터 구성을 사용 하시겠습니까?"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:1293
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py:1295
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 "프린터의 PrintCores 및 / 또는 자료는 현재 프로젝트 내의 자료와 다릅니다. 최상의 결과를 얻으려면 프린터에 삽입 된 PrintCores 및 재료를 항상 슬라이스하십시오."
@@ -522,145 +526,188 @@ msgid "{printer_name} has finished printing '{job_name}'. Please collect the pri
msgstr "인쇄를 완료했습니다. 인쇄물을 수거하고 빌드 플레이트를 지우십시오."
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:115
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:520
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:533
#, python-brace-format
msgid "{printer_name} is reserved to print '{job_name}'. Please change the printer's configuration to match the job, for it to start printing."
msgstr "?을 인쇄하기 위해 예약되어 있습니다. 인쇄를 시작하려면 프린터의 구성을 작업에 맞게 변경하십시오."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:278
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:277
msgctxt "@info:status"
msgid "Unable to send new print job: this 3D printer is not (yet) set up to host a group of connected Ultimaker 3 printers."
msgstr "새로운 인쇄 작업을 보낼 수 없습니다 :이 3D 프린터는 아직 연결된 Ultimaker 3 프린터 그룹을 호스트하도록 설정되지 않았습니다."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:410
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:423
#, python-brace-format
msgctxt "@info:status"
msgid "Unable to send print job to group {cluster_name}."
msgstr "{cluster_name} 그룹에 인쇄 작업을 보낼 수 없습니다."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:418
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:431
#, python-brace-format
msgctxt "@info:status"
msgid "Sent {file_name} to group {cluster_name}."
msgstr "파일이름을 cluster_name 그룹에 보냈습니다."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:423
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:436
msgctxt "@action:button"
msgid "Show print jobs"
msgstr "인쇄 작업 표시"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:424
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:437
msgctxt "@info:tooltip"
msgid "Opens the print jobs interface in your browser."
msgstr "브라우저에서 인쇄 작업 인터페이스를 엽니다."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:489
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:502
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/DiscoverUM3Action.qml:239
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/PrinterInfoBlock.qml:47
-msgctxt "@label"
+msgctxt "@label Printer name"
msgid "Unknown"
-msgstr "알 수 없는"
+msgstr "알 수 없음"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:492
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:505
#, fuzzy, python-brace-format
msgctxt "@info:status"
msgid "Printer '{printer_name}' has finished printing '{job_name}'."
msgstr "프린터가 인쇄를 완료했습니다."
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:494
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:497
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:507
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:510
msgctxt "@info:status"
msgid "Print finished"
msgstr "프린트가 완료됐습니다"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:522
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:525
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:535
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:538
#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/PrinterInfoBlock.qml:282
msgctxt "@label:status"
msgid "Action required"
msgstr "필요한 조치"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:643
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py:656
#, python-brace-format
msgctxt "@info:progress"
msgid "Sending {file_name} to group {cluster_name}"
msgstr "{filename} {file_name} filename>을 {cluster_name} 그룹에 보냄"
-#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/DiscoverUM3Action.py:19
+#: /home/ruben/Projects/Cura/plugins/UM3NetworkPrinting/DiscoverUM3Action.py:17
msgctxt "@action"
msgid "Connect via Network"
msgstr "네트워크를 통해 연결"
-#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py:64
+#: /home/ruben/Projects/Cura/plugins/MonitorStage/__init__.py:12
+msgctxt "@item:inmenu"
+msgid "Monitor"
+msgstr "모니터"
+
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py:66
#, 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 "{machine_name}의 새로운 기능을 사용할 수 있습니다! 프린터의 펌웨어를 업데이트하는 것이 좋습니다."
-#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py:65
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py:67
#, 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:66
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py:68
msgctxt "@action:button"
msgid "How to update"
msgstr "업데이트 방법"
-#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py:77
+#: /home/ruben/Projects/Cura/plugins/FirmwareUpdateChecker/FirmwareUpdateCheckerJob.py:79
msgctxt "@info"
msgid "Could not access update information."
msgstr "업데이트 정보에 액세스 할 수 없습니다."
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksReader.py:199
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksReader.py:579
msgctxt "@info:status"
-msgid "Errors appeared while opening your SolidWorks file! Please check, whether it is possible to open your file in SolidWorks itself without any problems as well!"
-msgstr "SolidWorks 파일을 여는 중 오류가 발생했습니다! 문제없이 SolidWorks에서 파일을 열 수 있는지 확인하십시오"
+msgid "SolidWorks reported errors, while opening your file. We recommend to solve these issues inside SolidWorks itself."
+msgstr "파일을 여는 도중 SolidWorks가 오류 보고. SolidWorks 자체에서 이 문제를 해결하도록 권장합니다."
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/__init__.py:31
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksReader.py:591
+msgctxt "@info:status"
+msgid ""
+"Found no models inside your drawing. Could you please check it's content again and make sure one part or assembly is inside?\n"
+"\n"
+" Thanks!."
+msgstr "도면에 모델이 없습니다. 내용을 다시 확인하시고 내부에 하나의 부품이나 조립만 있는지 확인하시겠습니까?\n\n 감사합니다!."
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksReader.py:595
+msgctxt "@info:status"
+msgid ""
+"Found more then one part or assembly inside your drawing. We currently only support drawings with exactly one part or assembly inside.\n"
+"\n"
+"Sorry!"
+msgstr "도면에 하나 이상의 부품 또는 조립이 있습니다. 저희는 현재 정확하게 하나의 부품 또는 조립만 있는 도면을 지원합니다.\n\n죄송합니다!"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/__init__.py:25
msgctxt "@item:inlistbox"
msgid "SolidWorks part file"
msgstr "SolidWorks 파트 파일"
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/__init__.py:35
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/__init__.py:29
msgctxt "@item:inlistbox"
msgid "SolidWorks assembly file"
msgstr "SolidWorks 어셈블리 파일"
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/ConfigDialog.py:21
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/__init__.py:33
+msgctxt "@item:inlistbox"
+msgid "SolidWorks drawing file"
+msgstr "SolidWorks 도면 파일"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/__init__.py:48
+msgctxt "@info:status"
+msgid ""
+"Dear customer,\n"
+"We could not find a valid installation of SolidWorks on your system. That means that either SolidWorks is not installed or you don't own an valid license. Please make sure that running SolidWorks itself works without issues and/or contact your ICT.\n"
+"\n"
+"With kind regards\n"
+" - Thomas Karl Pietrowski"
+msgstr "안녕하십니까,\n귀하의 시스템에 유효한 SolidWorks를 찾을 수 없습니다. 이는 곧 SolidWorks가 설치되어 있지 않거나 유효한 라이센스가 없음을 의미합니다. SolidWorks가 문제없이 실행될 수 있도록 해주시고 그리고/또는 귀사의 ICT에 연락해 주십시오.\n\n감사합니다.\n - Thomas Karl Pietrowski"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/__init__.py:57
+msgctxt "@info:status"
+msgid ""
+"Dear customer,\n"
+"You are currently running this plugin on an operating system other than Windows. This plugin will only work on Windows with SolidWorks installed, including an valid license. Please install this plugin on a Windows machine with SolidWorks installed.\n"
+"\n"
+"With kind regards\n"
+" - Thomas Karl Pietrowski"
+msgstr "안녕하십니까,\n귀하는 현재 Windows가 아닌 다른 운영 시스템에서 이 플러그인을 실행 중입니다. 이 플러그인은 유효한 라이센스가 있는 SolidWorks가 설치된 Windows에서만 사용 가능합니다. 이 플러그인을 SolidWorks가 설치된 Windows 컴퓨터에 설치하십시오.\n\n감사합니다\n - Thomas Karl Pietrowski"
+
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksDialogHandler.py:70
msgid "Configure"
msgstr "구성"
-#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/CommonComReader.py:135
-#, python-format
-msgctxt "@info:status"
-msgid "Error while starting %s!"
-msgstr "시작하는 도중 오류가 발생했습니다!"
+#: /home/ruben/Projects/Cura/plugins/CuraSolidWorksPlugin/SolidWorksDialogHandler.py:71
+msgid "Installation guide for SolidWorks macro"
+msgstr "SolidWorks 매크로 설치 가이드"
#: /home/ruben/Projects/Cura/plugins/SimulationView/__init__.py:14
msgctxt "@item:inlistbox"
-msgid "Simulation view"
-msgstr "시뮬레이션 보기"
+msgid "Layer view"
+msgstr "레이어 보기"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.py:100
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.py:103
msgctxt "@info:status"
msgid "Cura does not accurately display layers when Wire Printing is enabled"
msgstr "와이어 인쇄가 활성화되어있을 때 Cura는 레이어를 정확하게 표시하지 않습니다"
-#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.py:101
+#: /home/ruben/Projects/Cura/plugins/SimulationView/SimulationView.py:104
msgctxt "@info:title"
msgid "Simulation View"
msgstr "시뮬레이션 보기"
-#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.py:26
+#: /home/ruben/Projects/Cura/plugins/PostProcessingPlugin/PostProcessingPlugin.py:25
msgid "Modify G-Code"
msgstr "G 코드 수정"
#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/SliceInfo.py:43
msgctxt "@info"
-msgid "Cura collects anonymised slicing statistics. You can disable this in the preferences."
-msgstr "Cura는 익명의 슬라이싱 통계를 수집합니다. 환경 설정에서 이 기능을 비활성화 할 수 있습니다."
+msgid "Cura collects anonymized usage statistics."
+msgstr "Cura는 익명의 사용 통계를 수집합니다."
#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/SliceInfo.py:46
msgctxt "@info:title"
@@ -669,14 +716,41 @@ msgstr "데이터 수집"
#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/SliceInfo.py:48
msgctxt "@action:button"
-msgid "Dismiss"
-msgstr "버리다"
+msgid "Allow"
+msgstr "허용"
+
+#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/SliceInfo.py:49
+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 "Cura가 익명의 사용 통계를 보내 Cura에 대한 향후 개선을 우선화하는 데 도움을 줍니다. Cura 버전과 슬라이싱하는 모델의 해쉬 등 일부 선호사항과 설정이 발송됩니다."
+
+#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/SliceInfo.py:50
+msgctxt "@action:button"
+msgid "Disable"
+msgstr "사용 안함"
+
+#: /home/ruben/Projects/Cura/plugins/SliceInfoPlugin/SliceInfo.py:51
+msgctxt "@action:tooltip"
+msgid "Don't allow Cura to send anonymized usage statistics. You can enable it again in the preferences."
+msgstr "Cura가 익명의 사용 통계를 보내지 않게 합니다. 환경 설정에서 다시 사용할 수 있습니다."
#: /home/ruben/Projects/Cura/plugins/LegacyProfileReader/__init__.py:14
msgctxt "@item:inlistbox"
msgid "Cura 15.04 profiles"
msgstr "Cura 15.04 프로필"
+#: /home/ruben/Projects/Cura/plugins/CuraBlenderPlugin/__init__.py:15
+msgctxt "@item:inlistbox"
+msgid "Blender file"
+msgstr "Blender 파일"
+
+#: /home/ruben/Projects/Cura/plugins/CuraBlenderPlugin/CadIntegrationUtils/CommonReader.py:199
+msgctxt "@info:status"
+msgid ""
+"Could not export using \"{}\" quality!\n"
+"Felt back to \"{}\"."
+msgstr "\"{}\" 품질을 사용하여 내보낼 수 없습니다!\n \"{}\"(으)로 돌아갑니다."
+
#: /home/ruben/Projects/Cura/plugins/GCodeProfileReader/__init__.py:14
#: /home/ruben/Projects/Cura/plugins/GCodeReader/__init__.py:14
msgctxt "@item:inlistbox"
@@ -708,49 +782,49 @@ msgctxt "@item:inlistbox"
msgid "GIF Image"
msgstr "GIF 이미지"
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:269
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:299
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:269
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:297
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:319
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:299
#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:327
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:336
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:349
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:357
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:366
msgctxt "@info:title"
msgid "Unable to slice"
msgstr "슬라이스 할 수 없습니다"
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:296
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:326
#, python-brace-format
msgctxt "@info:status"
msgid "Unable to slice with the current settings. The following settings have errors: {0}"
msgstr "현재 설정으로 슬라이스 할 수 없습니다. 다음 설정에는 오류가 있습니다 : {0}"
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:318
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:348
#, 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 "일부 모델별 설정으로 인해 슬라이스할 수 없습니다. 하나 이상의 모델에서 다음 설정에 오류가 있습니다. {error_labels}"
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:326
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:356
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:335
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/CuraEngineBackend.py:365
msgctxt "@info:status"
msgid "Nothing to slice because none of the models fit the build volume. Please scale or rotate models to fit."
msgstr "어떤 모델도 빌드 볼륨에 맞지 않으므로 슬라이스 할 수 없습니다. 크기에 맞게 모형을 회전하거나 회전하십시오."
#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py:50
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py:239
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py:242
msgctxt "@info:status"
msgid "Processing Layers"
msgstr "레이어 처리 중"
-#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py:239
+#: /home/ruben/Projects/Cura/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py:242
msgctxt "@info:title"
msgid "Information"
msgstr "정보"
@@ -787,14 +861,14 @@ msgstr "Siemens NX 플러그인 파일을 복사하지 못했습니다. UGII_USE
msgid "Failed to install Siemens NX plugin. Could not set environment variable UGII_USER_DIR for Siemens NX."
msgstr "Siemens NX 플러그인을 설치하지 못했습니다. Siemens NX의 환경 변수 UGII_USER_DIR을 설정할 수 없습니다."
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.py:167
-#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:585
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.py:165
+#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:590
msgctxt "@title:tab"
msgid "Recommended"
msgstr "추천"
-#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.py:169
-#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:590
+#: /home/ruben/Projects/Cura/plugins/3MFReader/WorkspaceDialog.py:167
+#: /home/ruben/Projects/Cura/resources/qml/Sidebar.qml:595
msgctxt "@title:tab"
msgid "Custom"
msgstr "관습"
@@ -805,24 +879,24 @@ msgctxt "@item:inlistbox"
msgid "3MF File"
msgstr "3MF 파일"
-#: /home/ruben/Projects/Cura/plugins/3MFReader/ThreeMFWorkspaceReader.py:126
-#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:1142
+#: /home/ruben/Projects/Cura/plugins/3MFReader/ThreeMFWorkspaceReader.py:159
+#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:1185
msgctxt "@label"
msgid "Nozzle"
msgstr "노즐"
-#: /home/ruben/Projects/Cura/plugins/PluginBrowser/PluginBrowser.py:164
+#: /home/ruben/Projects/Cura/plugins/PluginBrowser/PluginBrowser.py:152
#, python-brace-format
msgctxt "@info:status"
msgid "Failed to get plugin ID from {0}"
msgstr "?에서 플러그인 ID를 가져 오는 데 실패했습니다"
-#: /home/ruben/Projects/Cura/plugins/PluginBrowser/PluginBrowser.py:165
+#: /home/ruben/Projects/Cura/plugins/PluginBrowser/PluginBrowser.py:153
msgctxt "@info:tile"
msgid "Warning"
msgstr "경고"
-#: /home/ruben/Projects/Cura/plugins/PluginBrowser/PluginBrowser.py:203
+#: /home/ruben/Projects/Cura/plugins/PluginBrowser/PluginBrowser.py:191
msgctxt "@window:title"
msgid "Plugin browser"
msgstr "플러그인 브라우저"
@@ -837,18 +911,18 @@ msgctxt "@item:inlistbox"
msgid "G File"
msgstr "G파일"
-#: /home/ruben/Projects/Cura/plugins/GCodeReader/GCodeReader.py:314
+#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:321
msgctxt "@info:status"
msgid "Parsing G-code"
msgstr "G 코드 파싱"
-#: /home/ruben/Projects/Cura/plugins/GCodeReader/GCodeReader.py:316
-#: /home/ruben/Projects/Cura/plugins/GCodeReader/GCodeReader.py:426
+#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:323
+#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:464
msgctxt "@info:title"
msgid "G-code Details"
msgstr "G 코드 세부 정보"
-#: /home/ruben/Projects/Cura/plugins/GCodeReader/GCodeReader.py:424
+#: /home/ruben/Projects/Cura/plugins/GCodeReader/FlavorParser.py:462
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 "파일을 보내기 전에 g 코드가 프린터 및 프린터 구성에 적합한 지 확인하십시오. g 코드 표현이 정확하지 않을 수 있습니다."
@@ -859,6 +933,16 @@ msgctxt "@item:inlistbox"
msgid "Cura Profile"
msgstr "Cura 프로필"
+#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/__init__.py:12
+msgctxt "@item:inmenu"
+msgid "Profile Assistant"
+msgstr "프로필 어시스턴트"
+
+#: /home/ruben/Projects/Cura/plugins/CuraPrintProfileCreator/__init__.py:17
+msgctxt "@item:inlistbox"
+msgid "Profile Assistant"
+msgstr "프로필 어시스턴트"
+
#: /home/ruben/Projects/Cura/plugins/3MFWriter/__init__.py:30
msgctxt "@item:inlistbox"
msgid "3MF file"
@@ -890,142 +974,116 @@ msgctxt "@action"
msgid "Level build plate"
msgstr "레벨 빌드 플레이트"
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:89
+#: /home/ruben/Projects/Cura/cura/PrintInformation.py:98
msgctxt "@tooltip"
msgid "Outer Wall"
msgstr "외벽"
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:90
+#: /home/ruben/Projects/Cura/cura/PrintInformation.py:99
msgctxt "@tooltip"
msgid "Inner Walls"
msgstr "내벽"
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:91
+#: /home/ruben/Projects/Cura/cura/PrintInformation.py:100
msgctxt "@tooltip"
msgid "Skin"
msgstr "외판"
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:92
+#: /home/ruben/Projects/Cura/cura/PrintInformation.py:101
msgctxt "@tooltip"
msgid "Infill"
msgstr "빈 공간 채우기"
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:93
+#: /home/ruben/Projects/Cura/cura/PrintInformation.py:102
msgctxt "@tooltip"
msgid "Support Infill"
msgstr "빈 공간 채우기 지지"
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:94
+#: /home/ruben/Projects/Cura/cura/PrintInformation.py:103
msgctxt "@tooltip"
msgid "Support Interface"
msgstr "지원 인터페이스"
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:95
+#: /home/ruben/Projects/Cura/cura/PrintInformation.py:104
msgctxt "@tooltip"
msgid "Support"
msgstr "지지물"
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:96
+#: /home/ruben/Projects/Cura/cura/PrintInformation.py:105
msgctxt "@tooltip"
msgid "Skirt"
msgstr "둘러싸다"
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:97
+#: /home/ruben/Projects/Cura/cura/PrintInformation.py:106
msgctxt "@tooltip"
msgid "Travel"
msgstr "움직여 가다"
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:98
+#: /home/ruben/Projects/Cura/cura/PrintInformation.py:107
msgctxt "@tooltip"
msgid "Retractions"
msgstr "취소"
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:99
+#: /home/ruben/Projects/Cura/cura/PrintInformation.py:108
msgctxt "@tooltip"
msgid "Other"
msgstr "다른"
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:199
+#: /home/ruben/Projects/Cura/cura/PrintInformation.py:231
msgctxt "@label unknown material"
msgid "Unknown"
msgstr "알 수 없음"
-#: /home/ruben/Projects/Cura/cura/PrintInformation.py:284
+#: /home/ruben/Projects/Cura/cura/PrintInformation.py:318
#, python-brace-format
msgctxt "@label"
msgid "Pre-sliced file {0}"
msgstr "미리 잘라낸 파일 {0}"
-#: /home/ruben/Projects/Cura/cura/PrinterOutputDevice.py:469
+#: /home/ruben/Projects/Cura/cura/PrinterOutputDevice.py:440
msgctxt "@item:material"
msgid "No material loaded"
msgstr "로드 된 자료 없음"
-#: /home/ruben/Projects/Cura/cura/PrinterOutputDevice.py:476
+#: /home/ruben/Projects/Cura/cura/PrinterOutputDevice.py:447
msgctxt "@item:material"
msgid "Unknown material"
msgstr "알 수없는 자료"
-#: /home/ruben/Projects/Cura/cura/ArrangeObjectsJob.py:30
-msgctxt "@info:status"
-msgid "Finding new location for objects"
-msgstr "객체의 새 위치 삽입"
-
-#: /home/ruben/Projects/Cura/cura/ArrangeObjectsJob.py:34
-msgctxt "@info:title"
-msgid "Finding Location"
-msgstr "위치 찾기"
-
-#: /home/ruben/Projects/Cura/cura/ArrangeObjectsJob.py:89
-#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:83
-msgctxt "@info:status"
-msgid "Unable to find a location within the build volume for all objects"
-msgstr "모든 개체에 대한 빌드 볼륨 내의 위치를 찾을 수 없습니다"
-
-#: /home/ruben/Projects/Cura/cura/ArrangeObjectsJob.py:90
-msgctxt "@info:title"
-msgid "Can't Find Location"
-msgstr "위치를 찾을 수 없음"
-
-#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:431
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:113
+#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:437
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:120
msgctxt "@title:window"
msgid "File Already Exists"
msgstr "파일이 이미 있습니다"
-#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:432
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:114
+#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:438
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:121
#, 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 "파일이 이미 있습니다. 덮어 쓰시겠습니까?"
-#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:815
+#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:872
msgctxt "@label"
msgid "Custom"
msgstr "맞춤"
-#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:819
+#: /home/ruben/Projects/Cura/cura/Settings/ContainerManager.py:876
msgctxt "@label"
msgid "Custom Material"
msgstr "맞춤 소재"
-#: /home/ruben/Projects/Cura/cura/Settings/ExtrudersModel.py:182
-msgctxt "@menuitem"
-msgid "Global"
-msgstr "전역"
-
-#: /home/ruben/Projects/Cura/cura/Settings/ExtrudersModel.py:229
+#: /home/ruben/Projects/Cura/cura/Settings/ExtrudersModel.py:205
msgctxt "@menuitem"
msgid "Not overridden"
msgstr "재정의되지 않음"
-#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:117
+#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:124
msgctxt "@info:status"
msgid "The selected material is incompatible with the selected machine or configuration."
msgstr "선택한 재료가 선택한 기계 또는 구성과 호환되지 않습니다."
-#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:118
+#: /home/ruben/Projects/Cura/cura/Settings/MachineManager.py:125
#: /home/ruben/Projects/Cura/cura/Settings/MaterialManager.py:24
msgctxt "@info:title"
msgid "Incompatible Material"
@@ -1046,67 +1104,89 @@ msgctxt "@action"
msgid "Undo changing the material diameter."
msgstr "재료 직경 변경을 취소하십시오."
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:144
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:151
#, 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:151
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:158
#, python-brace-format
msgctxt "@info:status Don't translate the XML tag !"
msgid "Failed to export profile to {0}: Writer plugin reported failure."
msgstr "프로필을 ?로 내보내지 못했습니다. Writer 플러그인이 오류를 보고했습니다."
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:156
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:163
#, 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:157
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:164
msgctxt "@info:title"
msgid "Export succeeded"
msgstr "내보내기 완료"
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:183
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:205
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:214
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:248
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:190
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:211
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:271
#, python-brace-format
msgctxt "@info:status Don't translate the XML tags or !"
msgid "Failed to import profile from {0}: {1}"
msgstr "?에서 프로필을 가져 오지 못했습니다"
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:216
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:252
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:230
+#, python-brace-format
+msgctxt "@info:status Don't translate the XML tags or !"
+msgid "This profile {0} contains incorrect data, could not import it."
+msgstr "이 프로필 {0}에는 정확하지 않은 데이터가 포함되어 있으므로, 불러올 수 없습니다."
+
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:240
+#, python-brace-format
+msgctxt "@info:status Don't translate the XML tags or !"
+msgid "The machine defined in profile {0} doesn't match with your current machine, could not import it."
+msgstr "프로필 {0}에 정의된 기계가 현재 기계와 일치하지 않으므로, 불러올 수 없습니다."
+
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:274
#, python-brace-format
msgctxt "@info:status"
msgid "Successfully imported profile {0}"
msgstr "프로필 {0}을 (를) 성공적으로 가져 왔습니다."
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:255
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:277
+#, python-brace-format
+msgctxt "@info:status"
+msgid "File {0} does not contain any valid profile."
+msgstr "파일 {0}에 유효한 프로필이 포함되어 있지 않습니다."
+
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:280
#, python-brace-format
msgctxt "@info:status"
msgid "Profile {0} has an unknown file type or is corrupted."
msgstr "프로파일 {0}에 알 수없는 파일 유형이 있거나 손상되었습니다."
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:274
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:298
msgctxt "@label"
msgid "Custom profile"
msgstr "사용자 정의 프로필"
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:285
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:313
msgctxt "@info:status"
msgid "Profile is missing a quality type."
msgstr "프로필에 품질 유형이 누락되었습니다."
-#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:321
+#: /home/ruben/Projects/Cura/cura/Settings/CuraContainerRegistry.py:349
#, python-brace-format
msgctxt "@info:status"
msgid "Could not find a quality type {0} for the current configuration."
msgstr "현재 구성에 대해 품질 유형 {0}을 (를) 찾을 수 없습니다."
+#: /home/ruben/Projects/Cura/cura/ObjectsModel.py:46
+#, python-brace-format
+msgctxt "@label"
+msgid "Group #{group_nr}"
+msgstr "그룹 #{group_nr}"
+
#: /home/ruben/Projects/Cura/cura/BuildVolume.py:100
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."
@@ -1117,142 +1197,167 @@ msgctxt "@info:title"
msgid "Build Volume"
msgstr "빌드 볼륨"
-#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:34
+#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:25
msgctxt "@info:status"
msgid "Multiplying and placing objects"
msgstr "객체 곱하기 및 배치"
-#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:35
-#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:83
+#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:26
+#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:78
msgctxt "@info:title"
msgid "Placing Object"
msgstr "개체 배치 중"
-#: /home/ruben/Projects/Cura/cura/CrashHandler.py:80
+#: /home/ruben/Projects/Cura/cura/MultiplyObjectsJob.py:78
+#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsJob.py:88
+#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsAllBuildPlatesJob.py:152
+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:29
+#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsAllBuildPlatesJob.py:64
+msgctxt "@info:status"
+msgid "Finding new location for objects"
+msgstr "객체의 새 위치 삽입"
+
+#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsJob.py:33
+#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsAllBuildPlatesJob.py:68
+msgctxt "@info:title"
+msgid "Finding Location"
+msgstr "위치 찾기"
+
+#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsJob.py:89
+#: /home/ruben/Projects/Cura/cura/Arranging/ArrangeObjectsAllBuildPlatesJob.py:153
+msgctxt "@info:title"
+msgid "Can't Find Location"
+msgstr "위치를 찾을 수 없음"
+
+#: /home/ruben/Projects/Cura/cura/CrashHandler.py:81
msgctxt "@title:window"
msgid "Crash Report"
msgstr "오류 보고서"
-#: /home/ruben/Projects/Cura/cura/CrashHandler.py:93
+#: /home/ruben/Projects/Cura/cura/CrashHandler.py:94
msgctxt "@label crash message"
msgid ""
-"
A fatal exception has occurred. Please send us this Crash Report to fix the problem
\n"
+"
A fatal error has occurred. Please send us this Crash Report to fix the problem
\n"
"
Please use the \"Send report\" button to post a bug report automatically to our servers