Merge remote-tracking branch 'Ultimaker/master'

This commit is contained in:
PCDotFan 2017-07-08 09:47:49 +08:00
commit bca7c75cd2
333 changed files with 1935 additions and 1157 deletions

View file

@ -45,7 +45,6 @@ Please checkout [cura-build](https://github.com/Ultimaker/cura-build)
Third party plugins Third party plugins
------------- -------------
* [Print Cost Calculator](https://github.com/nallath/PrintCostCalculator): Calculates weight and monetary cost of your print.
* [Post Processing Plugin](https://github.com/nallath/PostProcessingPlugin): Allows for post-processing scripts to run on g-code. * [Post Processing Plugin](https://github.com/nallath/PostProcessingPlugin): Allows for post-processing scripts to run on g-code.
* [Barbarian Plugin](https://github.com/nallath/BarbarianPlugin): Simple scale tool for imperial to metric. * [Barbarian Plugin](https://github.com/nallath/BarbarianPlugin): Simple scale tool for imperial to metric.
* [X3G Writer](https://github.com/Ghostkeeper/X3GWriter): Adds support for exporting X3G files. * [X3G Writer](https://github.com/Ghostkeeper/X3GWriter): Adds support for exporting X3G files.

View file

@ -718,8 +718,8 @@ class BuildVolume(SceneNode):
# For certain machines we don't need to compute disallowed areas for each nozzle. # For certain machines we don't need to compute disallowed areas for each nozzle.
# So we check here and only do the nozzle offsetting if needed. # So we check here and only do the nozzle offsetting if needed.
no_nozzle_offsetting_for_disallowed_areas = self._global_container_stack.getMetaDataEntry( nozzle_offsetting_for_disallowed_areas = self._global_container_stack.getMetaDataEntry(
"no_nozzle_offsetting_for_disallowed_areas", False) "nozzle_offsetting_for_disallowed_areas", True)
result = {} result = {}
for extruder in used_extruders: for extruder in used_extruders:
@ -727,9 +727,11 @@ class BuildVolume(SceneNode):
offset_x = extruder.getProperty("machine_nozzle_offset_x", "value") offset_x = extruder.getProperty("machine_nozzle_offset_x", "value")
if offset_x is None: if offset_x is None:
offset_x = 0 offset_x = 0
offset_y = -extruder.getProperty("machine_nozzle_offset_y", "value") offset_y = extruder.getProperty("machine_nozzle_offset_y", "value")
if offset_y is None: if offset_y is None:
offset_y = 0 offset_y = 0
else:
offset_y = -offset_y
result[extruder_id] = [] result[extruder_id] = []
for polygon in machine_disallowed_polygons: for polygon in machine_disallowed_polygons:
@ -742,7 +744,7 @@ class BuildVolume(SceneNode):
bottom_unreachable_border = 0 bottom_unreachable_border = 0
# Only do nozzle offsetting if needed # Only do nozzle offsetting if needed
if not no_nozzle_offsetting_for_disallowed_areas: if nozzle_offsetting_for_disallowed_areas:
#The build volume is defined as the union of the area that all extruders can reach, so we need to know the relative offset to all extruders. #The build volume is defined as the union of the area that all extruders can reach, so we need to know the relative offset to all extruders.
for other_extruder in ExtruderManager.getInstance().getActiveExtruderStacks(): for other_extruder in ExtruderManager.getInstance().getActiveExtruderStacks():
other_offset_x = other_extruder.getProperty("machine_nozzle_offset_x", "value") other_offset_x = other_extruder.getProperty("machine_nozzle_offset_x", "value")

View file

@ -257,7 +257,11 @@ class ConvexHullDecorator(SceneNodeDecorator):
# \return New Polygon instance that is offset with everything that # \return New Polygon instance that is offset with everything that
# influences the collision area. # influences the collision area.
def _offsetHull(self, convex_hull): def _offsetHull(self, convex_hull):
horizontal_expansion = self._getSettingProperty("xy_offset", "value") horizontal_expansion = max(
self._getSettingProperty("xy_offset", "value"),
self._getSettingProperty("xy_offset_layer_0", "value")
)
mold_width = 0 mold_width = 0
if self._getSettingProperty("mold_enabled", "value"): if self._getSettingProperty("mold_enabled", "value"):
mold_width = self._getSettingProperty("mold_width", "value") mold_width = self._getSettingProperty("mold_width", "value")
@ -332,4 +336,4 @@ class ConvexHullDecorator(SceneNodeDecorator):
## Settings that change the convex hull. ## Settings that change the convex hull.
# #
# If these settings change, the convex hull should be recalculated. # If these settings change, the convex hull should be recalculated.
_influencing_settings = {"xy_offset", "mold_enabled", "mold_width"} _influencing_settings = {"xy_offset", "xy_offset_layer_0", "mold_enabled", "mold_width"}

View file

@ -26,7 +26,6 @@ from UM.Settings.Validator import Validator
from UM.Message import Message from UM.Message import Message
from UM.i18n import i18nCatalog from UM.i18n import i18nCatalog
from UM.Workspace.WorkspaceReader import WorkspaceReader from UM.Workspace.WorkspaceReader import WorkspaceReader
from UM.Platform import Platform
from UM.Decorators import deprecated from UM.Decorators import deprecated
from UM.Operations.AddSceneNodeOperation import AddSceneNodeOperation from UM.Operations.AddSceneNodeOperation import AddSceneNodeOperation
@ -105,7 +104,7 @@ class CuraApplication(QtApplication):
# SettingVersion represents the set of settings available in the machine/extruder definitions. # SettingVersion represents the set of settings available in the machine/extruder definitions.
# You need to make sure that this version number needs to be increased if there is any non-backwards-compatible # You need to make sure that this version number needs to be increased if there is any non-backwards-compatible
# changes of the settings. # changes of the settings.
SettingVersion = 1 SettingVersion = 2
class ResourceTypes: class ResourceTypes:
QmlFiles = Resources.UserType + 1 QmlFiles = Resources.UserType + 1
@ -179,9 +178,9 @@ class CuraApplication(QtApplication):
UM.VersionUpgradeManager.VersionUpgradeManager.getInstance().setCurrentVersions( UM.VersionUpgradeManager.VersionUpgradeManager.getInstance().setCurrentVersions(
{ {
("quality_changes", InstanceContainer.Version * 1000000 + self.SettingVersion): (self.ResourceTypes.QualityInstanceContainer, "application/x-uranium-instancecontainer"), ("quality_changes", InstanceContainer.Version * 1000000 + self.SettingVersion): (self.ResourceTypes.QualityInstanceContainer, "application/x-uranium-instancecontainer"),
("machine_stack", ContainerStack.Version): (self.ResourceTypes.MachineStack, "application/x-uranium-containerstack"), ("machine_stack", ContainerStack.Version * 1000000 + self.SettingVersion): (self.ResourceTypes.MachineStack, "application/x-cura-globalstack"),
("extruder_train", ContainerStack.Version): (self.ResourceTypes.ExtruderStack, "application/x-uranium-extruderstack"), ("extruder_train", ContainerStack.Version * 1000000 + self.SettingVersion): (self.ResourceTypes.ExtruderStack, "application/x-cura-extruderstack"),
("preferences", Preferences.Version): (Resources.Preferences, "application/x-uranium-preferences"), ("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"), ("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"), ("definition_changes", InstanceContainer.Version * 1000000 + self.SettingVersion): (self.ResourceTypes.DefinitionChangesContainer, "application/x-uranium-instancecontainer"),
} }
@ -268,6 +267,9 @@ class CuraApplication(QtApplication):
with ContainerRegistry.getInstance().lockFile(): with ContainerRegistry.getInstance().lockFile():
ContainerRegistry.getInstance().load() ContainerRegistry.getInstance().load()
# set the setting version for Preferences
Preferences.getInstance().addPreference("metadata/setting_version", CuraApplication.SettingVersion)
Preferences.getInstance().addPreference("cura/active_mode", "simple") Preferences.getInstance().addPreference("cura/active_mode", "simple")
Preferences.getInstance().addPreference("cura/categories_expanded", "") Preferences.getInstance().addPreference("cura/categories_expanded", "")

View file

@ -218,20 +218,25 @@ class ContainerManager(QObject):
entries = entry_name.split("/") entries = entry_name.split("/")
entry_name = entries.pop() entry_name = entries.pop()
sub_item_changed = False
if entries: if entries:
root_name = entries.pop(0) root_name = entries.pop(0)
root = container.getMetaDataEntry(root_name) root = container.getMetaDataEntry(root_name)
item = root item = root
for entry in entries: for _ in range(len(entries)):
item = item.get(entries.pop(0), { }) item = item.get(entries.pop(0), { })
if item[entry_name] != entry_value:
sub_item_changed = True
item[entry_name] = entry_value item[entry_name] = entry_value
entry_name = root_name entry_name = root_name
entry_value = root entry_value = root
container.setMetaDataEntry(entry_name, entry_value) 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 return True

View file

@ -1,7 +1,7 @@
# Copyright (c) 2017 Ultimaker B.V. # Copyright (c) 2017 Ultimaker B.V.
# Cura is released under the terms of the AGPLv3 or higher. # Cura is released under the terms of the AGPLv3 or higher.
from typing import Any, Dict from typing import Any, Dict, Optional
from PyQt5.QtCore import pyqtProperty from PyQt5.QtCore import pyqtProperty
@ -42,6 +42,17 @@ class GlobalStack(CuraContainerStack):
def getLoadingPriority(cls) -> int: def getLoadingPriority(cls) -> int:
return 2 return 2
def getConfigurationTypeFromSerialized(self, serialized: str) -> Optional[str]:
configuration_type = None
try:
parser = self._readAndValidateSerialized(serialized)
configuration_type = parser["metadata"].get("type")
if configuration_type == "machine":
configuration_type = "machine_stack"
except Exception as e:
Logger.log("e", "Could not get configuration type: %s", e)
return configuration_type
## Add an extruder to the list of extruders of this stack. ## Add an extruder to the list of extruders of this stack.
# #
# \param extruder The extruder to add. # \param extruder The extruder to add.

View file

@ -49,6 +49,9 @@ class MaterialManager(QObject):
if button == "Undo": if button == "Undo":
container_manager = ContainerManager.getInstance() container_manager = ContainerManager.getInstance()
container_manager.setContainerMetaDataEntry(self._material_diameter_warning_message.material_id, "properties/diameter", self._material_diameter_warning_message.previous_diameter) 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() message.hide()
else: else:
Logger.log("w", "Unknown button action for material diameter warning message: {action}".format(action = button)) Logger.log("w", "Unknown button action for material diameter warning message: {action}".format(action = button))

View file

@ -1,6 +1,6 @@
{ {
"name": "3MF Reader", "name": "3MF Reader",
"author": "Ultimaker", "author": "Ultimaker B.V.",
"version": "1.0.0", "version": "1.0.0",
"description": "Provides support for reading 3MF files.", "description": "Provides support for reading 3MF files.",
"api": 4, "api": 4,

View file

@ -1,6 +1,6 @@
{ {
"name": "3MF Writer", "name": "3MF Writer",
"author": "Ultimaker", "author": "Ultimaker B.V.",
"version": "1.0.0", "version": "1.0.0",
"description": "Provides support for writing 3MF files.", "description": "Provides support for writing 3MF files.",
"api": 4, "api": 4,

View file

@ -1,6 +1,6 @@
{ {
"name": "Auto Save", "name": "Auto Save",
"author": "Ultimaker", "author": "Ultimaker B.V.",
"version": "1.0.0", "version": "1.0.0",
"description": "Automatically saves Preferences, Machines and Profiles after changes.", "description": "Automatically saves Preferences, Machines and Profiles after changes.",
"api": 4, "api": 4,

View file

@ -1,6 +1,6 @@
{ {
"name": "Changelog", "name": "Changelog",
"author": "Ultimaker", "author": "Ultimaker B.V.",
"version": "1.0.0", "version": "1.0.0",
"description": "Shows changes since latest checked version.", "description": "Shows changes since latest checked version.",
"api": 4, "api": 4,

View file

@ -1,5 +1,5 @@
# Copyright (c) 2016 Ultimaker B.V. #Copyright (c) 2017 Ultimaker B.V.
# Cura is released under the terms of the AGPLv3 or higher. #Cura is released under the terms of the AGPLv3 or higher.
import gc import gc
@ -173,19 +173,14 @@ class ProcessSlicedLayersJob(Job):
if extruders: if extruders:
material_color_map = numpy.zeros((len(extruders), 4), dtype=numpy.float32) material_color_map = numpy.zeros((len(extruders), 4), dtype=numpy.float32)
for extruder in extruders: for extruder in extruders:
material = extruder.findContainer({"type": "material"})
position = int(extruder.getMetaDataEntry("position", default="0")) # Get the position position = int(extruder.getMetaDataEntry("position", default="0")) # Get the position
color_code = material.getMetaDataEntry("color_code", default="#e0e000") color_code = extruder.material.getMetaDataEntry("color_code", default="#e0e000")
color = colorCodeToRGBA(color_code) color = colorCodeToRGBA(color_code)
material_color_map[position, :] = color material_color_map[position, :] = color
else: else:
# Single extruder via global stack. # Single extruder via global stack.
material_color_map = numpy.zeros((1, 4), dtype=numpy.float32) material_color_map = numpy.zeros((1, 4), dtype=numpy.float32)
material = global_container_stack.findContainer({"type": "material"}) color_code = global_container_stack.material.getMetaDataEntry("color_code", default="#e0e000")
color_code = "#e0e000"
if material:
if material.getMetaDataEntry("color_code") is not None:
color_code = material.getMetaDataEntry("color_code")
color = colorCodeToRGBA(color_code) color = colorCodeToRGBA(color_code)
material_color_map[0, :] = color material_color_map[0, :] = color

View file

@ -44,6 +44,14 @@ class GcodeStartEndFormatter(Formatter):
## Job class that builds up the message of scene data to send to CuraEngine. ## Job class that builds up the message of scene data to send to CuraEngine.
class StartSliceJob(Job): class StartSliceJob(Job):
## Meshes that are sent to the engine regardless of being outside of the
# build volume.
#
# If these settings are True for any mesh, the build volume is ignored.
# Note that Support Mesh is not in here because it actually generates
# g-code in the volume of the mesh.
_not_printed_mesh_settings = {"anti_overhang_mesh", "infill_mesh", "cutting_mesh"}
def __init__(self, slice_message): def __init__(self, slice_message):
super().__init__() super().__init__()
@ -132,7 +140,8 @@ class StartSliceJob(Job):
temp_list = [] temp_list = []
for node in DepthFirstIterator(self._scene.getRoot()): for node in DepthFirstIterator(self._scene.getRoot()):
if type(node) is SceneNode and node.getMeshData() and node.getMeshData().getVertices() is not None: if type(node) is SceneNode and node.getMeshData() and node.getMeshData().getVertices() is not None:
if not getattr(node, "_outside_buildarea", False): if not getattr(node, "_outside_buildarea", False)\
or (node.callDecoration("getStack") and any(node.callDecoration("getStack").getProperty(setting, "value") for setting in self._not_printed_mesh_settings)):
temp_list.append(node) temp_list.append(node)
Job.yieldThread() Job.yieldThread()

View file

@ -1,6 +1,6 @@
{ {
"name": "CuraEngine Backend", "name": "CuraEngine Backend",
"author": "Ultimaker", "author": "Ultimaker B.V.",
"description": "Provides the link to the CuraEngine slicing backend.", "description": "Provides the link to the CuraEngine slicing backend.",
"api": 4, "api": 4,
"version": "1.0.0", "version": "1.0.0",

View file

@ -1,6 +1,6 @@
{ {
"name": "Cura Profile Reader", "name": "Cura Profile Reader",
"author": "Ultimaker", "author": "Ultimaker B.V.",
"version": "1.0.0", "version": "1.0.0",
"description": "Provides support for importing Cura profiles.", "description": "Provides support for importing Cura profiles.",
"api": 4, "api": 4,

View file

@ -1,6 +1,6 @@
{ {
"name": "Cura Profile Writer", "name": "Cura Profile Writer",
"author": "Ultimaker", "author": "Ultimaker B.V.",
"version": "1.0.0", "version": "1.0.0",
"description": "Provides support for exporting Cura profiles.", "description": "Provides support for exporting Cura profiles.",
"api": 4, "api": 4,

View file

@ -1,6 +1,6 @@
{ {
"name": "GCode Profile Reader", "name": "GCode Profile Reader",
"author": "Ultimaker", "author": "Ultimaker B.V.",
"version": "1.0.0", "version": "1.0.0",
"description": "Provides support for importing profiles from g-code files.", "description": "Provides support for importing profiles from g-code files.",
"api": 4, "api": 4,

View file

@ -1,4 +1,4 @@
# Copyright (c) 2016 Ultimaker B.V. # Copyright (c) 2017 Ultimaker B.V.
# Cura is released under the terms of the AGPLv3 or higher. # Cura is released under the terms of the AGPLv3 or higher.
from UM.Mesh.MeshWriter import MeshWriter from UM.Mesh.MeshWriter import MeshWriter
@ -113,7 +113,7 @@ class GCodeWriter(MeshWriter):
# Ensure that quality_type is set. (Can happen if we have empty quality changes). # Ensure that quality_type is set. (Can happen if we have empty quality changes).
if flat_global_container.getMetaDataEntry("quality_type", None) is None: if flat_global_container.getMetaDataEntry("quality_type", None) is None:
flat_global_container.addMetaDataEntry("quality_type", stack.findContainer({"type": "quality"}).getMetaDataEntry("quality_type", "normal")) flat_global_container.addMetaDataEntry("quality_type", stack.quality.getMetaDataEntry("quality_type", "normal"))
serialized = flat_global_container.serialize() serialized = flat_global_container.serialize()
data = {"global_quality": serialized} data = {"global_quality": serialized}
@ -134,7 +134,7 @@ class GCodeWriter(MeshWriter):
# Ensure that quality_type is set. (Can happen if we have empty quality changes). # Ensure that quality_type is set. (Can happen if we have empty quality changes).
if flat_extruder_quality.getMetaDataEntry("quality_type", None) is None: if flat_extruder_quality.getMetaDataEntry("quality_type", None) is None:
flat_extruder_quality.addMetaDataEntry("quality_type", extruder.findContainer({"type": "quality"}).getMetaDataEntry("quality_type", "normal")) flat_extruder_quality.addMetaDataEntry("quality_type", extruder.quality.getMetaDataEntry("quality_type", "normal"))
extruder_serialized = flat_extruder_quality.serialize() extruder_serialized = flat_extruder_quality.serialize()
data.setdefault("extruder_quality", []).append(extruder_serialized) data.setdefault("extruder_quality", []).append(extruder_serialized)

View file

@ -1,6 +1,6 @@
{ {
"name": "GCode Writer", "name": "GCode Writer",
"author": "Ultimaker", "author": "Ultimaker B.V.",
"version": "1.0.0", "version": "1.0.0",
"description": "Writes GCode to a file.", "description": "Writes GCode to a file.",
"api": 4, "api": 4,

View file

@ -1,6 +1,6 @@
{ {
"name": "Image Reader", "name": "Image Reader",
"author": "Ultimaker", "author": "Ultimaker B.V.",
"version": "1.0.0", "version": "1.0.0",
"description": "Enables ability to generate printable geometry from 2D image files.", "description": "Enables ability to generate printable geometry from 2D image files.",
"api": 4, "api": 4,

View file

@ -39,6 +39,8 @@ Item
height: parent.height height: parent.height
z: slider.z - 1 z: slider.z - 1
color: UM.Theme.getColor("tool_panel_background") color: UM.Theme.getColor("tool_panel_background")
borderWidth: UM.Theme.getSize("default_lining").width
borderColor: UM.Theme.getColor("lining")
target: parent.buttonTarget target: parent.buttonTarget
arrowSize: UM.Theme.getSize("default_arrow").width arrowSize: UM.Theme.getSize("default_arrow").width
@ -530,27 +532,20 @@ Item
target: Qt.point(0, slider.activeHandle.y + slider.activeHandle.height / 2) target: Qt.point(0, slider.activeHandle.y + slider.activeHandle.height / 2)
arrowSize: UM.Theme.getSize("default_arrow").width arrowSize: UM.Theme.getSize("default_arrow").width
height: (Math.floor(UM.Theme.getSize("slider_handle").height + UM.Theme.getSize("default_margin").height) / 2) * 2 // Make sure height has an integer middle so drawing a pointy border is easier height: UM.Theme.getSize("slider_handle").height + UM.Theme.getSize("default_margin").height
width: valueLabel.width + UM.Theme.getSize("default_margin").width width: valueLabel.width + UM.Theme.getSize("default_margin").width
Behavior on height { NumberAnimation { duration: 50; } } Behavior on height { NumberAnimation { duration: 50; } }
color: UM.Theme.getColor("lining"); color: UM.Theme.getColor("tool_panel_background")
borderColor: UM.Theme.getColor("lining")
borderWidth: UM.Theme.getSize("default_lining").width
visible: slider.layersVisible visible: slider.layersVisible
UM.PointingRectangle
{
color: UM.Theme.getColor("tool_panel_background")
target: Qt.point(0, height / 2 + UM.Theme.getSize("default_lining").width)
arrowSize: UM.Theme.getSize("default_arrow").width
anchors.fill: parent
anchors.margins: UM.Theme.getSize("default_lining").width
MouseArea //Catch all mouse events (so scene doesnt handle them) MouseArea //Catch all mouse events (so scene doesnt handle them)
{ {
anchors.fill: parent anchors.fill: parent
} }
}
TextField TextField
{ {

View file

@ -1,6 +1,6 @@
{ {
"name": "Layer View", "name": "Layer View",
"author": "Ultimaker", "author": "Ultimaker B.V.",
"version": "1.0.0", "version": "1.0.0",
"description": "Provides the Layer view.", "description": "Provides the Layer view.",
"api": 4, "api": 4,

View file

@ -1,6 +1,6 @@
{ {
"name": "Legacy Cura Profile Reader", "name": "Legacy Cura Profile Reader",
"author": "Ultimaker", "author": "Ultimaker B.V.",
"version": "1.0.0", "version": "1.0.0",
"description": "Provides support for importing profiles from legacy Cura versions.", "description": "Provides support for importing profiles from legacy Cura versions.",
"api": 4, "api": 4,

View file

@ -1,6 +1,6 @@
{ {
"name": "Per Model Settings Tool", "name": "Per Model Settings Tool",
"author": "Ultimaker", "author": "Ultimaker B.V.",
"version": "1.0.0", "version": "1.0.0",
"description": "Provides the Per Model Settings.", "description": "Provides the Per Model Settings.",
"api": 4, "api": 4,

View file

@ -8,7 +8,7 @@ from UM.PluginRegistry import PluginRegistry
from UM.Application import Application from UM.Application import Application
from UM.Version import Version from UM.Version import Version
from PyQt5.QtNetwork import QNetworkAccessManager, QNetworkRequest from PyQt5.QtNetwork import QNetworkAccessManager, QNetworkRequest, QNetworkReply
from PyQt5.QtCore import QUrl, QObject, Qt, pyqtProperty, pyqtSignal, pyqtSlot from PyQt5.QtCore import QUrl, QObject, Qt, pyqtProperty, pyqtSignal, pyqtSlot
from PyQt5.QtQml import QQmlComponent, QQmlContext from PyQt5.QtQml import QQmlComponent, QQmlContext
@ -66,7 +66,9 @@ class PluginBrowser(QObject, Extension):
self._createDialog() self._createDialog()
self._dialog.show() self._dialog.show()
@pyqtSlot()
def requestPluginList(self): def requestPluginList(self):
Logger.log("i", "Requesting plugin list")
url = QUrl(self._api_url + "plugins") url = QUrl(self._api_url + "plugins")
self._plugin_list_request = QNetworkRequest(url) self._plugin_list_request = QNetworkRequest(url)
self._plugin_list_request.setRawHeader(*self._request_header) self._plugin_list_request.setRawHeader(*self._request_header)
@ -94,17 +96,23 @@ class PluginBrowser(QObject, Extension):
def _onDownloadPluginProgress(self, bytes_sent, bytes_total): def _onDownloadPluginProgress(self, bytes_sent, bytes_total):
if bytes_total > 0: if bytes_total > 0:
new_progress = bytes_sent / bytes_total * 100 new_progress = bytes_sent / bytes_total * 100
if new_progress > self._download_progress: self.setDownloadProgress(new_progress)
self._download_progress = new_progress
self.onDownloadProgressChanged.emit()
self._download_progress = new_progress
if new_progress == 100.0: if new_progress == 100.0:
self.setIsDownloading(False) self.setIsDownloading(False)
self._download_plugin_reply.downloadProgress.disconnect(self._onDownloadPluginProgress) self._download_plugin_reply.downloadProgress.disconnect(self._onDownloadPluginProgress)
self._temp_plugin_file = tempfile.NamedTemporaryFile(suffix = ".curaplugin")
self._temp_plugin_file.write(self._download_plugin_reply.readAll())
result = PluginRegistry.getInstance().installPlugin("file://" + self._temp_plugin_file.name) # must not delete the temporary file on Windows
self._temp_plugin_file = tempfile.NamedTemporaryFile(mode = "w+b", suffix = ".curaplugin", delete = False)
location = self._temp_plugin_file.name
# write first and close, otherwise on Windows, it cannot read the file
self._temp_plugin_file.write(self._download_plugin_reply.readAll())
self._temp_plugin_file.close()
# open as read
if not location.startswith("/"):
location = "/" + location # Ensure that it starts with a /, as otherwise it doesn't work on windows.
result = PluginRegistry.getInstance().installPlugin("file://" + location)
self._newly_installed_plugin_ids.append(result["id"]) self._newly_installed_plugin_ids.append(result["id"])
self.pluginsMetadataChanged.emit() self.pluginsMetadataChanged.emit()
@ -117,6 +125,11 @@ class PluginBrowser(QObject, Extension):
def downloadProgress(self): def downloadProgress(self):
return self._download_progress return self._download_progress
def setDownloadProgress(self, progress):
if progress != self._download_progress:
self._download_progress = progress
self.onDownloadProgressChanged.emit()
@pyqtSlot(str) @pyqtSlot(str)
def downloadAndInstallPlugin(self, url): def downloadAndInstallPlugin(self, url):
Logger.log("i", "Attempting to download & install plugin from %s", url) Logger.log("i", "Attempting to download & install plugin from %s", url)
@ -124,11 +137,21 @@ class PluginBrowser(QObject, Extension):
self._download_plugin_request = QNetworkRequest(url) self._download_plugin_request = QNetworkRequest(url)
self._download_plugin_request.setRawHeader(*self._request_header) self._download_plugin_request.setRawHeader(*self._request_header)
self._download_plugin_reply = self._network_manager.get(self._download_plugin_request) self._download_plugin_reply = self._network_manager.get(self._download_plugin_request)
self._download_progress = 0 self.setDownloadProgress(0)
self.setIsDownloading(True) self.setIsDownloading(True)
self.onDownloadProgressChanged.emit()
self._download_plugin_reply.downloadProgress.connect(self._onDownloadPluginProgress) self._download_plugin_reply.downloadProgress.connect(self._onDownloadPluginProgress)
@pyqtSlot()
def cancelDownload(self):
Logger.log("i", "user cancelled the download of a plugin")
self._download_plugin_reply.abort()
self._download_plugin_reply.downloadProgress.disconnect(self._onDownloadPluginProgress)
self._download_plugin_reply = None
self._download_plugin_request = None
self.setDownloadProgress(0)
self.setIsDownloading(False)
@pyqtProperty(QObject, notify=pluginsMetadataChanged) @pyqtProperty(QObject, notify=pluginsMetadataChanged)
def pluginsModel(self): def pluginsModel(self):
if self._plugins_model is None: if self._plugins_model is None:
@ -180,6 +203,20 @@ class PluginBrowser(QObject, Extension):
def _onRequestFinished(self, reply): def _onRequestFinished(self, reply):
reply_url = reply.url().toString() reply_url = reply.url().toString()
if reply.error() == QNetworkReply.TimeoutError:
Logger.log("w", "Got a timeout.")
# Reset everything.
self.setDownloadProgress(0)
self.setIsDownloading(False)
if self._download_plugin_reply:
self._download_plugin_reply.downloadProgress.disconnect(self._onDownloadPluginProgress)
self._download_plugin_reply.abort()
self._download_plugin_reply = None
return
elif reply.error() == QNetworkReply.HostNotFoundError:
Logger.log("w", "Unable to reach server.")
return
if reply.operation() == QNetworkAccessManager.GetOperation: if reply.operation() == QNetworkAccessManager.GetOperation:
if reply_url == self._api_url + "plugins": if reply_url == self._api_url + "plugins":
try: try:
@ -193,9 +230,20 @@ class PluginBrowser(QObject, Extension):
# Ignore any operation that is not a get operation # Ignore any operation that is not a get operation
pass pass
def _onNetworkAccesibleChanged(self, accessible):
if accessible == 0:
self.setDownloadProgress(0)
self.setIsDownloading(False)
if self._download_plugin_reply:
self._download_plugin_reply.downloadProgress.disconnect(self._onDownloadPluginProgress)
self._download_plugin_reply.abort()
self._download_plugin_reply = None
def _createNetworkManager(self): def _createNetworkManager(self):
if self._network_manager: if self._network_manager:
self._network_manager.finished.disconnect(self._onRequestFinished) self._network_manager.finished.disconnect(self._onRequestFinished)
self._network_manager.networkAccessibleChanged.disconnect(self._onNetworkAccesibleChanged)
self._network_manager = QNetworkAccessManager() self._network_manager = QNetworkAccessManager()
self._network_manager.finished.connect(self._onRequestFinished) self._network_manager.finished.connect(self._onRequestFinished)
self._network_manager.networkAccessibleChanged.connect(self._onNetworkAccesibleChanged)

View file

@ -14,6 +14,11 @@ UM.Dialog
Item Item
{ {
anchors.fill: parent anchors.fill: parent
Item
{
id: topBar
height: childrenRect.height;
width: parent.width
Label Label
{ {
id: introText id: introText
@ -21,11 +26,21 @@ UM.Dialog
width: parent.width width: parent.width
height: 30 height: 30
} }
Button
{
id: refresh
text: catalog.i18nc("@action:button", "Refresh")
onClicked: manager.requestPluginList()
anchors.right: parent.right
enabled: !manager.isDownloading
}
}
ScrollView ScrollView
{ {
width: parent.width width: parent.width
anchors.top: introText.bottom anchors.top: topBar.bottom
anchors.bottom: progressbar.top anchors.bottom: bottomBar.top
anchors.bottomMargin: UM.Theme.getSize("default_margin").height anchors.bottomMargin: UM.Theme.getSize("default_margin").height
frameVisible: true frameVisible: true
ListView ListView
@ -34,19 +49,45 @@ UM.Dialog
model: manager.pluginsModel model: manager.pluginsModel
anchors.fill: parent anchors.fill: parent
property var activePlugin
delegate: pluginDelegate delegate: pluginDelegate
} }
} }
Item
{
id: bottomBar
width: parent.width
height: closeButton.height
anchors.bottom:parent.bottom
anchors.left: parent.left
ProgressBar ProgressBar
{ {
id: progressbar id: progressbar
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
style: UM.Theme.styles.progressbar
minimumValue: 0; minimumValue: 0;
maximumValue: 100 maximumValue: 100
width: parent.width anchors.left:parent.left
height: 10 anchors.right: closeButton.left
value: manager.downloadProgress anchors.rightMargin: UM.Theme.getSize("default_margin").width
value: manager.isDownloading ? manager.downloadProgress : 0
}
Button
{
id: closeButton
text: catalog.i18nc("@action:button", "Close")
iconName: "dialog-close"
onClicked:
{
if (manager.isDownloading)
{
manager.cancelDownload()
}
base.close();
}
anchors.bottom: parent.bottom
anchors.right: parent.right
}
} }
Item Item
@ -58,10 +99,11 @@ UM.Dialog
Rectangle Rectangle
{ {
width: pluginList.width; width: pluginList.width;
height: childrenRect.height; height: texts.height;
color: index % 2 ? palette.base : palette.alternateBase color: index % 2 ? palette.base : palette.alternateBase
Column Column
{ {
id: texts
width: parent.width width: parent.width
height: childrenRect.height height: childrenRect.height
anchors.left: parent.left anchors.left: parent.left
@ -88,13 +130,48 @@ UM.Dialog
Button Button
{ {
id: downloadButton id: downloadButton
text: !model.already_installed ? catalog.i18nc("@action:button", "Download") : model.can_upgrade ? catalog.i18nc("@action:button", "Upgrade") : catalog.i18nc("@action:button", "Download") text:
onClicked: manager.downloadAndInstallPlugin(model.file_location) {
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.right: parent.right
anchors.rightMargin: UM.Theme.getSize("default_margin").width anchors.rightMargin: UM.Theme.getSize("default_margin").width
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
enabled: (!model.already_installed || model.can_upgrade) && !manager.isDownloading enabled:
{
if (manager.isDownloading)
{
return (pluginList.activePlugin == model);
}
else
{
return (!model.already_installed || model.can_upgrade);
}
}
} }
} }

View file

@ -1,6 +1,6 @@
{ {
"name": "Plugin Browser", "name": "Plugin Browser",
"author": "Ultimaker", "author": "Ultimaker B.V.",
"version": "1.0.0", "version": "1.0.0",
"api": 4, "api": 4,
"description": "Find, manage and install new plugins." "description": "Find, manage and install new plugins."

View file

@ -1,19 +1,18 @@
# Copyright (c) 2015 Ultimaker B.V. # Copyright (c) 2015 Ultimaker B.V.
# Copyright (c) 2013 David Braam # Copyright (c) 2013 David Braam
# Uranium is released under the terms of the AGPLv3 or higher. # Uranium is released under the terms of the AGPLv3 or higher.
from UM.i18n import i18nCatalog
catalog = i18nCatalog("cura")
from . import RemovableDrivePlugin from . import RemovableDrivePlugin
import string import string
import ctypes # type: ignore import ctypes
from ctypes import wintypes # Using ctypes.wintypes in the code below does not seem to work from ctypes import wintypes # Using ctypes.wintypes in the code below does not seem to work
from UM.i18n import i18nCatalog from UM.i18n import i18nCatalog
catalog = i18nCatalog("cura") catalog = i18nCatalog("cura")
# Ignore windows error popups. Fixes the whole "Can't open drive X" when user has an SD card reader.
ctypes.windll.kernel32.SetErrorMode(1)
# WinAPI Constants that we need # WinAPI Constants that we need
# Hardcoded here due to stupid WinDLL stuff that does not give us access to these values. # Hardcoded here due to stupid WinDLL stuff that does not give us access to these values.
DRIVE_REMOVABLE = 2 # [CodeStyle: Windows Enum value] DRIVE_REMOVABLE = 2 # [CodeStyle: Windows Enum value]

View file

@ -1,6 +1,6 @@
{ {
"name": "Removable Drive Output Device Plugin", "name": "Removable Drive Output Device Plugin",
"author": "Ultimaker", "author": "Ultimaker B.V.",
"description": "Provides removable drive hotplugging and writing support.", "description": "Provides removable drive hotplugging and writing support.",
"version": "1.0.0", "version": "1.0.0",
"api": 4, "api": 4,

View file

@ -1,69 +1,37 @@
# Copyright (c) 2015 Ultimaker B.V. # Copyright (c) 2015 Ultimaker B.V.
# Cura is released under the terms of the AGPLv3 or higher. # Cura is released under the terms of the AGPLv3 or higher.
from typing import Any
from cura.CuraApplication import CuraApplication from cura.CuraApplication import CuraApplication
from cura.Settings.ExtruderManager import ExtruderManager
from UM.Extension import Extension from UM.Extension import Extension
from UM.Application import Application from UM.Application import Application
from UM.Preferences import Preferences from UM.Preferences import Preferences
from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator
from UM.Scene.SceneNode import SceneNode
from UM.Message import Message from UM.Message import Message
from UM.i18n import i18nCatalog from UM.i18n import i18nCatalog
from UM.Logger import Logger from UM.Logger import Logger
from UM.Platform import Platform
import time
from UM.Qt.Duration import DurationFormat from UM.Qt.Duration import DurationFormat
from UM.Job import Job
from .SliceInfoJob import SliceInfoJob
import platform import platform
import math import math
import urllib.request import urllib.request
import urllib.parse import urllib.parse
import ssl
import hashlib
import json import json
catalog = i18nCatalog("cura") catalog = i18nCatalog("cura")
class SliceInfoJob(Job):
data = None # type: Any
url = None # type: str
def __init__(self, url, data):
super().__init__()
self.url = url
self.data = data
def run(self):
if not self.url or not self.data:
Logger.log("e", "URL or DATA for sending slice info was not set!")
return
# Submit data
kwoptions = {"data" : self.data,
"timeout" : 5
}
if Platform.isOSX():
kwoptions["context"] = ssl._create_unverified_context()
Logger.log("d", "Sending anonymous slice info to [%s]...", self.url)
try:
f = urllib.request.urlopen(self.url, **kwoptions)
Logger.log("i", "Sent anonymous slice info.")
f.close()
except urllib.error.HTTPError as http_exception:
Logger.log("e", "An HTTP error occurred while trying to send slice information: %s" % http_exception)
except Exception as e: # We don't want any exception to cause problems
Logger.log("e", "An exception occurred while trying to send slice information: %s" % e)
## This Extension runs in the background and sends several bits of information to the Ultimaker servers. ## This Extension runs in the background and sends several bits of information to the Ultimaker servers.
# The data is only sent when the user in question gave permission to do so. All data is anonymous and # The data is only sent when the user in question gave permission to do so. All data is anonymous and
# no model files are being sent (Just a SHA256 hash of the model). # no model files are being sent (Just a SHA256 hash of the model).
class SliceInfo(Extension): class SliceInfo(Extension):
info_url = "https://stats.youmagine.com/curastats/slice" info_url = "http://stats.ultimaker.com/api/cura"
def __init__(self): def __init__(self):
super().__init__() super().__init__()
@ -87,59 +55,137 @@ class SliceInfo(Extension):
Logger.log("d", "'info/send_slice_info' is turned off.") Logger.log("d", "'info/send_slice_info' is turned off.")
return # Do nothing, user does not want to send data return # Do nothing, user does not want to send data
# Listing all files placed on the buildplate global_container_stack = Application.getInstance().getGlobalContainerStack()
modelhashes = [] print_information = Application.getInstance().getPrintInformation()
data = dict() # The data that we're going to submit.
data["time_stamp"] = time.time()
data["schema_version"] = 0
data["cura_version"] = Application.getInstance().getVersion()
active_mode = Preferences.getInstance().getValue("cura/active_mode")
if active_mode == 0:
data["active_mode"] = "recommended"
else:
data["active_mode"] = "custom"
data["machine_settings_changed_by_user"] = global_container_stack.definitionChanges.getId() != "empty"
data["language"] = Preferences.getInstance().getValue("general/language")
data["os"] = {"type": platform.system(), "version": platform.version()}
data["active_machine"] = {"definition_id": global_container_stack.definition.getId(), "manufacturer": global_container_stack.definition.getMetaData().get("manufacturer","")}
data["extruders"] = []
extruders = list(ExtruderManager.getInstance().getMachineExtruders(global_container_stack.getId()))
extruders = sorted(extruders, key = lambda extruder: extruder.getMetaDataEntry("position"))
if not extruders:
extruders = [global_container_stack]
for extruder in extruders:
extruder_dict = dict()
extruder_dict["active"] = ExtruderManager.getInstance().getActiveExtruderStack() == extruder
extruder_dict["material"] = {"GUID": extruder.material.getMetaData().get("GUID", ""),
"type": extruder.material.getMetaData().get("material", ""),
"brand": extruder.material.getMetaData().get("brand", "")
}
extruder_dict["material_used"] = print_information.materialLengths[int(extruder.getMetaDataEntry("position", "0"))]
extruder_dict["variant"] = extruder.variant.getName()
extruder_dict["nozzle_size"] = extruder.getProperty("machine_nozzle_size", "value")
extruder_settings = dict()
extruder_settings["wall_line_count"] = extruder.getProperty("wall_line_count", "value")
extruder_settings["retraction_enable"] = extruder.getProperty("retraction_enable", "value")
extruder_settings["infill_sparse_density"] = extruder.getProperty("infill_sparse_density", "value")
extruder_settings["infill_pattern"] = extruder.getProperty("infill_pattern", "value")
extruder_settings["gradual_infill_steps"] = extruder.getProperty("gradual_infill_steps", "value")
extruder_settings["default_material_print_temperature"] = extruder.getProperty("default_material_print_temperature", "value")
extruder_settings["material_print_temperature"] = extruder.getProperty("material_print_temperature", "value")
extruder_dict["extruder_settings"] = extruder_settings
data["extruders"].append(extruder_dict)
data["quality_profile"] = global_container_stack.quality.getMetaData().get("quality_type")
data["models"] = []
# Listing all files placed on the build plate
for node in DepthFirstIterator(CuraApplication.getInstance().getController().getScene().getRoot()): for node in DepthFirstIterator(CuraApplication.getInstance().getController().getScene().getRoot()):
if node.callDecoration("isSliceable"): if node.callDecoration("isSliceable"):
modelhashes.append(node.getMeshData().getHash()) model = dict()
model["hash"] = node.getMeshData().getHash()
bounding_box = node.getBoundingBox()
model["bounding_box"] = {"minimum": {"x": bounding_box.minimum.x,
"y": bounding_box.minimum.y,
"z": bounding_box.minimum.z},
"maximum": {"x": bounding_box.maximum.x,
"y": bounding_box.maximum.y,
"z": bounding_box.maximum.z}}
model["transformation"] = {"data": str(node.getWorldTransformation().getData()).replace("\n", "")}
extruder_position = node.callDecoration("getActiveExtruderPosition")
model["extruder"] = 0 if extruder_position is None else int(extruder_position)
# Creating md5sums and formatting them as discussed on JIRA model_settings = dict()
modelhash_formatted = ",".join(modelhashes) model_stack = node.callDecoration("getStack")
if model_stack:
model_settings["support_enabled"] = model_stack.getProperty("support_enable", "value")
model_settings["support_extruder_nr"] = int(model_stack.getProperty("support_extruder_nr", "value"))
global_container_stack = Application.getInstance().getGlobalContainerStack() # Mesh modifiers;
model_settings["infill_mesh"] = model_stack.getProperty("infill_mesh", "value")
model_settings["cutting_mesh"] = model_stack.getProperty("cutting_mesh", "value")
model_settings["support_mesh"] = model_stack.getProperty("support_mesh", "value")
model_settings["anti_overhang_mesh"] = model_stack.getProperty("anti_overhang_mesh", "value")
# Get total material used (in mm^3) model_settings["wall_line_count"] = model_stack.getProperty("wall_line_count", "value")
print_information = Application.getInstance().getPrintInformation() model_settings["retraction_enable"] = model_stack.getProperty("retraction_enable", "value")
material_radius = 0.5 * global_container_stack.getProperty("material_diameter", "value")
# Send material per extruder # Infill settings
material_used = [str(math.pi * material_radius * material_radius * material_length) for material_length in print_information.materialLengths] model_settings["infill_sparse_density"] = model_stack.getProperty("infill_sparse_density", "value")
material_used = ",".join(material_used) model_settings["infill_pattern"] = model_stack.getProperty("infill_pattern", "value")
model_settings["gradual_infill_steps"] = model_stack.getProperty("gradual_infill_steps", "value")
containers = { "": global_container_stack.serialize() } model["model_settings"] = model_settings
for container in global_container_stack.getContainers():
container_id = container.getId()
try:
container_serialized = container.serialize()
except NotImplementedError:
Logger.log("w", "Container %s could not be serialized!", container_id)
continue
if container_serialized:
containers[container_id] = container_serialized
else:
Logger.log("i", "No data found in %s to be serialized!", container_id)
# Bundle the collected data data["models"].append(model)
submitted_data = {
"processor": platform.processor(), print_times = print_information.printTimesPerFeature
"machine": platform.machine(), data["print_times"] = {"travel": int(print_times["travel"].getDisplayString(DurationFormat.Format.Seconds)),
"platform": platform.platform(), "support": int(print_times["support"].getDisplayString(DurationFormat.Format.Seconds)),
"settings": json.dumps(containers), # bundle of containers with their serialized contents "infill": int(print_times["infill"].getDisplayString(DurationFormat.Format.Seconds)),
"version": Application.getInstance().getVersion(), "total": int(print_information.currentPrintTime.getDisplayString(DurationFormat.Format.Seconds))}
"modelhash": modelhash_formatted,
"printtime": print_information.currentPrintTime.getDisplayString(DurationFormat.Format.ISO8601), print_settings = dict()
"filament": material_used, print_settings["layer_height"] = global_container_stack.getProperty("layer_height", "value")
"language": Preferences.getInstance().getValue("general/language"),
} # Support settings
print_settings["support_enabled"] = global_container_stack.getProperty("support_enable", "value")
print_settings["support_extruder_nr"] = int(global_container_stack.getProperty("support_extruder_nr", "value"))
# Platform adhesion settings
print_settings["adhesion_type"] = global_container_stack.getProperty("adhesion_type", "value")
# Shell settings
print_settings["wall_line_count"] = global_container_stack.getProperty("wall_line_count", "value")
print_settings["retraction_enable"] = global_container_stack.getProperty("retraction_enable", "value")
# Prime tower settings
print_settings["prime_tower_enable"] = global_container_stack.getProperty("prime_tower_enable", "value")
# Infill settings
print_settings["infill_sparse_density"] = global_container_stack.getProperty("infill_sparse_density", "value")
print_settings["infill_pattern"] = global_container_stack.getProperty("infill_pattern", "value")
print_settings["gradual_infill_steps"] = global_container_stack.getProperty("gradual_infill_steps", "value")
print_settings["print_sequence"] = global_container_stack.getProperty("print_sequence", "value")
data["print_settings"] = print_settings
# Convert data to bytes # Convert data to bytes
submitted_data = urllib.parse.urlencode(submitted_data) binary_data = json.dumps(data).encode("utf-8")
binary_data = submitted_data.encode("utf-8")
# Sending slice info non-blocking # Sending slice info non-blocking
reportJob = SliceInfoJob(self.info_url, binary_data) reportJob = SliceInfoJob(self.info_url, binary_data)
reportJob.start() reportJob.start()
except Exception as e: except Exception:
# We really can't afford to have a mistake here, as this would break the sending of g-code to a device # We really can't afford to have a mistake here, as this would break the sending of g-code to a device
# (Either saving or directly to a printer). The functionality of the slice data is not *that* important. # (Either saving or directly to a printer). The functionality of the slice data is not *that* important.
Logger.log("e", "Exception raised while sending slice info: %s" %(repr(e))) # But we should be notified about these problems of course. Logger.logException("e", "Exception raised while sending slice info.") # But we should be notified about these problems of course.

View file

@ -0,0 +1,38 @@
# Copyright (c) 2017 Ultimaker B.V.
# Cura is released under the terms of the AGPLv3 or higher.
from UM.Job import Job
from UM.Logger import Logger
from UM.Platform import Platform
import ssl
import urllib.request
import urllib.error
class SliceInfoJob(Job):
def __init__(self, url, data):
super().__init__()
self._url = url
self._data = data
def run(self):
if not self._url or not self._data:
Logger.log("e", "URL or DATA for sending slice info was not set!")
return
# Submit data
kwoptions = {"data" : self._data, "timeout" : 5}
if Platform.isOSX():
kwoptions["context"] = ssl._create_unverified_context()
Logger.log("i", "Sending anonymous slice info to [%s]...", self._url)
try:
f = urllib.request.urlopen(self._url, **kwoptions)
Logger.log("i", "Sent anonymous slice info.")
f.close()
except urllib.error.HTTPError:
Logger.logException("e", "An HTTP error occurred while trying to send slice information")
except Exception: # We don't want any exception to cause problems
Logger.logException("e", "An exception occurred while trying to send slice information")

View file

@ -1,6 +1,6 @@
{ {
"name": "Slice info", "name": "Slice info",
"author": "Ultimaker", "author": "Ultimaker B.V.",
"version": "1.0.0", "version": "1.0.0",
"description": "Submits anonymous slice info. Can be disabled through preferences.", "description": "Submits anonymous slice info. Can be disabled through preferences.",
"api": 4, "api": 4,

View file

@ -1,6 +1,6 @@
{ {
"name": "Solid View", "name": "Solid View",
"author": "Ultimaker", "author": "Ultimaker B.V.",
"version": "1.0.0", "version": "1.0.0",
"description": "Provides a normal solid mesh view.", "description": "Provides a normal solid mesh view.",
"api": 4, "api": 4,

View file

@ -625,7 +625,7 @@ class NetworkPrinterOutputDevice(PrinterOutputDevice):
# is ignored. # is ignored.
# \param kwargs Keyword arguments. # \param kwargs Keyword arguments.
def requestWrite(self, nodes, file_name = None, filter_by_machine = False, file_handler = None, **kwargs): def requestWrite(self, nodes, file_name = None, filter_by_machine = False, file_handler = None, **kwargs):
if self._printer_state != "idle": if self._printer_state not in ["idle", ""]:
self._error_message = Message( self._error_message = Message(
i18n_catalog.i18nc("@info:status", "Unable to start a new print job, printer is busy. Current printer status is %s.") % self._printer_state) i18n_catalog.i18nc("@info:status", "Unable to start a new print job, printer is busy. Current printer status is %s.") % self._printer_state)
self._error_message.show() self._error_message.show()

View file

@ -1,6 +1,6 @@
{ {
"name": "UM3 Network Connection", "name": "UM3 Network Connection",
"author": "Ultimaker", "author": "Ultimaker B.V.",
"description": "Manages network connections to Ultimaker 3 printers", "description": "Manages network connections to Ultimaker 3 printers",
"version": "1.0.0", "version": "1.0.0",
"api": 4, "api": 4,

View file

@ -1,6 +1,6 @@
{ {
"name": "USB printing", "name": "USB printing",
"author": "Ultimaker", "author": "Ultimaker B.V.",
"version": "1.0.0", "version": "1.0.0",
"api": 4, "api": 4,
"description": "Accepts G-Code and sends them to a printer. Plugin can also update firmware.", "description": "Accepts G-Code and sends them to a printer. Plugin can also update firmware.",

View file

@ -1,6 +1,6 @@
{ {
"name": "Ultimaker machine actions", "name": "Ultimaker machine actions",
"author": "Ultimaker", "author": "Ultimaker B.V.",
"version": "1.0.0", "version": "1.0.0",
"description": "Provides machine actions for Ultimaker machines (such as bed leveling wizard, selecting upgrades, etc)", "description": "Provides machine actions for Ultimaker machines (such as bed leveling wizard, selecting upgrades, etc)",
"api": 4, "api": 4,

View file

@ -1,6 +1,6 @@
{ {
"name": "Version Upgrade 2.1 to 2.2", "name": "Version Upgrade 2.1 to 2.2",
"author": "Ultimaker", "author": "Ultimaker B.V.",
"version": "1.0.0", "version": "1.0.0",
"description": "Upgrades configurations from Cura 2.1 to Cura 2.2.", "description": "Upgrades configurations from Cura 2.1 to Cura 2.2.",
"api": 4, "api": 4,

View file

@ -1,6 +1,6 @@
{ {
"name": "Version Upgrade 2.2 to 2.4", "name": "Version Upgrade 2.2 to 2.4",
"author": "Ultimaker", "author": "Ultimaker B.V.",
"version": "1.0.0", "version": "1.0.0",
"description": "Upgrades configurations from Cura 2.2 to Cura 2.4.", "description": "Upgrades configurations from Cura 2.2 to Cura 2.4.",
"api": 4, "api": 4,

View file

@ -5,7 +5,6 @@ import configparser #To parse the files we need to upgrade and write the new fil
import io #To serialise configparser output to a string. import io #To serialise configparser output to a string.
from UM.VersionUpgrade import VersionUpgrade from UM.VersionUpgrade import VersionUpgrade
from cura.CuraApplication import CuraApplication
_removed_settings = { #Settings that were removed in 2.5. _removed_settings = { #Settings that were removed in 2.5.
"start_layers_at_same_position", "start_layers_at_same_position",
@ -62,8 +61,13 @@ class VersionUpgrade25to26(VersionUpgrade):
parser["general"]["visible_settings"] = ";".join(new_visible_settings) parser["general"]["visible_settings"] = ";".join(new_visible_settings)
#Change the version number in the file. #Change the version number in the file.
if parser.has_section("general"): #It better have! if "general" not in parser:
parser["general"]["version"] = "5" parser["general"] = {}
parser.set("general", "version", "4")
if "metadata" not in parser:
parser["metadata"] = {}
parser.set("metadata", "setting_version", "1")
#Re-serialise the file. #Re-serialise the file.
output = io.StringIO() output = io.StringIO()
@ -91,11 +95,9 @@ class VersionUpgrade25to26(VersionUpgrade):
if not parser.has_section(each_section): if not parser.has_section(each_section):
parser.add_section(each_section) parser.add_section(each_section)
# Change the version number in the file. # Update version numbers
parser["metadata"]["setting_version"] = str(CuraApplication.SettingVersion)
# Update version
parser["general"]["version"] = "2" parser["general"]["version"] = "2"
parser["metadata"]["setting_version"] = "1"
#Re-serialise the file. #Re-serialise the file.
output = io.StringIO() output = io.StringIO()

View file

@ -1,6 +1,6 @@
{ {
"name": "Version Upgrade 2.5 to 2.6", "name": "Version Upgrade 2.5 to 2.6",
"author": "Ultimaker", "author": "Ultimaker B.V.",
"version": "1.0.0", "version": "1.0.0",
"description": "Upgrades configurations from Cura 2.5 to Cura 2.6.", "description": "Upgrades configurations from Cura 2.5 to Cura 2.6.",
"api": 4, "api": 4,

View file

@ -0,0 +1,167 @@
# Copyright (c) 2017 Ultimaker B.V.
# Cura is released under the terms of the AGPLv3 or higher.
import configparser #To parse the files we need to upgrade and write the new files.
import io #To serialise configparser output to a string.
from UM.VersionUpgrade import VersionUpgrade
from cura.CuraApplication import CuraApplication
# a dict of renamed quality profiles: <old_id> : <new_id>
_renamed_quality_profiles = {
"um3_aa0.4_PVA_Not_Supported_Quality": "um3_aa0.4_PVA_Fast_Print",
"um3_aa0.8_CPEP_Not_Supported_Quality": "um3_aa0.8_CPEP_Fast_Print",
"um3_aa0.8_CPEP_Not_Supported_Superdraft_Quality": "um3_aa0.8_CPEP_Superdraft_Print",
"um3_aa0.8_CPEP_Not_Supported_Verydraft_Quality": "um3_aa0.8_CPEP_Verydraft_Print",
"um3_aa0.8_PC_Not_Supported_Quality": "um3_aa0.8_PC_Fast_Print",
"um3_aa0.8_PC_Not_Supported_Superdraft_Quality": "um3_aa0.8_PC_Superdraft_Print",
"um3_aa0.8_PC_Not_Supported_Verydraft_Quality": "um3_aa0.8_PC_Verydraft_Print",
"um3_aa0.8_PVA_Not_Supported_Quality": "um3_aa0.8_PVA_Fast_Print",
"um3_aa0.8_PVA_Not_Supported_Superdraft_Quality": "um3_aa0.8_PVA_Superdraft_Print",
"um3_bb0.4_ABS_Not_Supported_Quality": "um3_bb0.4_ABS_Fast_print",
"um3_bb0.4_ABS_Not_Supported_Superdraft_Quality": "um3_bb0.4_ABS_Superdraft_Print",
"um3_bb0.4_CPE_Not_Supported_Quality": "um3_bb0.4_CPE_Fast_Print",
"um3_bb0.4_CPE_Not_Supported_Superdraft_Quality": "um3_bb0.4_CPE_Superdraft_Print",
"um3_bb0.4_CPEP_Not_Supported_Quality": "um3_bb0.4_CPEP_Fast_Print",
"um3_bb0.4_CPEP_Not_Supported_Superdraft_Quality": "um3_bb0.4_CPEP_Superdraft_Print",
"um3_bb0.4_Nylon_Not_Supported_Quality": "um3_bb0.4_Nylon_Fast_Print",
"um3_bb0.4_Nylon_Not_Supported_Superdraft_Quality": "um3_bb0.4_Nylon_Superdraft_Print",
"um3_bb0.4_PC_Not_Supported_Quality": "um3_bb0.4_PC_Fast_Print",
"um3_bb0.4_PLA_Not_Supported_Quality": "um3_bb0.4_PLA_Fast_Print",
"um3_bb0.4_PLA_Not_Supported_Superdraft_Quality": "um3_bb0.4_PLA_Superdraft_Print",
"um3_bb0.4_TPU_Not_Supported_Quality": "um3_bb0.4_TPU_Fast_Print",
"um3_bb0.4_TPU_Not_Supported_Superdraft_Quality": "um3_bb0.4_TPU_Superdraft_Print",
"um3_bb0.8_ABS_Not_Supported_Quality": "um3_bb0.8_ABS_Fast_Print",
"um3_bb0.8_ABS_Not_Supported_Superdraft_Quality": "um3_bb0.8_ABS_Superdraft_Print",
"um3_bb0.8_CPE_Not_Supported_Quality": "um3_bb0.8_CPE_Fast_Print",
"um3_bb0.8_CPE_Not_Supported_Superdraft_Quality": "um3_bb0.8_CPE_Superdraft_Print",
"um3_bb0.8_CPEP_Not_Supported_Quality": "um3_bb0.um3_bb0.8_CPEP_Fast_Print",
"um3_bb0.8_CPEP_Not_Supported_Superdraft_Quality": "um3_bb0.8_CPEP_Superdraft_Print",
"um3_bb0.8_Nylon_Not_Supported_Quality": "um3_bb0.8_Nylon_Fast_Print",
"um3_bb0.8_Nylon_Not_Supported_Superdraft_Quality": "um3_bb0.8_Nylon_Superdraft_Print",
"um3_bb0.8_PC_Not_Supported_Quality": "um3_bb0.8_PC_Fast_Print",
"um3_bb0.8_PC_Not_Supported_Superdraft_Quality": "um3_bb0.8_PC_Superdraft_Print",
"um3_bb0.8_PLA_Not_Supported_Quality": "um3_bb0.8_PLA_Fast_Print",
"um3_bb0.8_PLA_Not_Supported_Superdraft_Quality": "um3_bb0.8_PLA_Superdraft_Print",
"um3_bb0.8_TPU_Not_Supported_Quality": "um3_bb0.8_TPU_Fast_print",
"um3_bb0.8_TPU_Not_Supported_Superdraft_Quality": "um3_bb0.8_TPU_Superdraft_Print",
}
## A collection of functions that convert the configuration of the user in Cura
# 2.6 to a configuration for Cura 2.7.
#
# All of these methods are essentially stateless.
class VersionUpgrade26to27(VersionUpgrade):
## Gets the version number from a CFG file in Uranium's 2.6 format.
#
# Since the format may change, this is implemented for the 2.6 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 preferences file from version 2.6 to 2.7.
#
# \param serialised The serialised form of a preferences file.
# \param filename The name of the file to upgrade.
def upgradePreferences(self, serialised, filename):
parser = configparser.ConfigParser(interpolation=None)
parser.read_string(serialised)
# Update version numbers
if "general" not in parser:
parser["general"] = {}
parser["general"]["version"] = "4"
if "metadata" not in parser:
parser["metadata"] = {}
parser["metadata"]["setting_version"] = "2"
# Re-serialise the file.
output = io.StringIO()
parser.write(output)
return [filename], [output.getvalue()]
## Upgrades a container file other than a container stack file from version 2.6 to 2.7.
#
# \param serialised The serialised form of a container file.
# \param filename The name of the file to upgrade.
def upgradeOtherContainer(self, serialised, filename):
parser = configparser.ConfigParser(interpolation=None)
parser.read_string(serialised)
# Update version numbers
if "general" not in parser:
parser["general"] = {}
parser["general"]["version"] = "2"
if "metadata" not in parser:
parser["metadata"] = {}
parser["metadata"]["setting_version"] = "2"
# Re-serialise the file.
output = io.StringIO()
parser.write(output)
return [filename], [output.getvalue()]
## Upgrades a container stack from version 2.6 to 2.7.
#
# \param serialised The serialised form of a container stack.
# \param filename The name of the file to upgrade.
def upgradeStack(self, serialised, filename):
parser = configparser.ConfigParser(interpolation = None)
parser.read_string(serialised)
# Update IDs of the renamed quality profiles
if parser.has_section("containers"):
key_list = [key for key in parser["containers"].keys()]
for key in key_list:
container_id = parser.get("containers", key)
new_id = _renamed_quality_profiles.get(container_id)
if new_id is not None:
parser.set("containers", key, new_id)
for each_section in ("general", "metadata"):
if not parser.has_section(each_section):
parser.add_section(each_section)
# Update version numbers
if "general" not in parser:
parser["general"] = {}
parser["general"]["version"] = "3"
if "metadata" not in parser:
parser["metadata"] = {}
parser["metadata"]["setting_version"] = "2"
# Re-serialise the file.
output = io.StringIO()
parser.write(output)
return [filename], [output.getvalue()]

View file

@ -0,0 +1,62 @@
# Copyright (c) 2017 Ultimaker B.V.
# Cura is released under the terms of the AGPLv3 or higher.
from . import VersionUpgrade26to27
from UM.i18n import i18nCatalog
catalog = i18nCatalog("cura")
upgrade = VersionUpgrade26to27.VersionUpgrade26to27()
def getMetaData():
return {
"version_upgrade": {
# From To Upgrade function
("machine_stack", 3000000): ("machine_stack", 3000002, upgrade.upgradeStack),
("extruder_train", 3000000): ("extruder_train", 3000002, upgrade.upgradeStack),
# In 2.6.x, Preferences are saved with "version = 4" and no setting_version.
# This means those Preferences files will still be treated as "4.0" as defined in VersionUpgrade25to26,
# so the 25to26 upgrade routine will be called again.
#
# To fix this, we first fix the upgrade routine for 25to26 so it actually upgrades to "4.1", and then
# here we can upgrade from "4.1" to "4.2" safely.
#
("preferences", 4000001): ("preferences", 4000002, upgrade.upgradePreferences),
# NOTE: All the instance containers share the same general/version, so we have to update all of them
# if any is updated.
("quality_changes", 2000001): ("quality_changes", 2000002, upgrade.upgradeOtherContainer),
("user", 2000001): ("user", 2000002, upgrade.upgradeOtherContainer),
("quality", 2000001): ("quality", 2000002, upgrade.upgradeOtherContainer),
("definition_changes", 2000001): ("definition_changes", 2000002, upgrade.upgradeOtherContainer),
},
"sources": {
"machine_stack": {
"get_version": upgrade.getCfgVersion,
"location": {"./machine_instances"}
},
"extruder_train": {
"get_version": upgrade.getCfgVersion,
"location": {"./extruders"}
},
"preferences": {
"get_version": upgrade.getCfgVersion,
"location": {"."}
},
"quality_changes": {
"get_version": upgrade.getCfgVersion,
"location": {"./quality"}
},
"user": {
"get_version": upgrade.getCfgVersion,
"location": {"./user"}
},
"definition_changes": {
"get_version": upgrade.getCfgVersion,
"location": {"./machine_instances"}
}
}
}
def register(app):
return { "version_upgrade": upgrade }

View file

@ -0,0 +1,8 @@
{
"name": "Version Upgrade 2.6 to 2.7",
"author": "Ultimaker B.V.",
"version": "1.0.0",
"description": "Upgrades configurations from Cura 2.6 to Cura 2.7.",
"api": 4,
"i18n-catalog": "cura"
}

View file

@ -0,0 +1,191 @@
# Copyright (c) 2017 Ultimaker B.V.
# Cura is released under the terms of the AGPLv3 or higher.
import configparser #To check whether the appropriate exceptions are raised.
import pytest #To register tests with.
import VersionUpgrade26to27 #The module we're testing.
## Creates an instance of the upgrader to test with.
@pytest.fixture
def upgrader():
return VersionUpgrade26to27.VersionUpgrade26to27()
test_cfg_version_good_data = [
{
"test_name": "Simple",
"file_data": """[general]
version = 1
""",
"version": 1000000
},
{
"test_name": "Other Data Around",
"file_data": """[nonsense]
life = good
[general]
version = 3
[values]
layer_height = 0.12
infill_sparse_density = 42
""",
"version": 3000000
},
{
"test_name": "Negative Version", #Why not?
"file_data": """[general]
version = -20
""",
"version": -20000000
},
{
"test_name": "Setting Version",
"file_data": """[general]
version = 1
[metadata]
setting_version = 1
""",
"version": 1000001
},
{
"test_name": "Negative Setting Version",
"file_data": """[general]
version = 1
[metadata]
setting_version = -3
""",
"version": 999997
}
]
## Tests the technique that gets the version number from CFG files.
#
# \param data The parametrised data to test with. It contains a test name
# to debug with, the serialised contents of a CFG file and the correct
# version number in that CFG file.
# \param upgrader The instance of the upgrade class to test.
@pytest.mark.parametrize("data", test_cfg_version_good_data)
def test_cfgVersionGood(data, upgrader):
version = upgrader.getCfgVersion(data["file_data"])
assert version == data["version"]
test_cfg_version_bad_data = [
{
"test_name": "Empty",
"file_data": "",
"exception": configparser.Error #Explicitly not specified further which specific error we're getting, because that depends on the implementation of configparser.
},
{
"test_name": "No General",
"file_data": """[values]
layer_height = 0.1337
""",
"exception": configparser.Error
},
{
"test_name": "No Version",
"file_data": """[general]
true = false
""",
"exception": configparser.Error
},
{
"test_name": "Not a Number",
"file_data": """[general]
version = not-a-text-version-number
""",
"exception": ValueError
},
{
"test_name": "Setting Value NaN",
"file_data": """[general]
version = 4
[metadata]
setting_version = latest_or_something
""",
"exception": ValueError
},
{
"test_name": "Major-Minor",
"file_data": """[general]
version = 1.2
""",
"exception": ValueError
}
]
## Tests whether getting a version number from bad CFG files gives an
# exception.
#
# \param data The parametrised data to test with. It contains a test name
# to debug with, the serialised contents of a CFG file and the class of
# exception it needs to throw.
# \param upgrader The instance of the upgrader to test.
@pytest.mark.parametrize("data", test_cfg_version_bad_data)
def test_cfgVersionBad(data, upgrader):
with pytest.raises(data["exception"]):
upgrader.getCfgVersion(data["file_data"])
test_upgrade_stacks_with_not_supported_data = [
{
"test_name": "Global stack with Not Supported quality profile",
"file_data": """[general]
version = 3
name = Ultimaker 3
id = Ultimaker 3
[metadata]
type = machine
[containers]
0 = Ultimaker 3_user
1 = empty
2 = um3_global_Normal_Quality
3 = empty
4 = empty
5 = empty
6 = ultimaker3
"""
},
{
"test_name": "Extruder stack left with Not Supported quality profile",
"file_data": """[general]
version = 3
name = Extruder 1
id = ultimaker3_extruder_left #2
[metadata]
position = 0
machine = Ultimaker 3
type = extruder_train
[containers]
0 = ultimaker3_extruder_left #2_user
1 = empty
2 = um3_aa0.4_PVA_Not_Supported_Quality
3 = generic_pva_ultimaker3_AA_0.4
4 = ultimaker3_aa04
5 = ultimaker3_extruder_left #2_settings
6 = ultimaker3_extruder_left
"""
}
]
## Tests whether the "Not Supported" quality profiles in the global and extruder stacks are renamed for the 2.7
# version of preferences.
@pytest.mark.parametrize("data", test_upgrade_stacks_with_not_supported_data)
def test_upgradeStacksWithNotSupportedQuality(data, upgrader):
# Read old file
original_parser = configparser.ConfigParser(interpolation = None)
original_parser.read_string(data["file_data"])
# Perform the upgrade.
_, upgraded_stacks = upgrader.upgradeStack(data["file_data"], "<string>")
upgraded_stack = upgraded_stacks[0]
# Find whether the not supported profile has been renamed
parser = configparser.ConfigParser(interpolation = None)
parser.read_string(upgraded_stack)
assert("Not_Supported" not in parser.get("containers", "2"))

View file

@ -1,6 +1,6 @@
{ {
"name": "X-Ray View", "name": "X-Ray View",
"author": "Ultimaker", "author": "Ultimaker B.V.",
"version": "1.0.0", "version": "1.0.0",
"description": "Provides the X-Ray view.", "description": "Provides the X-Ray view.",
"api": 4, "api": 4,

View file

@ -12,9 +12,8 @@ from UM.Util import parseBool
from cura.CuraApplication import CuraApplication from cura.CuraApplication import CuraApplication
import UM.Dictionary import UM.Dictionary
from UM.Settings.InstanceContainer import InstanceContainer, InvalidInstanceError from UM.Settings.InstanceContainer import InstanceContainer
from UM.Settings.ContainerRegistry import ContainerRegistry from UM.Settings.ContainerRegistry import ContainerRegistry
from cura.Settings.CuraContainerRegistry import CuraContainerRegistry
## Handles serializing and deserializing material containers from an XML file ## Handles serializing and deserializing material containers from an XML file
@ -37,7 +36,7 @@ class XmlMaterialProfile(InstanceContainer):
# \return The corresponding setting_version. # \return The corresponding setting_version.
def xmlVersionToSettingVersion(self, xml_version: str) -> int: def xmlVersionToSettingVersion(self, xml_version: str) -> int:
if xml_version == "1.3": if xml_version == "1.3":
return 1 return 2
return 0 #Older than 1.3. return 0 #Older than 1.3.
def getInheritedFiles(self): def getInheritedFiles(self):

View file

@ -21,7 +21,7 @@ class XmlMaterialUpgrader(VersionUpgrade):
def _xmlVersionToSettingVersion(self, xml_version: str) -> int: def _xmlVersionToSettingVersion(self, xml_version: str) -> int:
if xml_version == "1.3": if xml_version == "1.3":
return 1 return 2
return 0 #Older than 1.3. return 0 #Older than 1.3.
def upgradeMaterial(self, serialised, filename): def upgradeMaterial(self, serialised, filename):

View file

@ -19,7 +19,7 @@ def getMetaData():
"mimetype": "application/x-ultimaker-material-profile" "mimetype": "application/x-ultimaker-material-profile"
}, },
"version_upgrade": { "version_upgrade": {
("materials", 1000000): ("materials", 1000001, upgrader.upgradeMaterial), ("materials", 1000000): ("materials", 1000002, upgrader.upgradeMaterial),
}, },
"sources": { "sources": {
"materials": { "materials": {

View file

@ -1,6 +1,6 @@
{ {
"name": "Material Profiles", "name": "Material Profiles",
"author": "Ultimaker", "author": "Ultimaker B.V.",
"version": "1.0.0", "version": "1.0.0",
"description": "Provides capabilities to read and write XML-based material profiles.", "description": "Provides capabilities to read and write XML-based material profiles.",
"api": 4, "api": 4,

View file

@ -50,11 +50,15 @@
"prime_tower_wall_thickness": { "resolve": 0.7 }, "prime_tower_wall_thickness": { "resolve": 0.7 },
"prime_tower_position_x": { "default_value": 50 }, "prime_tower_position_x": { "default_value": 50 },
"prime_tower_position_y": { "default_value": 150 }, "prime_tower_position_y": { "default_value": 150 },
"machine_max_feedrate_z": { "default_value": 20 },
"machine_disallowed_areas": { "default_value": [
[[215, 135], [-215, 135], [-215, 75], [215, 75]]
]},
"machine_start_gcode": { "machine_start_gcode": {
"default_value": "\nM92 E159 ;2288 for V5 extruder\n\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\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"
}, },
"machine_end_gcode": { "machine_end_gcode": {
"default_value": "; -- END GCODE --\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\n; -- end of 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 --"
}, },
"layer_height": { "maximum_value": "(0.8 * min(extruderValues('machine_nozzle_size')))" }, "layer_height": { "maximum_value": "(0.8 * min(extruderValues('machine_nozzle_size')))" },
"layer_height_0": { "maximum_value": "(0.8 * min(extruderValues('machine_nozzle_size')))" }, "layer_height_0": { "maximum_value": "(0.8 * min(extruderValues('machine_nozzle_size')))" },

View file

@ -303,8 +303,9 @@
"type": "enum", "type": "enum",
"options": "options":
{ {
"RepRap (Marlin/Sprinter)": "RepRap (Marlin/Sprinter)", "RepRap (Marlin/Sprinter)": "Marlin",
"RepRap (Volumatric)": "RepRap (Volumetric)", "RepRap (Volumatric)": "Marlin (Volumetric)",
"RepRap (RepRap)": "RepRap",
"UltiGCode": "Ultimaker 2", "UltiGCode": "Ultimaker 2",
"Griffin": "Griffin", "Griffin": "Griffin",
"Makerbot": "Makerbot", "Makerbot": "Makerbot",
@ -677,7 +678,7 @@
"minimum_value_warning": "(0.1 + 0.4 * machine_nozzle_size) if outer_inset_first else 0.1 * machine_nozzle_size", "minimum_value_warning": "(0.1 + 0.4 * machine_nozzle_size) if outer_inset_first else 0.1 * machine_nozzle_size",
"maximum_value_warning": "2 * machine_nozzle_size", "maximum_value_warning": "2 * machine_nozzle_size",
"default_value": 0.4, "default_value": 0.4,
"value": "wall_line_width", "value": "extruderValue(wall_0_extruder_nr, 'wall_line_width')",
"type": "float", "type": "float",
"limit_to_extruder": "wall_0_extruder_nr", "limit_to_extruder": "wall_0_extruder_nr",
"settable_per_mesh": true "settable_per_mesh": true
@ -1136,6 +1137,19 @@
"limit_to_extruder": "wall_0_extruder_nr", "limit_to_extruder": "wall_0_extruder_nr",
"settable_per_mesh": true "settable_per_mesh": true
}, },
"xy_offset_layer_0":
{
"label": "Initial Layer Horizontal Expansion",
"description": "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\".",
"unit": "mm",
"type": "float",
"minimum_value_warning": "-1",
"maximum_value_warning": "1",
"default_value": 0,
"value": "xy_offset",
"limit_to_extruder": "wall_0_extruder_nr",
"settable_per_mesh": true
},
"z_seam_type": "z_seam_type":
{ {
"label": "Z Seam Alignment", "label": "Z Seam Alignment",
@ -1175,6 +1189,17 @@
"limit_to_extruder": "wall_0_extruder_nr", "limit_to_extruder": "wall_0_extruder_nr",
"settable_per_mesh": true "settable_per_mesh": true
}, },
"z_seam_relative":
{
"label": "Z Seam Relative",
"description": "When enabled, the z seam coordinates are relative to each part's centre. When disabled, the coordinates define an absolute position on the build plate.",
"unit": "mm",
"type": "bool",
"default_value": false,
"enabled": "z_seam_type == 'back'",
"limit_to_extruder": "wall_0_extruder_nr",
"settable_per_mesh": true
},
"skin_no_small_gaps_heuristic": "skin_no_small_gaps_heuristic":
{ {
"label": "Ignore Small Z Gaps", "label": "Ignore Small Z Gaps",
@ -1524,6 +1549,7 @@
"maximum_value_warning": "285", "maximum_value_warning": "285",
"enabled": "machine_nozzle_temp_enabled", "enabled": "machine_nozzle_temp_enabled",
"settable_per_extruder": true, "settable_per_extruder": true,
"settable_per_mesh": false,
"minimum_value": "-273.15" "minimum_value": "-273.15"
}, },
"material_print_temperature": "material_print_temperature":
@ -4357,7 +4383,7 @@
"unit": "mm", "unit": "mm",
"type": "float", "type": "float",
"default_value": 2, "default_value": 2,
"value": "round(max(2 * max(extruderValues('prime_tower_line_width')), 0.5 * (resolveOrValue('prime_tower_size') - math.sqrt(max(0, resolveOrValue('prime_tower_size') ** 2 - max(extruderValues('prime_tower_min_volume')) / resolveOrValue('layer_height'))))), 3)", "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)",
"resolve": "max(extruderValues('prime_tower_wall_thickness'))", "resolve": "max(extruderValues('prime_tower_wall_thickness'))",
"minimum_value": "0.001", "minimum_value": "0.001",
"minimum_value_warning": "2 * min(extruderValues('prime_tower_line_width')) - 0.0001", "minimum_value_warning": "2 * min(extruderValues('prime_tower_line_width')) - 0.0001",
@ -4376,8 +4402,6 @@
"unit": "mm", "unit": "mm",
"enabled": "resolveOrValue('prime_tower_enable')", "enabled": "resolveOrValue('prime_tower_enable')",
"default_value": 200, "default_value": 200,
"minimum_value_warning": "-1000",
"maximum_value_warning": "1000",
"maximum_value": "machine_width / 2 if machine_center_is_zero else machine_width", "maximum_value": "machine_width / 2 if machine_center_is_zero else machine_width",
"minimum_value": "resolveOrValue('prime_tower_size') - machine_width / 2 if machine_center_is_zero else resolveOrValue('prime_tower_size')", "minimum_value": "resolveOrValue('prime_tower_size') - machine_width / 2 if machine_center_is_zero else resolveOrValue('prime_tower_size')",
"settable_per_mesh": false, "settable_per_mesh": false,
@ -4391,8 +4415,6 @@
"unit": "mm", "unit": "mm",
"enabled": "resolveOrValue('prime_tower_enable')", "enabled": "resolveOrValue('prime_tower_enable')",
"default_value": 200, "default_value": 200,
"minimum_value_warning": "-1000",
"maximum_value_warning": "1000",
"maximum_value": "machine_depth / 2 - resolveOrValue('prime_tower_size') if machine_center_is_zero else machine_depth - resolveOrValue('prime_tower_size')", "maximum_value": "machine_depth / 2 - resolveOrValue('prime_tower_size') if machine_center_is_zero else machine_depth - resolveOrValue('prime_tower_size')",
"minimum_value": "machine_depth / -2 if machine_center_is_zero else 0", "minimum_value": "machine_depth / -2 if machine_center_is_zero else 0",
"settable_per_mesh": false, "settable_per_mesh": false,
@ -4897,6 +4919,16 @@
"limit_to_extruder": "infill_extruder_nr", "limit_to_extruder": "infill_extruder_nr",
"settable_per_mesh": true "settable_per_mesh": true
}, },
"spaghetti_infill_stepped":
{
"label": "Spaghetti Infill Stepping",
"description": "Whether to print spaghetti infill in steps or extrude all the infill filament at the end of the print.",
"type": "bool",
"default_value": true,
"enabled": "infill_sparse_density > 0 and spaghetti_infill_enabled",
"limit_to_extruder": "infill_extruder_nr",
"settable_per_mesh": true
},
"spaghetti_max_infill_angle": "spaghetti_max_infill_angle":
{ {
"label": "Spaghetti Maximum Infill Angle", "label": "Spaghetti Maximum Infill Angle",
@ -4907,7 +4939,7 @@
"minimum_value": "0", "minimum_value": "0",
"maximum_value": "90", "maximum_value": "90",
"maximum_value_warning": "45", "maximum_value_warning": "45",
"enabled": "infill_sparse_density > 0 and spaghetti_infill_enabled", "enabled": "infill_sparse_density > 0 and spaghetti_infill_enabled and spaghetti_infill_stepped",
"limit_to_extruder": "infill_extruder_nr", "limit_to_extruder": "infill_extruder_nr",
"settable_per_mesh": true "settable_per_mesh": true
}, },
@ -4920,7 +4952,7 @@
"default_value": 2.0, "default_value": 2.0,
"minimum_value": "layer_height", "minimum_value": "layer_height",
"maximum_value_warning": "10.0", "maximum_value_warning": "10.0",
"enabled": "infill_sparse_density > 0 and spaghetti_infill_enabled", "enabled": "infill_sparse_density > 0 and spaghetti_infill_enabled and spaghetti_infill_stepped",
"limit_to_extruder": "infill_extruder_nr", "limit_to_extruder": "infill_extruder_nr",
"settable_per_mesh": true "settable_per_mesh": true
}, },
@ -4950,6 +4982,19 @@
"limit_to_extruder": "infill_extruder_nr", "limit_to_extruder": "infill_extruder_nr",
"settable_per_mesh": true "settable_per_mesh": true
}, },
"spaghetti_infill_extra_volume":
{
"label": "Spaghetti Infill Extra Volume",
"description": "A correction term to adjust the total volume being extruded each time when filling spaghetti.",
"unit": "mm³",
"type": "float",
"default_value": 0,
"minimum_value_warning": "0",
"maximum_value_warning": "100",
"enabled": "infill_sparse_density > 0 and spaghetti_infill_enabled",
"limit_to_extruder": "infill_extruder_nr",
"settable_per_mesh": true
},
"support_conical_enabled": "support_conical_enabled":
{ {
"label": "Enable Conical Support", "label": "Enable Conical Support",

View file

@ -14,7 +14,7 @@
"maximum_value": "3" "maximum_value": "3"
}, },
"machine_nozzle_offset_x": { "default_value": 0.0 }, "machine_nozzle_offset_x": { "default_value": 0.0 },
"machine_nozzle_offset_y": { "default_value": 60.0 }, "machine_nozzle_offset_y": { "default_value": 0.0 },
"machine_extruder_start_code": { "machine_extruder_start_code": {
"default_value": "\n;start extruder_2\n\nM117 printing\n" "default_value": "\n;start extruder_2\n\nM117 printing\n"
}, },

View file

@ -13,8 +13,8 @@
"default_value": 3, "default_value": 3,
"maximum_value": "3" "maximum_value": "3"
}, },
"machine_nozzle_offset_x": { "default_value": 24.0 }, "machine_nozzle_offset_x": { "default_value": 0.0 },
"machine_nozzle_offset_y": { "default_value": 60.0 }, "machine_nozzle_offset_y": { "default_value": 0.0 },
"machine_extruder_start_code": { "machine_extruder_start_code": {
"default_value": "\n;start extruder_3\n\nM117 printing\n" "default_value": "\n;start extruder_3\n\nM117 printing\n"
}, },

View file

@ -1,4 +1,4 @@
// Copyright (c) 2015 Ultimaker B.V. // Copyright (c) 2017 Ultimaker B.V.
// Cura is released under the terms of the AGPLv3 or higher. // Cura is released under the terms of the AGPLv3 or higher.
import QtQuick 2.2 import QtQuick 2.2
@ -18,7 +18,24 @@ UM.MainWindow
//: Cura application window title //: Cura application window title
title: catalog.i18nc("@title:window","Cura"); title: catalog.i18nc("@title:window","Cura");
viewportRect: Qt.rect(0, 0, (base.width - sidebar.width) / base.width, 1.0) viewportRect: Qt.rect(0, 0, (base.width - sidebar.width) / base.width, 1.0)
property bool monitoringPrint: false property bool showPrintMonitor: false
Connections
{
target: Printer
onShowPrintMonitor:
{
if (show)
{
topbar.startMonitoringPrint()
}
else
{
topbar.stopMonitoringPrint()
}
}
}
Component.onCompleted: Component.onCompleted:
{ {
CuraApplication.setMinimumWindowSize(UM.Theme.getSize("window_minimum_size")) CuraApplication.setMinimumWindowSize(UM.Theme.getSize("window_minimum_size"))
@ -329,7 +346,8 @@ UM.MainWindow
tooltip: ''; tooltip: '';
anchors anchors
{ {
top: parent.top; top: topbar.bottom;
topMargin: UM.Theme.getSize("default_margin").height;
left: parent.left; left: parent.left;
} }
action: Cura.Actions.open; action: Cura.Actions.open;
@ -371,19 +389,30 @@ UM.MainWindow
} }
} }
Topbar
{
id: topbar
anchors.left:parent.left
anchors.right: parent.right
anchors.top: parent.top
monitoringPrint: base.showPrintMonitor
onStartMonitoringPrint: base.showPrintMonitor = true
onStopMonitoringPrint: base.showPrintMonitor = false
}
Sidebar Sidebar
{ {
id: sidebar; id: sidebar;
anchors anchors
{ {
top: parent.top; top: topbar.bottom;
bottom: parent.bottom; bottom: parent.bottom;
right: parent.right; right: parent.right;
} }
z: 1 z: 1
onMonitoringPrintChanged: base.monitoringPrint = monitoringPrint
width: UM.Theme.getSize("sidebar").width; width: UM.Theme.getSize("sidebar").width;
monitoringPrint: base.showPrintMonitor
} }
Button Button
@ -412,13 +441,13 @@ UM.MainWindow
color: UM.Theme.getColor("viewport_overlay") color: UM.Theme.getColor("viewport_overlay")
anchors anchors
{ {
top: parent.top top: topbar.bottom
bottom: parent.bottom bottom: parent.bottom
left:parent.left left:parent.left
right: sidebar.left right: sidebar.left
} }
visible: opacity > 0 visible: opacity > 0
opacity: base.monitoringPrint ? 0.75 : 0 opacity: base.showPrintMonitor ? 0.75 : 0
Behavior on opacity { NumberAnimation { duration: 100; } } Behavior on opacity { NumberAnimation { duration: 100; } }
@ -433,12 +462,10 @@ UM.MainWindow
Loader Loader
{ {
sourceComponent: Cura.MachineManager.printerOutputDevices.length > 0 ? Cura.MachineManager.printerOutputDevices[0].monitorItem: null sourceComponent: Cura.MachineManager.printerOutputDevices.length > 0 ? Cura.MachineManager.printerOutputDevices[0].monitorItem: null
visible: base.monitoringPrint visible: base.showPrintMonitor
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
anchors.horizontalCenterOffset: - UM.Theme.getSize("sidebar").width / 2 anchors.horizontalCenterOffset: - UM.Theme.getSize("sidebar").width / 2
} }
UM.MessageStack UM.MessageStack

View file

@ -86,6 +86,8 @@ UM.PreferencesPage
centerOnSelectCheckbox.checked = boolCheck(UM.Preferences.getValue("view/center_on_select")) centerOnSelectCheckbox.checked = boolCheck(UM.Preferences.getValue("view/center_on_select"))
UM.Preferences.resetPreference("view/invert_zoom"); UM.Preferences.resetPreference("view/invert_zoom");
invertZoomCheckbox.checked = boolCheck(UM.Preferences.getValue("view/invert_zoom")) invertZoomCheckbox.checked = boolCheck(UM.Preferences.getValue("view/invert_zoom"))
UM.Preferences.resetPreference("view/zoom_to_mouse");
zoomToMouseCheckbox.checked = boolCheck(UM.Preferences.getValue("view/zoom_to_mouse"))
UM.Preferences.resetPreference("view/top_layer_count"); UM.Preferences.resetPreference("view/top_layer_count");
topLayerCountCheckbox.checked = boolCheck(UM.Preferences.getValue("view/top_layer_count")) topLayerCountCheckbox.checked = boolCheck(UM.Preferences.getValue("view/top_layer_count"))
@ -355,6 +357,20 @@ UM.PreferencesPage
} }
} }
UM.TooltipArea {
width: childrenRect.width;
height: childrenRect.height;
text: catalog.i18nc("@info:tooltip", "Should zooming move in the direction of the mouse?")
CheckBox
{
id: zoomToMouseCheckbox
text: catalog.i18nc("@action:button", "Zoom toward mouse direction");
checked: boolCheck(UM.Preferences.getValue("view/zoom_to_mouse"))
onClicked: UM.Preferences.setValue("view/zoom_to_mouse", checked)
}
}
UM.TooltipArea { UM.TooltipArea {
width: childrenRect.width width: childrenRect.width
height: childrenRect.height height: childrenRect.height

View file

@ -169,9 +169,11 @@ TabView
// This does not use a SettingPropertyProvider, because we need to make the change to all containers // This does not use a SettingPropertyProvider, because we need to make the change to all containers
// which derive from the same base_file // which derive from the same base_file
var old_diameter = Cura.ContainerManager.getContainerProperty(base.containerId, "material_diameter", "value").toString(); var old_diameter = Cura.ContainerManager.getContainerProperty(base.containerId, "material_diameter", "value").toString();
base.setMetaDataEntry("approximate_diameter", properties.approximate_diameter, Math.round(value).toString()); var old_approximate_diameter = Cura.ContainerManager.getContainerMetaDataEntry(base.containerId, "approximate_diameter");
base.setMetaDataEntry("approximate_diameter", old_approximate_diameter, Math.round(value).toString());
base.setMetaDataEntry("properties/diameter", properties.diameter, value); base.setMetaDataEntry("properties/diameter", properties.diameter, value);
if (Cura.MachineManager.filterMaterialsByMachine && properties.approximate_diameter != Cura.MachineManager.activeMachine.approximateMaterialDiameter) var new_approximate_diameter = Cura.ContainerManager.getContainerMetaDataEntry(base.containerId, "approximate_diameter");
if (Cura.MachineManager.filterMaterialsByMachine && new_approximate_diameter != Cura.MachineManager.activeMachine.approximateMaterialDiameter)
{ {
Cura.MaterialManager.showMaterialWarningMessage(base.containerId, old_diameter); Cura.MaterialManager.showMaterialWarningMessage(base.containerId, old_diameter);
} }

View file

@ -1,5 +1,5 @@
// Copyright (c) 2016 Ultimaker B.V. //Copyright (c) 2017 Ultimaker B.V.
// Cura is released under the terms of the AGPLv3 or higher. //Cura is released under the terms of the AGPLv3 or higher.
import QtQuick 2.1 import QtQuick 2.1
import QtQuick.Controls 1.1 import QtQuick.Controls 1.1
@ -139,6 +139,7 @@ UM.ManagementPage
enabled: base.currentItem != null && base.currentItem.id != Cura.MachineManager.activeMaterialId && Cura.MachineManager.hasMaterials enabled: base.currentItem != null && base.currentItem.id != Cura.MachineManager.activeMaterialId && Cura.MachineManager.hasMaterials
onClicked: onClicked:
{ {
forceActiveFocus();
Cura.MachineManager.setActiveMaterial(base.currentItem.id) Cura.MachineManager.setActiveMaterial(base.currentItem.id)
currentItem = base.model.getItem(base.objectList.currentIndex) // Refresh the current item. currentItem = base.model.getItem(base.objectList.currentIndex) // Refresh the current item.
} }
@ -149,6 +150,7 @@ UM.ManagementPage
iconName: "list-add" iconName: "list-add"
onClicked: onClicked:
{ {
forceActiveFocus();
var material_id = Cura.ContainerManager.createMaterial() var material_id = Cura.ContainerManager.createMaterial()
if(material_id == "") if(material_id == "")
{ {
@ -168,6 +170,7 @@ UM.ManagementPage
enabled: base.currentItem != null enabled: base.currentItem != null
onClicked: onClicked:
{ {
forceActiveFocus();
var base_file = Cura.ContainerManager.getContainerMetaDataEntry(base.currentItem.id, "base_file") var base_file = Cura.ContainerManager.getContainerMetaDataEntry(base.currentItem.id, "base_file")
// We need to copy the base container instead of the specific variant. // We need to copy the base container instead of the specific variant.
var material_id = base_file == "" ? Cura.ContainerManager.duplicateMaterial(base.currentItem.id): Cura.ContainerManager.duplicateMaterial(base_file) var material_id = base_file == "" ? Cura.ContainerManager.duplicateMaterial(base.currentItem.id): Cura.ContainerManager.duplicateMaterial(base_file)
@ -187,20 +190,32 @@ UM.ManagementPage
text: catalog.i18nc("@action:button", "Remove"); text: catalog.i18nc("@action:button", "Remove");
iconName: "list-remove"; iconName: "list-remove";
enabled: base.currentItem != null && !base.currentItem.readOnly && !Cura.ContainerManager.isContainerUsed(base.currentItem.id) enabled: base.currentItem != null && !base.currentItem.readOnly && !Cura.ContainerManager.isContainerUsed(base.currentItem.id)
onClicked: confirmDialog.open() onClicked:
{
forceActiveFocus();
confirmDialog.open();
}
}, },
Button Button
{ {
text: catalog.i18nc("@action:button", "Import"); text: catalog.i18nc("@action:button", "Import");
iconName: "document-import"; iconName: "document-import";
onClicked: importDialog.open(); onClicked:
{
forceActiveFocus();
importDialog.open();
}
visible: true; visible: true;
}, },
Button Button
{ {
text: catalog.i18nc("@action:button", "Export") text: catalog.i18nc("@action:button", "Export")
iconName: "document-export" iconName: "document-export"
onClicked: exportDialog.open() onClicked:
{
forceActiveFocus();
exportDialog.open();
}
enabled: currentItem != null enabled: currentItem != null
} }
] ]

View file

@ -1,4 +1,4 @@
// Copyright (c) 2015 Ultimaker B.V. // Copyright (c) 2017 Ultimaker B.V.
// Cura is released under the terms of the AGPLv3 or higher. // Cura is released under the terms of the AGPLv3 or higher.
import QtQuick 2.2 import QtQuick 2.2
@ -24,7 +24,7 @@ Item {
{ {
if(!activity) if(!activity)
{ {
return catalog.i18nc("@label:PrintjobStatus", "Please load a 3d model"); return catalog.i18nc("@label:PrintjobStatus", "Please load a 3D model");
} }
switch(base.backendState) switch(base.backendState)

View file

@ -15,24 +15,15 @@ Rectangle
id: base; id: base;
property int currentModeIndex; property int currentModeIndex;
property bool monitoringPrint: false; // When adding more "tabs", one want to replace this bool with a ListModel
property bool hideSettings: PrintInformation.preSliced property bool hideSettings: PrintInformation.preSliced
Connections
{
target: Printer
onShowPrintMonitor:
{
base.monitoringPrint = show;
showSettings.checked = !show;
showMonitor.checked = show;
}
}
// Is there an output device for this printer? // Is there an output device for this printer?
property bool printerConnected: Cura.MachineManager.printerOutputDevices.length != 0 property bool printerConnected: Cura.MachineManager.printerOutputDevices.length != 0
property bool printerAcceptsCommands: printerConnected && Cura.MachineManager.printerOutputDevices[0].acceptsCommands property bool printerAcceptsCommands: printerConnected && Cura.MachineManager.printerOutputDevices[0].acceptsCommands
property int backendState: UM.Backend.state; property int backendState: UM.Backend.state;
property bool monitoringPrint: false
color: UM.Theme.getColor("sidebar") color: UM.Theme.getColor("sidebar")
UM.I18nCatalog { id: catalog; name:"cura"} UM.I18nCatalog { id: catalog; name:"cura"}
@ -88,227 +79,10 @@ Rectangle
} }
} }
// Printer selection and mode selection buttons for changing between Setting & Monitor print mode
Rectangle
{
id: sidebarHeaderBar
anchors.left: parent.left
anchors.right: parent.right
height: childrenRect.height
color: UM.Theme.getColor("sidebar_header_bar")
Row
{
anchors.left: parent.left
anchors.right: parent.right
anchors.rightMargin: UM.Theme.getSize("default_margin").width
spacing: UM.Theme.getSize("default_margin").width
ToolButton
{
id: machineSelection
text: Cura.MachineManager.activeMachineName
width: parent.width - (showSettings.width + showMonitor.width + 2 * UM.Theme.getSize("default_margin").width)
height: UM.Theme.getSize("sidebar_header").height
tooltip: Cura.MachineManager.activeMachineName
anchors.verticalCenter: parent.verticalCenter
style: ButtonStyle {
background: Rectangle {
color: {
if(control.pressed) {
return UM.Theme.getColor("sidebar_header_active");
} else if(control.hovered) {
return UM.Theme.getColor("sidebar_header_hover");
} else {
return UM.Theme.getColor("sidebar_header_bar");
}
}
Behavior on color { ColorAnimation { duration: 50; } }
Rectangle {
id: underline;
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
height: UM.Theme.getSize("sidebar_header_highlight").height
color: UM.Theme.getColor("sidebar_header_highlight_hover")
visible: control.hovered || control.pressed
}
UM.RecolorImage {
id: downArrow
anchors.verticalCenter: parent.verticalCenter
anchors.right: parent.right
anchors.rightMargin: UM.Theme.getSize("default_margin").width
width: UM.Theme.getSize("standard_arrow").width
height: UM.Theme.getSize("standard_arrow").height
sourceSize.width: width
sourceSize.height: width
color: UM.Theme.getColor("text_reversed")
source: UM.Theme.getIcon("arrow_bottom")
}
Label {
id: sidebarComboBoxLabel
color: UM.Theme.getColor("text_reversed")
text: control.text;
elide: Text.ElideRight;
anchors.left: parent.left;
anchors.leftMargin: UM.Theme.getSize("default_margin").width
anchors.right: downArrow.left;
anchors.rightMargin: control.rightMargin;
anchors.verticalCenter: parent.verticalCenter;
font: UM.Theme.getFont("large")
}
}
label: Label{}
}
menu: PrinterMenu { }
}
Button
{
id: showSettings
width: height
height: UM.Theme.getSize("sidebar_header").height
onClicked: monitoringPrint = false
iconSource: UM.Theme.getIcon("tab_settings");
property color overlayColor: "transparent"
property string overlayIconSource: ""
checkable: true
checked: !monitoringPrint
exclusiveGroup: sidebarHeaderBarGroup
property string tooltipText: catalog.i18nc("@tooltip", "<b>Print Setup</b><br/><br/>Edit or review the settings for the active print job.")
onHoveredChanged: {
if (hovered)
{
tooltipDelayTimer.item = showSettings
tooltipDelayTimer.text = tooltipText
tooltipDelayTimer.start();
}
else
{
tooltipDelayTimer.stop();
base.hideTooltip();
}
}
style: UM.Theme.styles.sidebar_header_tab
}
Button
{
id: showMonitor
width: height
height: UM.Theme.getSize("sidebar_header").height
onClicked: monitoringPrint = true
iconSource: printerConnected ? UM.Theme.getIcon("tab_monitor_with_status") : UM.Theme.getIcon("tab_monitor")
property color overlayColor:
{
if(!printerAcceptsCommands)
{
return UM.Theme.getColor("status_unknown");
}
if(Cura.MachineManager.printerOutputDevices[0].printerState == "maintenance")
{
return UM.Theme.getColor("status_busy");
}
switch(Cura.MachineManager.printerOutputDevices[0].jobState)
{
case "printing":
case "pre_print":
case "wait_cleanup":
case "pausing":
case "resuming":
return UM.Theme.getColor("status_busy");
case "ready":
case "":
return UM.Theme.getColor("status_ready");
case "paused":
return UM.Theme.getColor("status_paused");
case "error":
return UM.Theme.getColor("status_stopped");
case "offline":
return UM.Theme.getColor("status_offline");
default:
return UM.Theme.getColor("text_reversed");
}
}
property string overlayIconSource:
{
if(!printerConnected)
{
return "";
}
else if(!printerAcceptsCommands)
{
return UM.Theme.getIcon("tab_status_unknown");
}
if(Cura.MachineManager.printerOutputDevices[0].printerState == "maintenance")
{
return UM.Theme.getIcon("tab_status_busy");
}
switch(Cura.MachineManager.printerOutputDevices[0].jobState)
{
case "printing":
case "pre_print":
case "wait_cleanup":
case "pausing":
case "resuming":
return UM.Theme.getIcon("tab_status_busy");
case "ready":
case "":
return UM.Theme.getIcon("tab_status_connected")
case "paused":
return UM.Theme.getIcon("tab_status_paused")
case "error":
return UM.Theme.getIcon("tab_status_stopped")
case "offline":
return UM.Theme.getIcon("tab_status_offline")
default:
return ""
}
}
checkable: true
checked: monitoringPrint
exclusiveGroup: sidebarHeaderBarGroup
property string tooltipText: catalog.i18nc("@tooltip", "<b>Print Monitor</b><br/><br/>Monitor the state of the connected printer and the print job in progress.")
onHoveredChanged: {
if (hovered)
{
tooltipDelayTimer.item = showMonitor
tooltipDelayTimer.text = tooltipText
tooltipDelayTimer.start();
}
else
{
tooltipDelayTimer.stop();
base.hideTooltip();
}
}
style: UM.Theme.styles.sidebar_header_tab
}
ExclusiveGroup { id: sidebarHeaderBarGroup }
}
}
SidebarHeader { SidebarHeader {
id: header id: header
width: parent.width width: parent.width
anchors.top: sidebarHeaderBar.bottom
onShowTooltip: base.showTooltip(item, location, text) onShowTooltip: base.showTooltip(item, location, text)
onHideTooltip: base.hideTooltip() onHideTooltip: base.hideTooltip()
} }

View file

@ -106,23 +106,14 @@ Item
opacity: panel.item && panel.width > 0 ? 1 : 0 opacity: panel.item && panel.width > 0 ? 1 : 0
Behavior on opacity { NumberAnimation { duration: 100 } } Behavior on opacity { NumberAnimation { duration: 100 } }
color: UM.Theme.getColor("lining"); color: UM.Theme.getColor("tool_panel_background")
borderColor: UM.Theme.getColor("lining")
borderWidth: UM.Theme.getSize("default_lining").width
UM.PointingRectangle
{
id: panelBackground;
color: UM.Theme.getColor("tool_panel_background");
anchors.fill: parent
anchors.margins: UM.Theme.getSize("default_lining").width
target: Qt.point(-UM.Theme.getSize("default_margin").width, UM.Theme.getSize("button").height/2)
arrowSize: parent.arrowSize
MouseArea //Catch all mouse events (so scene doesnt handle them) MouseArea //Catch all mouse events (so scene doesnt handle them)
{ {
anchors.fill: parent anchors.fill: parent
} }
}
Loader Loader
{ {

216
resources/qml/Topbar.qml Normal file
View file

@ -0,0 +1,216 @@
// Copyright (c) 2017 Ultimaker B.V.
// Cura is released under the terms of the AGPLv3 or higher.
import QtQuick 2.2
import QtQuick.Controls 1.1
import QtQuick.Controls.Styles 1.1
import QtQuick.Layouts 1.1
import UM 1.2 as UM
import Cura 1.0 as Cura
import "Menus"
Rectangle
{
id: base
anchors.left: parent.left
anchors.right: parent.right
height: UM.Theme.getSize("sidebar_header").height
color: UM.Theme.getColor("sidebar_header_bar")
property bool printerConnected: Cura.MachineManager.printerOutputDevices.length != 0
property bool printerAcceptsCommands: printerConnected && Cura.MachineManager.printerOutputDevices[0].acceptsCommands
property bool monitoringPrint: false
signal startMonitoringPrint()
signal stopMonitoringPrint()
UM.I18nCatalog
{
id: catalog
name:"cura"
}
Row
{
anchors.left: parent.left
anchors.right: machineSelection.left
anchors.rightMargin: UM.Theme.getSize("default_margin").width
spacing: UM.Theme.getSize("default_margin").width
Button
{
id: showSettings
height: UM.Theme.getSize("sidebar_header").height
onClicked: base.stopMonitoringPrint()
iconSource: UM.Theme.getIcon("tab_settings");
property color overlayColor: "transparent"
property string overlayIconSource: ""
text: catalog.i18nc("@title:tab","Prepare")
checkable: true
checked: !base.monitoringPrint
exclusiveGroup: sidebarHeaderBarGroup
style: UM.Theme.styles.topbar_header_tab
}
Button
{
id: showMonitor
height: UM.Theme.getSize("sidebar_header").height
onClicked: base.startMonitoringPrint()
text: catalog.i18nc("@title:tab", "Print")
iconSource: printerConnected ? UM.Theme.getIcon("tab_monitor_with_status") : UM.Theme.getIcon("tab_monitor")
property color overlayColor:
{
if(!printerAcceptsCommands)
{
return UM.Theme.getColor("status_unknown");
}
if(Cura.MachineManager.printerOutputDevices[0].printerState == "maintenance")
{
return UM.Theme.getColor("status_busy");
}
switch(Cura.MachineManager.printerOutputDevices[0].jobState)
{
case "printing":
case "pre_print":
case "wait_cleanup":
case "pausing":
case "resuming":
return UM.Theme.getColor("status_busy");
case "ready":
case "":
return UM.Theme.getColor("status_ready");
case "paused":
return UM.Theme.getColor("status_paused");
case "error":
return UM.Theme.getColor("status_stopped");
case "offline":
return UM.Theme.getColor("status_offline");
default:
return UM.Theme.getColor("text_reversed");
}
}
property string overlayIconSource:
{
if(!printerConnected)
{
return "";
}
else if(!printerAcceptsCommands)
{
return UM.Theme.getIcon("tab_status_unknown");
}
if(Cura.MachineManager.printerOutputDevices[0].printerState == "maintenance")
{
return UM.Theme.getIcon("tab_status_busy");
}
switch(Cura.MachineManager.printerOutputDevices[0].jobState)
{
case "printing":
case "pre_print":
case "wait_cleanup":
case "pausing":
case "resuming":
return UM.Theme.getIcon("tab_status_busy");
case "ready":
case "":
return UM.Theme.getIcon("tab_status_connected")
case "paused":
return UM.Theme.getIcon("tab_status_paused")
case "error":
return UM.Theme.getIcon("tab_status_stopped")
case "offline":
return UM.Theme.getIcon("tab_status_offline")
default:
return ""
}
}
checkable: true
checked: base.monitoringPrint
exclusiveGroup: sidebarHeaderBarGroup
style: UM.Theme.styles.topbar_header_tab
}
ExclusiveGroup { id: sidebarHeaderBarGroup }
}
ToolButton
{
id: machineSelection
text: Cura.MachineManager.activeMachineName
width: UM.Theme.getSize("sidebar").width;
height: UM.Theme.getSize("sidebar_header").height
tooltip: Cura.MachineManager.activeMachineName
anchors.verticalCenter: parent.verticalCenter
anchors.right: parent.right
style: ButtonStyle
{
background: Rectangle
{
color:
{
if(control.pressed)
{
return UM.Theme.getColor("sidebar_header_active");
} else if(control.hovered)
{
return UM.Theme.getColor("sidebar_header_hover");
} else
{
return UM.Theme.getColor("sidebar_header_bar");
}
}
Behavior on color { ColorAnimation { duration: 50; } }
Rectangle
{
id: underline;
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
height: UM.Theme.getSize("sidebar_header_highlight").height
color: UM.Theme.getColor("sidebar_header_highlight_hover")
visible: control.hovered || control.pressed
}
UM.RecolorImage
{
id: downArrow
anchors.verticalCenter: parent.verticalCenter
anchors.right: parent.right
anchors.rightMargin: UM.Theme.getSize("default_margin").width
width: UM.Theme.getSize("standard_arrow").width
height: UM.Theme.getSize("standard_arrow").height
sourceSize.width: width
sourceSize.height: width
color: UM.Theme.getColor("text_reversed")
source: UM.Theme.getIcon("arrow_bottom")
}
Label
{
id: sidebarComboBoxLabel
color: UM.Theme.getColor("text_reversed")
text: control.text;
elide: Text.ElideRight;
anchors.left: parent.left;
anchors.leftMargin: UM.Theme.getSize("default_margin").width
anchors.right: downArrow.left;
anchors.rightMargin: control.rightMargin;
anchors.verticalCenter: parent.verticalCenter;
font: UM.Theme.getFont("large")
}
}
label: Label {}
}
menu: PrinterMenu { }
}
}

View file

@ -8,7 +8,7 @@ type = quality
material = generic_pla material = generic_pla
weight = 0 weight = 0
quality_type = normal quality_type = normal
setting_version = 1 setting_version = 2
[values] [values]
layer_height = 0.2 layer_height = 0.2

View file

@ -8,7 +8,7 @@ type = quality
material = generic_pla material = generic_pla
weight = 1 weight = 1
quality_type = high quality_type = high
setting_version = 1 setting_version = 2
[values] [values]
layer_height = 0.1 layer_height = 0.1

View file

@ -8,7 +8,7 @@ type = quality
material = generic_pla material = generic_pla
weight = 0 weight = 0
quality_type = normal quality_type = normal
setting_version = 1 setting_version = 2
[values] [values]
layer_height = 0.2 layer_height = 0.2

View file

@ -8,7 +8,7 @@ type = quality
material = generic_pla material = generic_pla
weight = 0 weight = 0
quality_type = normal quality_type = normal
setting_version = 1 setting_version = 2
[values] [values]
layer_height = 0.2 layer_height = 0.2

View file

@ -8,7 +8,7 @@ type = quality
material = generic_pla material = generic_pla
weight = 1 weight = 1
quality_type = high quality_type = high
setting_version = 1 setting_version = 2
[values] [values]
layer_height = 0.1 layer_height = 0.1

View file

@ -8,7 +8,7 @@ type = quality
material = generic_pla material = generic_pla
weight = 0 weight = 0
quality_type = normal quality_type = normal
setting_version = 1 setting_version = 2
[values] [values]
layer_height = 0.2 layer_height = 0.2

View file

@ -8,7 +8,7 @@ type = quality
material = generic_pla material = generic_pla
weight = 0 weight = 0
quality_type = normal quality_type = normal
setting_version = 1 setting_version = 2
[values] [values]
layer_height = 0.2 layer_height = 0.2

View file

@ -7,7 +7,7 @@ type = quality
material = generic_pla material = generic_pla
weight = 1 weight = 1
quality_type = high quality_type = high
setting_version = 1 setting_version = 2
[values] [values]
layer_height = 0.1 layer_height = 0.1

View file

@ -8,7 +8,7 @@ type = quality
material = generic_pla material = generic_pla
weight = 0 weight = 0
quality_type = normal quality_type = normal
setting_version = 1 setting_version = 2
[values] [values]
layer_height = 0.2 layer_height = 0.2

View file

@ -8,7 +8,7 @@ type = quality
quality_type = high quality_type = high
material = generic_abs_175_cartesio_0.25_mm material = generic_abs_175_cartesio_0.25_mm
weight = 1 weight = 1
setting_version = 1 setting_version = 2
[values] [values]
infill_line_width = 0.3 infill_line_width = 0.3
@ -35,7 +35,7 @@ speed_print = 50
speed_infill = =speed_print speed_infill = =speed_print
speed_layer_0 = =round(speed_print / 5 * 4) speed_layer_0 = =round(speed_print / 5 * 4)
speed_wall = =round(speed_print / 2) speed_wall = =round(speed_print / 2)
speed_wall_0 = =10 if speed_wall < 11 else (speed_print / 5 *3) speed_wall_0 = =10 if speed_wall < 11 else 15
speed_topbottom = =round(speed_print / 5 * 4) speed_topbottom = =round(speed_print / 5 * 4)
speed_travel = =round(speed_print if magic_spiralize else 150) speed_travel = =round(speed_print if magic_spiralize else 150)
speed_travel_layer_0 = =speed_travel speed_travel_layer_0 = =speed_travel

View file

@ -8,7 +8,7 @@ type = quality
quality_type = normal quality_type = normal
material = generic_abs_175_cartesio_0.25_mm material = generic_abs_175_cartesio_0.25_mm
weight = 2 weight = 2
setting_version = 1 setting_version = 2
[values] [values]
infill_line_width = 0.3 infill_line_width = 0.3

View file

@ -8,7 +8,7 @@ type = quality
quality_type = high quality_type = high
material = generic_abs_175_cartesio_0.4_mm material = generic_abs_175_cartesio_0.4_mm
weight = 1 weight = 1
setting_version = 1 setting_version = 2
[values] [values]
infill_line_width = 0.5 infill_line_width = 0.5
@ -35,7 +35,7 @@ speed_print = 50
speed_infill = =speed_print speed_infill = =speed_print
speed_layer_0 = =round(speed_print / 5 * 4) speed_layer_0 = =round(speed_print / 5 * 4)
speed_wall = =round(speed_print / 2) speed_wall = =round(speed_print / 2)
speed_wall_0 = =10 if speed_wall < 11 else (speed_print / 5 *3) speed_wall_0 = =10 if speed_wall < 11 else 15
speed_topbottom = =round(speed_print / 5 * 4) speed_topbottom = =round(speed_print / 5 * 4)
speed_travel = =round(speed_print if magic_spiralize else 150) speed_travel = =round(speed_print if magic_spiralize else 150)
speed_travel_layer_0 = =speed_travel speed_travel_layer_0 = =speed_travel

View file

@ -8,7 +8,7 @@ type = quality
quality_type = normal quality_type = normal
material = generic_abs_175_cartesio_0.4_mm material = generic_abs_175_cartesio_0.4_mm
weight = 2 weight = 2
setting_version = 1 setting_version = 2
[values] [values]
infill_line_width = 0.5 infill_line_width = 0.5

View file

@ -8,7 +8,7 @@ type = quality
quality_type = coarse quality_type = coarse
material = generic_abs_175_cartesio_0.8_mm material = generic_abs_175_cartesio_0.8_mm
weight = 3 weight = 3
setting_version = 1 setting_version = 2
[values] [values]
infill_line_width = 0.9 infill_line_width = 0.9

View file

@ -8,7 +8,7 @@ type = quality
quality_type = extra coarse quality_type = extra coarse
material = generic_abs_175_cartesio_0.8_mm material = generic_abs_175_cartesio_0.8_mm
weight = 4 weight = 4
setting_version = 1 setting_version = 2
[values] [values]
infill_line_width = 0.9 infill_line_width = 0.9

View file

@ -8,7 +8,7 @@ type = quality
quality_type = high quality_type = high
material = generic_abs_175_cartesio_0.8_mm material = generic_abs_175_cartesio_0.8_mm
weight = 1 weight = 1
setting_version = 1 setting_version = 2
[values] [values]
infill_line_width = 0.9 infill_line_width = 0.9
@ -35,7 +35,7 @@ speed_print = 50
speed_infill = =speed_print speed_infill = =speed_print
speed_layer_0 = =round(speed_print / 5 * 4) speed_layer_0 = =round(speed_print / 5 * 4)
speed_wall = =round(speed_print / 2) speed_wall = =round(speed_print / 2)
speed_wall_0 = =10 if speed_wall < 11 else (speed_print / 5 *3) speed_wall_0 = =10 if speed_wall < 11 else 15
speed_topbottom = =round(speed_print / 5 * 4) speed_topbottom = =round(speed_print / 5 * 4)
speed_travel = =round(speed_print if magic_spiralize else 150) speed_travel = =round(speed_print if magic_spiralize else 150)
speed_travel_layer_0 = =speed_travel speed_travel_layer_0 = =speed_travel

View file

@ -8,7 +8,7 @@ type = quality
quality_type = normal quality_type = normal
material = generic_abs_175_cartesio_0.8_mm material = generic_abs_175_cartesio_0.8_mm
weight = 2 weight = 2
setting_version = 1 setting_version = 2
[values] [values]
infill_line_width = 0.9 infill_line_width = 0.9

View file

@ -8,7 +8,7 @@ type = quality
quality_type = high quality_type = high
material = dsm_arnitel2045_175_cartesio_0.4_mm material = dsm_arnitel2045_175_cartesio_0.4_mm
weight = 1 weight = 1
setting_version = 1 setting_version = 2
[values] [values]
infill_line_width = 0.5 infill_line_width = 0.5
@ -35,7 +35,7 @@ speed_print = 25
speed_infill = =speed_print speed_infill = =speed_print
speed_layer_0 = =round(speed_print / 5 * 4) speed_layer_0 = =round(speed_print / 5 * 4)
speed_wall = =round(speed_print / 2) speed_wall = =round(speed_print / 2)
speed_wall_0 = =10 if speed_wall < 11 else (speed_print / 5 *3) speed_wall_0 = =10 if speed_wall < 11 else 15
speed_topbottom = =round(speed_print / 5 * 4) speed_topbottom = =round(speed_print / 5 * 4)
speed_travel = =round(speed_print if magic_spiralize else 150) speed_travel = =round(speed_print if magic_spiralize else 150)
speed_travel_layer_0 = =speed_travel speed_travel_layer_0 = =speed_travel

View file

@ -8,7 +8,7 @@ type = quality
quality_type = normal quality_type = normal
material = dsm_arnitel2045_175_cartesio_0.4_mm material = dsm_arnitel2045_175_cartesio_0.4_mm
weight = 2 weight = 2
setting_version = 1 setting_version = 2
[values] [values]
infill_line_width = 0.5 infill_line_width = 0.5

View file

@ -8,7 +8,7 @@ type = quality
quality_type = coarse quality_type = coarse
global_quality = True global_quality = True
weight = 0 weight = 0
setting_version = 1 setting_version = 2
[values] [values]
layer_height = 0.4 layer_height = 0.4

View file

@ -8,7 +8,7 @@ type = quality
quality_type = extra coarse quality_type = extra coarse
global_quality = True global_quality = True
weight = 0 weight = 0
setting_version = 1 setting_version = 2
[values] [values]
layer_height = 0.6 layer_height = 0.6

View file

@ -8,7 +8,7 @@ type = quality
quality_type = high quality_type = high
global_quality = True global_quality = True
weight = 0 weight = 0
setting_version = 1 setting_version = 2
[values] [values]
layer_height = 0.1 layer_height = 0.1

View file

@ -8,7 +8,7 @@ type = quality
quality_type = normal quality_type = normal
global_quality = True global_quality = True
weight = 0 weight = 0
setting_version = 1 setting_version = 2
[values] [values]
layer_height = 0.2 layer_height = 0.2

View file

@ -8,7 +8,7 @@ type = quality
quality_type = high quality_type = high
material = generic_hips_175_cartesio_0.25_mm material = generic_hips_175_cartesio_0.25_mm
weight = 1 weight = 1
setting_version = 1 setting_version = 2
[values] [values]
infill_line_width = 0.3 infill_line_width = 0.3
@ -35,7 +35,7 @@ speed_print = 50
speed_infill = =speed_print speed_infill = =speed_print
speed_layer_0 = =round(speed_print / 5 * 4) speed_layer_0 = =round(speed_print / 5 * 4)
speed_wall = =round(speed_print / 2) speed_wall = =round(speed_print / 2)
speed_wall_0 = =10 if speed_wall < 11 else (speed_print / 5 *3) speed_wall_0 = =10 if speed_wall < 11 else 15
speed_topbottom = =round(speed_print / 5 * 4) speed_topbottom = =round(speed_print / 5 * 4)
speed_travel = =round(speed_print if magic_spiralize else 150) speed_travel = =round(speed_print if magic_spiralize else 150)
speed_travel_layer_0 = =speed_travel speed_travel_layer_0 = =speed_travel

View file

@ -8,7 +8,7 @@ type = quality
quality_type = normal quality_type = normal
material = generic_hips_175_cartesio_0.25_mm material = generic_hips_175_cartesio_0.25_mm
weight = 2 weight = 2
setting_version = 1 setting_version = 2
[values] [values]
infill_line_width = 0.3 infill_line_width = 0.3

View file

@ -8,7 +8,7 @@ type = quality
quality_type = high quality_type = high
material = generic_hips_175_cartesio_0.4_mm material = generic_hips_175_cartesio_0.4_mm
weight = 1 weight = 1
setting_version = 1 setting_version = 2
[values] [values]
infill_line_width = 0.5 infill_line_width = 0.5
@ -35,7 +35,7 @@ speed_print = 50
speed_infill = =speed_print speed_infill = =speed_print
speed_layer_0 = =round(speed_print / 5 * 4) speed_layer_0 = =round(speed_print / 5 * 4)
speed_wall = =round(speed_print / 2) speed_wall = =round(speed_print / 2)
speed_wall_0 = =10 if speed_wall < 11 else (speed_print / 5 *3) speed_wall_0 = =10 if speed_wall < 11 else 15
speed_topbottom = =round(speed_print / 5 * 4) speed_topbottom = =round(speed_print / 5 * 4)
speed_travel = =round(speed_print if magic_spiralize else 150) speed_travel = =round(speed_print if magic_spiralize else 150)
speed_travel_layer_0 = =speed_travel speed_travel_layer_0 = =speed_travel

View file

@ -8,7 +8,7 @@ type = quality
quality_type = normal quality_type = normal
material = generic_hips_175_cartesio_0.4_mm material = generic_hips_175_cartesio_0.4_mm
weight = 2 weight = 2
setting_version = 1 setting_version = 2
[values] [values]
infill_line_width = 0.5 infill_line_width = 0.5

View file

@ -8,7 +8,7 @@ type = quality
quality_type = coarse quality_type = coarse
material = generic_hips_175_cartesio_0.8_mm material = generic_hips_175_cartesio_0.8_mm
weight = 3 weight = 3
setting_version = 1 setting_version = 2
[values] [values]
infill_line_width = 0.9 infill_line_width = 0.9

View file

@ -8,7 +8,7 @@ type = quality
quality_type = extra coarse quality_type = extra coarse
material = generic_hips_175_cartesio_0.8_mm material = generic_hips_175_cartesio_0.8_mm
weight = 4 weight = 4
setting_version = 1 setting_version = 2
[values] [values]
infill_line_width = 0.9 infill_line_width = 0.9

View file

@ -8,7 +8,7 @@ type = quality
quality_type = high quality_type = high
material = generic_hips_175_cartesio_0.8_mm material = generic_hips_175_cartesio_0.8_mm
weight = 1 weight = 1
setting_version = 1 setting_version = 2
[values] [values]
infill_line_width = 0.9 infill_line_width = 0.9
@ -35,7 +35,7 @@ speed_print = 50
speed_infill = =speed_print speed_infill = =speed_print
speed_layer_0 = =round(speed_print / 5 * 4) speed_layer_0 = =round(speed_print / 5 * 4)
speed_wall = =round(speed_print / 2) speed_wall = =round(speed_print / 2)
speed_wall_0 = =10 if speed_wall < 11 else (speed_print / 5 *3) speed_wall_0 = =10 if speed_wall < 11 else 15
speed_topbottom = =round(speed_print / 5 * 4) speed_topbottom = =round(speed_print / 5 * 4)
speed_travel = =round(speed_print if magic_spiralize else 150) speed_travel = =round(speed_print if magic_spiralize else 150)
speed_travel_layer_0 = =speed_travel speed_travel_layer_0 = =speed_travel

View file

@ -8,7 +8,7 @@ type = quality
quality_type = normal quality_type = normal
material = generic_hips_175_cartesio_0.8_mm material = generic_hips_175_cartesio_0.8_mm
weight = 2 weight = 2
setting_version = 1 setting_version = 2
[values] [values]
infill_line_width = 0.9 infill_line_width = 0.9

View file

@ -8,7 +8,7 @@ type = quality
quality_type = high quality_type = high
material = generic_nylon_175_cartesio_0.25_mm material = generic_nylon_175_cartesio_0.25_mm
weight = 1 weight = 1
setting_version = 1 setting_version = 2
[values] [values]
infill_line_width = 0.3 infill_line_width = 0.3
@ -35,7 +35,7 @@ speed_print = 50
speed_infill = =speed_print speed_infill = =speed_print
speed_layer_0 = =round(speed_print / 5 * 4) speed_layer_0 = =round(speed_print / 5 * 4)
speed_wall = =round(speed_print / 2) speed_wall = =round(speed_print / 2)
speed_wall_0 = =10 if speed_wall < 11 else (speed_print / 5 *3) speed_wall_0 = =10 if speed_wall < 11 else 15
speed_topbottom = =round(speed_print / 5 * 4) speed_topbottom = =round(speed_print / 5 * 4)
speed_travel = =round(speed_print if magic_spiralize else 150) speed_travel = =round(speed_print if magic_spiralize else 150)
speed_travel_layer_0 = =speed_travel speed_travel_layer_0 = =speed_travel

View file

@ -8,7 +8,7 @@ type = quality
quality_type = normal quality_type = normal
material = generic_nylon_175_cartesio_0.25_mm material = generic_nylon_175_cartesio_0.25_mm
weight = 2 weight = 2
setting_version = 1 setting_version = 2
[values] [values]
infill_line_width = 0.3 infill_line_width = 0.3

View file

@ -8,7 +8,7 @@ type = quality
quality_type = high quality_type = high
material = generic_nylon_175_cartesio_0.4_mm material = generic_nylon_175_cartesio_0.4_mm
weight = 1 weight = 1
setting_version = 1 setting_version = 2
[values] [values]
infill_line_width = 0.5 infill_line_width = 0.5
@ -35,7 +35,7 @@ speed_print = 50
speed_infill = =speed_print speed_infill = =speed_print
speed_layer_0 = =round(speed_print / 5 * 4) speed_layer_0 = =round(speed_print / 5 * 4)
speed_wall = =round(speed_print / 2) speed_wall = =round(speed_print / 2)
speed_wall_0 = =10 if speed_wall < 11 else (speed_print / 5 *3) speed_wall_0 = =10 if speed_wall < 11 else 15
speed_topbottom = =round(speed_print / 5 * 4) speed_topbottom = =round(speed_print / 5 * 4)
speed_travel = =round(speed_print if magic_spiralize else 150) speed_travel = =round(speed_print if magic_spiralize else 150)
speed_travel_layer_0 = =speed_travel speed_travel_layer_0 = =speed_travel

View file

@ -8,7 +8,7 @@ type = quality
quality_type = normal quality_type = normal
material = generic_nylon_175_cartesio_0.4_mm material = generic_nylon_175_cartesio_0.4_mm
weight = 2 weight = 2
setting_version = 1 setting_version = 2
[values] [values]
infill_line_width = 0.5 infill_line_width = 0.5

View file

@ -8,7 +8,7 @@ type = quality
quality_type = coarse quality_type = coarse
material = generic_nylon_175_cartesio_0.8_mm material = generic_nylon_175_cartesio_0.8_mm
weight = 3 weight = 3
setting_version = 1 setting_version = 2
[values] [values]
infill_line_width = 0.9 infill_line_width = 0.9

View file

@ -8,7 +8,7 @@ type = quality
quality_type = extra coarse quality_type = extra coarse
material = generic_nylon_175_cartesio_0.8_mm material = generic_nylon_175_cartesio_0.8_mm
weight = 4 weight = 4
setting_version = 1 setting_version = 2
[values] [values]
infill_line_width = 0.9 infill_line_width = 0.9

View file

@ -8,7 +8,7 @@ type = quality
quality_type = high quality_type = high
material = generic_nylon_175_cartesio_0.8_mm material = generic_nylon_175_cartesio_0.8_mm
weight = 1 weight = 1
setting_version = 1 setting_version = 2
[values] [values]
infill_line_width = 0.9 infill_line_width = 0.9
@ -35,7 +35,7 @@ speed_print = 50
speed_infill = =speed_print speed_infill = =speed_print
speed_layer_0 = =round(speed_print / 5 * 4) speed_layer_0 = =round(speed_print / 5 * 4)
speed_wall = =round(speed_print / 2) speed_wall = =round(speed_print / 2)
speed_wall_0 = =10 if speed_wall < 11 else (speed_print / 5 *3) speed_wall_0 = =10 if speed_wall < 11 else 15
speed_topbottom = =round(speed_print / 5 * 4) speed_topbottom = =round(speed_print / 5 * 4)
speed_travel = =round(speed_print if magic_spiralize else 150) speed_travel = =round(speed_print if magic_spiralize else 150)
speed_travel_layer_0 = =speed_travel speed_travel_layer_0 = =speed_travel

Some files were not shown because too many files have changed in this diff Show more