@ -2,6 +2,8 @@
|
|||||||
project(cura)
|
project(cura)
|
||||||
cmake_minimum_required(VERSION 2.8.12)
|
cmake_minimum_required(VERSION 2.8.12)
|
||||||
|
|
||||||
|
include(GNUInstallDirs)
|
||||||
|
|
||||||
set(URANIUM_SCRIPTS_DIR "${CMAKE_SOURCE_DIR}/../uranium/scripts" CACHE DIRECTORY "The location of the scripts directory of the Uranium repository")
|
set(URANIUM_SCRIPTS_DIR "${CMAKE_SOURCE_DIR}/../uranium/scripts" CACHE DIRECTORY "The location of the scripts directory of the Uranium repository")
|
||||||
|
|
||||||
if(NOT ${URANIUM_SCRIPTS_DIR} STREQUAL "")
|
if(NOT ${URANIUM_SCRIPTS_DIR} STREQUAL "")
|
||||||
@ -10,13 +12,11 @@ if(NOT ${URANIUM_SCRIPTS_DIR} STREQUAL "")
|
|||||||
|
|
||||||
# Build Translations
|
# Build Translations
|
||||||
find_package(Gettext)
|
find_package(Gettext)
|
||||||
include(${URANIUM_SCRIPTS_DIR}/ECMPoQmTools.cmake)
|
|
||||||
|
|
||||||
if(GETTEXT_FOUND)
|
if(GETTEXT_FOUND)
|
||||||
# translations target will convert .po files into .mo and .qm as needed.
|
# translations target will convert .po files into .mo and .qm as needed.
|
||||||
# The files are checked for a _qt suffix and if it is found, converted to
|
# The files are checked for a _qt suffix and if it is found, converted to
|
||||||
# qm, otherwise they are converted to .po.
|
# qm, otherwise they are converted to .po.
|
||||||
add_custom_target(translations)
|
add_custom_target(translations ALL)
|
||||||
# copy-translations can be used to copy the built translation files from the
|
# copy-translations can be used to copy the built translation files from the
|
||||||
# build directory to the source resources directory. This is mostly a convenience
|
# build directory to the source resources directory. This is mostly a convenience
|
||||||
# during development, normally you want to simply use the install target to install
|
# during development, normally you want to simply use the install target to install
|
||||||
@ -33,29 +33,27 @@ if(NOT ${URANIUM_SCRIPTS_DIR} STREQUAL "")
|
|||||||
it
|
it
|
||||||
es
|
es
|
||||||
fi
|
fi
|
||||||
|
pl
|
||||||
|
cs
|
||||||
|
bg
|
||||||
)
|
)
|
||||||
foreach(lang ${languages})
|
foreach(lang ${languages})
|
||||||
file(GLOB po_files resources/i18n/${lang}/*.po)
|
file(GLOB po_files resources/i18n/${lang}/*.po)
|
||||||
foreach(file ${po_files})
|
foreach(file ${po_files})
|
||||||
string(REGEX MATCH "qt\\.po$" match "${file}")
|
|
||||||
if(match)
|
|
||||||
ecm_process_po_files_as_qm(${lang} PO_FILES ${file})
|
|
||||||
else()
|
|
||||||
string(REGEX REPLACE ".*/(.*).po" "${lang}/\\1.mo" mofile ${file})
|
string(REGEX REPLACE ".*/(.*).po" "${lang}/\\1.mo" mofile ${file})
|
||||||
add_custom_command(TARGET translations POST_BUILD COMMAND mkdir ARGS -p ${lang} COMMAND ${GETTEXT_MSGFMT_EXECUTABLE} ARGS ${file} -o ${mofile})
|
add_custom_command(TARGET translations POST_BUILD COMMAND mkdir ARGS -p ${lang} COMMAND ${GETTEXT_MSGFMT_EXECUTABLE} ARGS ${file} -o ${mofile})
|
||||||
endif()
|
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
file(GLOB qm_files ${CMAKE_BINARY_DIR}/${lang}/*.qm)
|
|
||||||
file(GLOB mo_files ${CMAKE_BINARY_DIR}/${lang}/*.mo)
|
file(GLOB mo_files ${CMAKE_BINARY_DIR}/${lang}/*.mo)
|
||||||
foreach(file ${qm_files} ${mo_files})
|
foreach(file ${mo_files})
|
||||||
add_custom_command(TARGET copy-translations POST_BUILD COMMAND mkdir ARGS -p ${CMAKE_SOURCE_DIR}/resources/i18n/${lang}/LC_MESSAGES/ COMMAND cp ARGS ${file} ${CMAKE_SOURCE_DIR}/resources/i18n/${lang}/LC_MESSAGES/ COMMENT "Copying ${file}...")
|
add_custom_command(TARGET copy-translations POST_BUILD COMMAND mkdir ARGS -p ${CMAKE_SOURCE_DIR}/resources/i18n/${lang}/LC_MESSAGES/ COMMAND cp ARGS ${file} ${CMAKE_SOURCE_DIR}/resources/i18n/${lang}/LC_MESSAGES/ COMMENT "Copying ${file}...")
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
|
install(FILES ${mo_files} DESTINATION ${CMAKE_INSTALL_DATADIR}/uranium/resources/i18n/${lang}/LC_MESSAGES/)
|
||||||
endforeach()
|
endforeach()
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
include(GNUInstallDirs)
|
|
||||||
find_package(PythonInterp 3.4.0 REQUIRED)
|
find_package(PythonInterp 3.4.0 REQUIRED)
|
||||||
|
|
||||||
install(DIRECTORY resources DESTINATION ${CMAKE_INSTALL_DATADIR}/cura)
|
install(DIRECTORY resources DESTINATION ${CMAKE_INSTALL_DATADIR}/cura)
|
||||||
|
@ -39,7 +39,8 @@ Please checkout [cura-build](https://github.com/Ultimaker/cura-build)
|
|||||||
|
|
||||||
Third party plugins
|
Third party plugins
|
||||||
-------------
|
-------------
|
||||||
[Print time calculator](https://github.com/nallath/PrintCostCalculator)
|
* [Print time calculator](https://github.com/nallath/PrintCostCalculator)
|
||||||
|
* [Post processing plugin](https://github.com/nallath/PostProcessingPlugin)
|
||||||
|
|
||||||
Making profiles for other printers
|
Making profiles for other printers
|
||||||
----------------------------------
|
----------------------------------
|
||||||
|
@ -5,7 +5,7 @@ GenericName=3D Printing Software
|
|||||||
Comment=
|
Comment=
|
||||||
Exec=/usr/bin/cura_app.py
|
Exec=/usr/bin/cura_app.py
|
||||||
TryExec=/usr/bin/cura_app.py
|
TryExec=/usr/bin/cura_app.py
|
||||||
Icon=/usr/share/cura/resources/images/cura_icon.png
|
Icon=/usr/share/cura/resources/images/cura-icon.png
|
||||||
Terminal=false
|
Terminal=false
|
||||||
Type=Application
|
Type=Application
|
||||||
Categories=Graphics;
|
Categories=Graphics;
|
||||||
|
@ -10,6 +10,7 @@ from UM.Mesh.MeshBuilder import MeshBuilder
|
|||||||
from UM.Math.Vector import Vector
|
from UM.Math.Vector import Vector
|
||||||
from UM.Math.Color import Color
|
from UM.Math.Color import Color
|
||||||
from UM.Math.AxisAlignedBox import AxisAlignedBox
|
from UM.Math.AxisAlignedBox import AxisAlignedBox
|
||||||
|
from UM.Math.Polygon import Polygon
|
||||||
|
|
||||||
import numpy
|
import numpy
|
||||||
|
|
||||||
@ -33,15 +34,18 @@ class BuildVolume(SceneNode):
|
|||||||
|
|
||||||
self.setCalculateBoundingBox(False)
|
self.setCalculateBoundingBox(False)
|
||||||
|
|
||||||
|
self._active_instance = None
|
||||||
|
Application.getInstance().getMachineManager().activeMachineInstanceChanged.connect(self._onActiveInstanceChanged)
|
||||||
|
self._onActiveInstanceChanged()
|
||||||
|
|
||||||
def setWidth(self, width):
|
def setWidth(self, width):
|
||||||
self._width = width
|
if width: self._width = width
|
||||||
|
|
||||||
def setHeight(self, height):
|
def setHeight(self, height):
|
||||||
self._height = height
|
if height: self._height = height
|
||||||
|
|
||||||
def setDepth(self, depth):
|
def setDepth(self, depth):
|
||||||
self._depth = depth
|
if depth: self._depth = depth
|
||||||
|
|
||||||
def getDisallowedAreas(self):
|
def getDisallowedAreas(self):
|
||||||
return self._disallowed_areas
|
return self._disallowed_areas
|
||||||
@ -55,12 +59,12 @@ class BuildVolume(SceneNode):
|
|||||||
|
|
||||||
if not self._material:
|
if not self._material:
|
||||||
self._material = renderer.createMaterial(
|
self._material = renderer.createMaterial(
|
||||||
Resources.getPath(Resources.ShadersLocation, "basic.vert"),
|
Resources.getPath(Resources.Shaders, "basic.vert"),
|
||||||
Resources.getPath(Resources.ShadersLocation, "vertexcolor.frag")
|
Resources.getPath(Resources.Shaders, "vertexcolor.frag")
|
||||||
)
|
)
|
||||||
self._grid_material = renderer.createMaterial(
|
self._grid_material = renderer.createMaterial(
|
||||||
Resources.getPath(Resources.ShadersLocation, "basic.vert"),
|
Resources.getPath(Resources.Shaders, "basic.vert"),
|
||||||
Resources.getPath(Resources.ShadersLocation, "grid.frag")
|
Resources.getPath(Resources.Shaders, "grid.frag")
|
||||||
)
|
)
|
||||||
self._grid_material.setUniformValue("u_gridColor0", Color(245, 245, 245, 255))
|
self._grid_material.setUniformValue("u_gridColor0", Color(245, 245, 245, 255))
|
||||||
self._grid_material.setUniformValue("u_gridColor1", Color(205, 202, 201, 255))
|
self._grid_material.setUniformValue("u_gridColor1", Color(205, 202, 201, 255))
|
||||||
@ -135,17 +139,18 @@ class BuildVolume(SceneNode):
|
|||||||
|
|
||||||
self._aabb = AxisAlignedBox(minimum = Vector(minW, minH - 1.0, minD), maximum = Vector(maxW, maxH, maxD))
|
self._aabb = AxisAlignedBox(minimum = Vector(minW, minH - 1.0, minD), maximum = Vector(maxW, maxH, maxD))
|
||||||
|
|
||||||
settings = Application.getInstance().getActiveMachine()
|
|
||||||
|
|
||||||
skirt_size = 0.0
|
skirt_size = 0.0
|
||||||
if settings.getSettingValueByKey("adhesion_type") == "None":
|
|
||||||
skirt_size = settings.getSettingValueByKey("skirt_line_count") * settings.getSettingValueByKey("skirt_line_width") + settings.getSettingValueByKey("skirt_gap")
|
|
||||||
elif settings.getSettingValueByKey("adhesion_type") == "Brim":
|
|
||||||
skirt_size = settings.getSettingValueByKey("brim_line_count") * settings.getSettingValueByKey("skirt_line_width")
|
|
||||||
else:
|
|
||||||
skirt_size = settings.getSettingValueByKey("skirt_line_width")
|
|
||||||
|
|
||||||
skirt_size += settings.getSettingValueByKey("skirt_line_width")
|
#profile = Application.getInstance().getMachineManager().getActiveProfile()
|
||||||
|
#if profile:
|
||||||
|
#if profile.getSettingValue("adhesion_type") == "skirt":
|
||||||
|
#skirt_size = profile.getSettingValue("skirt_line_count") * profile.getSettingValue("skirt_line_width") + profile.getSettingValue("skirt_gap")
|
||||||
|
#elif profile.getSettingValue("adhesion_type") == "brim":
|
||||||
|
#skirt_size = profile.getSettingValue("brim_line_count") * profile.getSettingValue("skirt_line_width")
|
||||||
|
#else:
|
||||||
|
#skirt_size = profile.getSettingValue("skirt_line_width")
|
||||||
|
|
||||||
|
#skirt_size += profile.getSettingValue("skirt_line_width")
|
||||||
|
|
||||||
scale_to_max_bounds = AxisAlignedBox(
|
scale_to_max_bounds = AxisAlignedBox(
|
||||||
minimum = Vector(minW + skirt_size, minH, minD + skirt_size + disallowed_area_size),
|
minimum = Vector(minW + skirt_size, minH, minD + skirt_size + disallowed_area_size),
|
||||||
@ -153,3 +158,21 @@ class BuildVolume(SceneNode):
|
|||||||
)
|
)
|
||||||
|
|
||||||
Application.getInstance().getController().getScene()._maximum_bounds = scale_to_max_bounds
|
Application.getInstance().getController().getScene()._maximum_bounds = scale_to_max_bounds
|
||||||
|
|
||||||
|
def _onActiveInstanceChanged(self):
|
||||||
|
self._active_instance = Application.getInstance().getMachineManager().getActiveMachineInstance()
|
||||||
|
|
||||||
|
if self._active_instance:
|
||||||
|
self._width = self._active_instance.getMachineSettingValue("machine_width")
|
||||||
|
self._height = self._active_instance.getMachineSettingValue("machine_height")
|
||||||
|
self._depth = self._active_instance.getMachineSettingValue("machine_depth")
|
||||||
|
|
||||||
|
disallowed_areas = self._active_instance.getMachineSettingValue("machine_disallowed_areas")
|
||||||
|
areas = []
|
||||||
|
if disallowed_areas:
|
||||||
|
for area in disallowed_areas:
|
||||||
|
areas.append(Polygon(numpy.array(area, numpy.float32)))
|
||||||
|
|
||||||
|
self._disallowed_areas = areas
|
||||||
|
|
||||||
|
self.rebuild()
|
||||||
|
@ -14,18 +14,10 @@ class ConvexHullDecorator(SceneNodeDecorator):
|
|||||||
|
|
||||||
self._convex_hull_node = None
|
self._convex_hull_node = None
|
||||||
self._convex_hull_job = None
|
self._convex_hull_job = None
|
||||||
settings = Application.getInstance().getActiveMachine()
|
|
||||||
print_sequence_setting = settings.getSettingByKey("print_sequence")
|
|
||||||
if print_sequence_setting:
|
|
||||||
print_sequence_setting.valueChanged.connect(self._onPrintSequenceSettingChanged)
|
|
||||||
|
|
||||||
def _onPrintSequenceSettingChanged(self, setting):
|
self._profile = None
|
||||||
if self._convex_hull_job:
|
Application.getInstance().getMachineManager().activeProfileChanged.connect(self._onActiveProfileChanged)
|
||||||
self._convex_hull_job.cancel()
|
self._onActiveProfileChanged()
|
||||||
self.setConvexHull(None)
|
|
||||||
if self._convex_hull_node:
|
|
||||||
self._convex_hull_node.setParent(None)
|
|
||||||
self._convex_hull_node = None
|
|
||||||
|
|
||||||
def getConvexHull(self):
|
def getConvexHull(self):
|
||||||
return self._convex_hull
|
return self._convex_hull
|
||||||
@ -61,4 +53,20 @@ class ConvexHullDecorator(SceneNodeDecorator):
|
|||||||
def setConvexHullNode(self, node):
|
def setConvexHullNode(self, node):
|
||||||
self._convex_hull_node = node
|
self._convex_hull_node = node
|
||||||
|
|
||||||
|
def _onActiveProfileChanged(self):
|
||||||
|
if self._profile:
|
||||||
|
self._profile.settingValueChanged.disconnect(self._onSettingValueChanged)
|
||||||
|
|
||||||
|
self._profile = Application.getInstance().getMachineManager().getActiveProfile()
|
||||||
|
|
||||||
|
if self._profile:
|
||||||
|
self._profile.settingValueChanged.connect(self._onSettingValueChanged)
|
||||||
|
|
||||||
|
def _onSettingValueChanged(self, setting):
|
||||||
|
if setting == "print_sequence":
|
||||||
|
if self._convex_hull_job:
|
||||||
|
self._convex_hull_job.cancel()
|
||||||
|
self.setConvexHull(None)
|
||||||
|
if self._convex_hull_node:
|
||||||
|
self._convex_hull_node.setParent(None)
|
||||||
|
self._convex_hull_node = None
|
||||||
|
@ -36,7 +36,8 @@ class ConvexHullJob(Job):
|
|||||||
return
|
return
|
||||||
mesh = self._node.getMeshData()
|
mesh = self._node.getMeshData()
|
||||||
vertex_data = mesh.getTransformed(self._node.getWorldTransformation()).getVertices()
|
vertex_data = mesh.getTransformed(self._node.getWorldTransformation()).getVertices()
|
||||||
|
# Don't use data below 0. TODO; We need a better check for this as this gives poor results for meshes with long edges.
|
||||||
|
vertex_data = vertex_data[vertex_data[:,1]>0]
|
||||||
hull = Polygon(numpy.rint(vertex_data[:, [0, 2]]).astype(int))
|
hull = Polygon(numpy.rint(vertex_data[:, [0, 2]]).astype(int))
|
||||||
|
|
||||||
# First, calculate the normal convex hull around the points
|
# First, calculate the normal convex hull around the points
|
||||||
@ -45,14 +46,17 @@ class ConvexHullJob(Job):
|
|||||||
# Then, do a Minkowski hull with a simple 1x1 quad to outset and round the normal convex hull.
|
# Then, do a Minkowski hull with a simple 1x1 quad to outset and round the normal convex hull.
|
||||||
# This is done because of rounding errors.
|
# This is done because of rounding errors.
|
||||||
hull = hull.getMinkowskiHull(Polygon(numpy.array([[-1, -1], [-1, 1], [1, 1], [1, -1]], numpy.float32)))
|
hull = hull.getMinkowskiHull(Polygon(numpy.array([[-1, -1], [-1, 1], [1, 1], [1, -1]], numpy.float32)))
|
||||||
settings = Application.getInstance().getActiveMachine()
|
|
||||||
|
|
||||||
if settings.getSettingValueByKey("print_sequence") == "One at a time" and not self._node.getParent().callDecoration("isGroup"):
|
profile = Application.getInstance().getMachineManager().getActiveProfile()
|
||||||
|
if profile:
|
||||||
|
if profile.getSettingValue("print_sequence") == "one_at_a_time" and not self._node.getParent().callDecoration("isGroup"):
|
||||||
# Printing one at a time and it's not an object in a group
|
# Printing one at a time and it's not an object in a group
|
||||||
self._node.callDecoration("setConvexHullBoundary", copy.deepcopy(hull))
|
self._node.callDecoration("setConvexHullBoundary", copy.deepcopy(hull))
|
||||||
head_hull = hull.getMinkowskiHull(Polygon(numpy.array(settings.getSettingValueByKey("machine_head_with_fans_polygon"),numpy.float32)))
|
head_hull = hull.getMinkowskiHull(Polygon(numpy.array(profile.getSettingValue("machine_head_with_fans_polygon"),numpy.float32)))
|
||||||
self._node.callDecoration("setConvexHullHead", head_hull)
|
self._node.callDecoration("setConvexHullHead", head_hull)
|
||||||
hull = hull.getMinkowskiHull(Polygon(numpy.array(settings.getSettingValueByKey("machine_head_polygon"),numpy.float32)))
|
hull = hull.getMinkowskiHull(Polygon(numpy.array(profile.getSettingValue("machine_head_polygon"),numpy.float32)))
|
||||||
|
else:
|
||||||
|
self._node.callDecoration("setConvexHullHead", None)
|
||||||
hull_node = ConvexHullNode.ConvexHullNode(self._node, hull, Application.getInstance().getController().getScene().getRoot())
|
hull_node = ConvexHullNode.ConvexHullNode(self._node, hull, Application.getInstance().getController().getScene().getRoot())
|
||||||
self._node.callDecoration("setConvexHullNode", hull_node)
|
self._node.callDecoration("setConvexHullNode", hull_node)
|
||||||
self._node.callDecoration("setConvexHull", hull)
|
self._node.callDecoration("setConvexHull", hull)
|
||||||
@ -66,4 +70,3 @@ class ConvexHullJob(Job):
|
|||||||
hull_node = self._node.getParent().callDecoration("getConvexHullNode")
|
hull_node = self._node.getParent().callDecoration("getConvexHullNode")
|
||||||
if hull_node:
|
if hull_node:
|
||||||
hull_node.setParent(None)
|
hull_node.setParent(None)
|
||||||
|
|
||||||
|
@ -22,22 +22,33 @@ class ConvexHullNode(SceneNode):
|
|||||||
self._inherit_orientation = False
|
self._inherit_orientation = False
|
||||||
self._inherit_scale = False
|
self._inherit_scale = False
|
||||||
|
|
||||||
|
self._color = Color(35, 35, 35, 0.5)
|
||||||
|
|
||||||
self._node = node
|
self._node = node
|
||||||
self._node.transformationChanged.connect(self._onNodePositionChanged)
|
self._node.transformationChanged.connect(self._onNodePositionChanged)
|
||||||
self._node.parentChanged.connect(self._onNodeParentChanged)
|
self._node.parentChanged.connect(self._onNodeParentChanged)
|
||||||
#self._onNodePositionChanged(self._node)
|
self._node.decoratorsChanged.connect(self._onNodeDecoratorsChanged)
|
||||||
|
self._onNodeDecoratorsChanged(self._node)
|
||||||
|
self.convexHullHeadMesh = None
|
||||||
self._hull = hull
|
self._hull = hull
|
||||||
|
|
||||||
hull_points = self._hull.getPoints()
|
hull_points = self._hull.getPoints()
|
||||||
center = (hull_points.min(0) + hull_points.max(0)) / 2.0
|
hull_mesh = self.createHullMesh(self._hull.getPoints())
|
||||||
|
if hull_mesh:
|
||||||
|
self.setMeshData(hull_mesh)
|
||||||
|
convex_hull_head = self._node.callDecoration("getConvexHullHead")
|
||||||
|
if convex_hull_head:
|
||||||
|
self.convexHullHeadMesh = self.createHullMesh(convex_hull_head.getPoints())
|
||||||
|
|
||||||
|
def createHullMesh(self, hull_points):
|
||||||
mesh = MeshData()
|
mesh = MeshData()
|
||||||
|
if len(hull_points) > 3:
|
||||||
|
center = (hull_points.min(0) + hull_points.max(0)) / 2.0
|
||||||
mesh.addVertex(center[0], 0.1, center[1])
|
mesh.addVertex(center[0], 0.1, center[1])
|
||||||
|
else:
|
||||||
|
return None
|
||||||
for point in hull_points:
|
for point in hull_points:
|
||||||
mesh.addVertex(point[0], 0.1, point[1])
|
mesh.addVertex(point[0], 0.1, point[1])
|
||||||
|
|
||||||
indices = []
|
indices = []
|
||||||
for i in range(len(hull_points) - 1):
|
for i in range(len(hull_points) - 1):
|
||||||
indices.append([0, i + 1, i + 2])
|
indices.append([0, i + 1, i + 2])
|
||||||
@ -45,35 +56,43 @@ class ConvexHullNode(SceneNode):
|
|||||||
indices.append([0, mesh.getVertexCount() - 1, 1])
|
indices.append([0, mesh.getVertexCount() - 1, 1])
|
||||||
|
|
||||||
mesh.addIndices(numpy.array(indices, numpy.int32))
|
mesh.addIndices(numpy.array(indices, numpy.int32))
|
||||||
|
return mesh
|
||||||
self.setMeshData(mesh)
|
|
||||||
|
|
||||||
def getWatchedNode(self):
|
def getWatchedNode(self):
|
||||||
return self._node
|
return self._node
|
||||||
|
|
||||||
def render(self, renderer):
|
def render(self, renderer):
|
||||||
if not self._material:
|
if not self._material:
|
||||||
self._material = renderer.createMaterial(Resources.getPath(Resources.ShadersLocation, "basic.vert"), Resources.getPath(Resources.ShadersLocation, "color.frag"))
|
self._material = renderer.createMaterial(Resources.getPath(Resources.Shaders, "basic.vert"), Resources.getPath(Resources.Shaders, "color.frag"))
|
||||||
|
|
||||||
self._material.setUniformValue("u_color", Color(35, 35, 35, 128))
|
|
||||||
if self.getParent():
|
if self.getParent():
|
||||||
|
self._material.setUniformValue("u_color", self._color)
|
||||||
renderer.queueNode(self, material = self._material, transparent = True)
|
renderer.queueNode(self, material = self._material, transparent = True)
|
||||||
|
if self.convexHullHeadMesh:
|
||||||
|
renderer.queueNode(self, material = self._material,transparent = True, mesh = self.convexHullHeadMesh)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def _onNodePositionChanged(self, node):
|
def _onNodePositionChanged(self, node):
|
||||||
#self.setPosition(node.getWorldPosition())
|
|
||||||
if node.callDecoration("getConvexHull"):
|
if node.callDecoration("getConvexHull"):
|
||||||
node.callDecoration("setConvexHull", None)
|
node.callDecoration("setConvexHull", None)
|
||||||
node.callDecoration("setConvexHullNode", None)
|
node.callDecoration("setConvexHullNode", None)
|
||||||
self.setParent(None)
|
self.setParent(None)
|
||||||
|
|
||||||
#self._node.transformationChanged.disconnect(self._onNodePositionChanged)
|
|
||||||
#self._node.parentChanged.disconnect(self._onNodeParentChanged)
|
|
||||||
|
|
||||||
def _onNodeParentChanged(self, node):
|
def _onNodeParentChanged(self, node):
|
||||||
if node.getParent():
|
if node.getParent():
|
||||||
self.setParent(self._original_parent)
|
self.setParent(self._original_parent)
|
||||||
else:
|
else:
|
||||||
self.setParent(None)
|
self.setParent(None)
|
||||||
|
|
||||||
|
def _onNodeDecoratorsChanged(self, node):
|
||||||
|
self._color = Color(35, 35, 35, 0.5)
|
||||||
|
|
||||||
|
if not node:
|
||||||
|
return
|
||||||
|
|
||||||
|
if node.hasDecoration("getProfile"):
|
||||||
|
self._color.setR(0.75)
|
||||||
|
|
||||||
|
if node.hasDecoration("getSetting"):
|
||||||
|
self._color.setG(0.75)
|
||||||
|
@ -3,18 +3,27 @@ import platform
|
|||||||
import traceback
|
import traceback
|
||||||
import webbrowser
|
import webbrowser
|
||||||
|
|
||||||
from PyQt5.QtCore import QT_VERSION_STR, PYQT_VERSION_STR
|
from PyQt5.QtCore import QT_VERSION_STR, PYQT_VERSION_STR, QCoreApplication
|
||||||
from PyQt5.QtWidgets import QDialog, QDialogButtonBox, QVBoxLayout, QLabel, QTextEdit
|
from PyQt5.QtWidgets import QDialog, QDialogButtonBox, QVBoxLayout, QLabel, QTextEdit
|
||||||
|
from UM.i18n import i18nCatalog
|
||||||
|
catalog = i18nCatalog("cura")
|
||||||
|
|
||||||
|
def show(type, value, tb):
|
||||||
|
if not hasattr(sys, "frozen"):
|
||||||
|
traceback.print_exception(type, value, tb)
|
||||||
|
|
||||||
|
application = QCoreApplication.instance()
|
||||||
|
if not application:
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
def show():
|
|
||||||
dialog = QDialog()
|
dialog = QDialog()
|
||||||
dialog.setWindowTitle("Oops!")
|
dialog.setWindowTitle(catalog.i18nc("@title:window", "Oops!"))
|
||||||
|
|
||||||
layout = QVBoxLayout(dialog)
|
layout = QVBoxLayout(dialog)
|
||||||
|
|
||||||
label = QLabel(dialog)
|
label = QLabel(dialog)
|
||||||
layout.addWidget(label)
|
layout.addWidget(label)
|
||||||
label.setText("<p>An uncaught exception has occurred!</p><p>Please use the information below to post a bug report at <a href=\"http://github.com/Ultimaker/Cura/issues\">http://github.com/Ultimaker/Cura/issues</a></p>")
|
label.setText(catalog.i18nc("@label", "<p>An uncaught exception has occurred!</p><p>Please use the information below to post a bug report at <a href=\"http://github.com/Ultimaker/Cura/issues\">http://github.com/Ultimaker/Cura/issues</a></p>"))
|
||||||
|
|
||||||
textarea = QTextEdit(dialog)
|
textarea = QTextEdit(dialog)
|
||||||
layout.addWidget(textarea)
|
layout.addWidget(textarea)
|
||||||
@ -25,7 +34,7 @@ def show():
|
|||||||
except:
|
except:
|
||||||
version = "Unknown"
|
version = "Unknown"
|
||||||
|
|
||||||
trace = "".join(traceback.format_exception(sys.exc_info()[0], sys.exc_info()[1], sys.exc_info()[2]))
|
trace = "".join(traceback.format_exception(type, value, tb))
|
||||||
|
|
||||||
crash_info = "Version: {0}\nPlatform: {1}\nQt: {2}\nPyQt: {3}\n\nException:\n{4}"
|
crash_info = "Version: {0}\nPlatform: {1}\nQt: {2}\nPyQt: {3}\n\nException:\n{4}"
|
||||||
crash_info = crash_info.format(version, platform.platform(), QT_VERSION_STR, PYQT_VERSION_STR, trace)
|
crash_info = crash_info.format(version, platform.platform(), QT_VERSION_STR, PYQT_VERSION_STR, trace)
|
||||||
@ -34,8 +43,9 @@ def show():
|
|||||||
|
|
||||||
buttons = QDialogButtonBox(QDialogButtonBox.Close, dialog)
|
buttons = QDialogButtonBox(QDialogButtonBox.Close, dialog)
|
||||||
layout.addWidget(buttons)
|
layout.addWidget(buttons)
|
||||||
buttons.addButton("Open Web Page", QDialogButtonBox.HelpRole)
|
buttons.addButton(catalog.i18nc("@action:button", "Open Web Page"), QDialogButtonBox.HelpRole)
|
||||||
buttons.rejected.connect(lambda: dialog.close())
|
buttons.rejected.connect(lambda: dialog.close())
|
||||||
buttons.helpRequested.connect(lambda: webbrowser.open("http://github.com/Ultimaker/Cura/issues"))
|
buttons.helpRequested.connect(lambda: webbrowser.open("http://github.com/Ultimaker/Cura/issues"))
|
||||||
|
|
||||||
dialog.exec_()
|
dialog.exec_()
|
||||||
|
sys.exit(1)
|
||||||
|
@ -1,6 +1,13 @@
|
|||||||
# 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.
|
||||||
|
|
||||||
|
import platform
|
||||||
|
|
||||||
|
if platform.system() == "Linux": # Needed for platform.linux_distribution, which is not available on Windows and OSX
|
||||||
|
# For Ubuntu: https://bugs.launchpad.net/ubuntu/+source/python-qt4/+bug/941826
|
||||||
|
if platform.linux_distribution()[0] in ("Ubuntu", ): # Just in case it also happens on Debian, so it can be added
|
||||||
|
from OpenGL import GL
|
||||||
|
|
||||||
from UM.Qt.QtApplication import QtApplication
|
from UM.Qt.QtApplication import QtApplication
|
||||||
from UM.Scene.SceneNode import SceneNode
|
from UM.Scene.SceneNode import SceneNode
|
||||||
from UM.Scene.Camera import Camera
|
from UM.Scene.Camera import Camera
|
||||||
@ -38,26 +45,32 @@ from . import PrintInformation
|
|||||||
from . import CuraActions
|
from . import CuraActions
|
||||||
from . import MultiMaterialDecorator
|
from . import MultiMaterialDecorator
|
||||||
|
|
||||||
from PyQt5.QtCore import pyqtSlot, QUrl, Qt, pyqtSignal, pyqtProperty
|
from PyQt5.QtCore import pyqtSlot, QUrl, Qt, pyqtSignal, pyqtProperty, QEvent, Q_ENUMS
|
||||||
from PyQt5.QtGui import QColor, QIcon
|
from PyQt5.QtGui import QColor, QIcon
|
||||||
|
from PyQt5.QtQml import qmlRegisterUncreatableType
|
||||||
|
|
||||||
import platform
|
import platform
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
import os.path
|
import os.path
|
||||||
import configparser
|
|
||||||
import numpy
|
import numpy
|
||||||
|
import copy
|
||||||
numpy.seterr(all="ignore")
|
numpy.seterr(all="ignore")
|
||||||
|
|
||||||
class CuraApplication(QtApplication):
|
class CuraApplication(QtApplication):
|
||||||
|
class ResourceTypes:
|
||||||
|
QmlFiles = Resources.UserType + 1
|
||||||
|
Firmware = Resources.UserType + 2
|
||||||
|
Q_ENUMS(ResourceTypes)
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
Resources.addResourcePath(os.path.join(QtApplication.getInstallPrefix(), "share", "cura"))
|
Resources.addSearchPath(os.path.join(QtApplication.getInstallPrefix(), "share", "cura"))
|
||||||
if not hasattr(sys, "frozen"):
|
if not hasattr(sys, "frozen"):
|
||||||
Resources.addResourcePath(os.path.join(os.path.abspath(os.path.dirname(__file__)), ".."))
|
Resources.addSearchPath(os.path.join(os.path.abspath(os.path.dirname(__file__)), ".."))
|
||||||
|
|
||||||
super().__init__(name = "cura", version = "master")
|
super().__init__(name = "cura", version = "15.09.82")
|
||||||
|
|
||||||
self.setWindowIcon(QIcon(Resources.getPath(Resources.ImagesLocation, "cura-icon.png")))
|
self.setWindowIcon(QIcon(Resources.getPath(Resources.Images, "cura-icon.png")))
|
||||||
|
|
||||||
self.setRequiredPlugins([
|
self.setRequiredPlugins([
|
||||||
"CuraEngineBackend",
|
"CuraEngineBackend",
|
||||||
@ -78,12 +91,19 @@ class CuraApplication(QtApplication):
|
|||||||
self._previous_active_tool = None
|
self._previous_active_tool = None
|
||||||
self._platform_activity = False
|
self._platform_activity = False
|
||||||
|
|
||||||
self.activeMachineChanged.connect(self._onActiveMachineChanged)
|
self.getMachineManager().activeMachineInstanceChanged.connect(self._onActiveMachineChanged)
|
||||||
|
self.getMachineManager().addMachineRequested.connect(self._onAddMachineRequested)
|
||||||
|
self.getController().getScene().sceneChanged.connect(self.updatePlatformActivity)
|
||||||
|
|
||||||
|
Resources.addType(self.ResourceTypes.QmlFiles, "qml")
|
||||||
|
Resources.addType(self.ResourceTypes.Firmware, "firmware")
|
||||||
|
|
||||||
Preferences.getInstance().addPreference("cura/active_machine", "")
|
Preferences.getInstance().addPreference("cura/active_machine", "")
|
||||||
Preferences.getInstance().addPreference("cura/active_mode", "simple")
|
Preferences.getInstance().addPreference("cura/active_mode", "simple")
|
||||||
Preferences.getInstance().addPreference("cura/recent_files", "")
|
Preferences.getInstance().addPreference("cura/recent_files", "")
|
||||||
Preferences.getInstance().addPreference("cura/categories_expanded", "")
|
Preferences.getInstance().addPreference("cura/categories_expanded", "")
|
||||||
|
Preferences.getInstance().addPreference("view/center_on_select", True)
|
||||||
|
Preferences.getInstance().addPreference("mesh/scale_to_fit", True)
|
||||||
|
|
||||||
JobQueue.getInstance().jobFinished.connect(self._onJobFinished)
|
JobQueue.getInstance().jobFinished.connect(self._onJobFinished)
|
||||||
|
|
||||||
@ -115,7 +135,12 @@ class CuraApplication(QtApplication):
|
|||||||
def run(self):
|
def run(self):
|
||||||
self._i18n_catalog = i18nCatalog("cura");
|
self._i18n_catalog = i18nCatalog("cura");
|
||||||
|
|
||||||
self.showSplashMessage(self._i18n_catalog.i18nc("Splash screen message", "Setting up scene..."))
|
i18nCatalog.setTagReplacements({
|
||||||
|
"filename": "font color=\"black\"",
|
||||||
|
"message": "font color=UM.Theme.colors.message_text;",
|
||||||
|
})
|
||||||
|
|
||||||
|
self.showSplashMessage(self._i18n_catalog.i18nc("@info:progress", "Setting up scene..."))
|
||||||
|
|
||||||
controller = self.getController()
|
controller = self.getController()
|
||||||
|
|
||||||
@ -125,7 +150,7 @@ class CuraApplication(QtApplication):
|
|||||||
|
|
||||||
t = controller.getTool("TranslateTool")
|
t = controller.getTool("TranslateTool")
|
||||||
if t:
|
if t:
|
||||||
t.setEnabledAxis([ToolHandle.XAxis, ToolHandle.ZAxis])
|
t.setEnabledAxis([ToolHandle.XAxis, ToolHandle.YAxis,ToolHandle.ZAxis])
|
||||||
|
|
||||||
Selection.selectionChanged.connect(self.onSelectionChanged)
|
Selection.selectionChanged.connect(self.onSelectionChanged)
|
||||||
|
|
||||||
@ -149,33 +174,34 @@ class CuraApplication(QtApplication):
|
|||||||
|
|
||||||
controller.getScene().setActiveCamera("3d")
|
controller.getScene().setActiveCamera("3d")
|
||||||
|
|
||||||
self.showSplashMessage(self._i18n_catalog.i18nc("Splash screen message", "Loading interface..."))
|
self.showSplashMessage(self._i18n_catalog.i18nc("@info:progress", "Loading interface..."))
|
||||||
|
|
||||||
self.setMainQml(Resources.getPath(Resources.QmlFilesLocation, "Cura.qml"))
|
self.setMainQml(Resources.getPath(self.ResourceTypes.QmlFiles, "Cura.qml"))
|
||||||
self.initializeEngine()
|
self.initializeEngine()
|
||||||
|
|
||||||
if self.getMachines():
|
manager = self.getMachineManager()
|
||||||
active_machine_pref = Preferences.getInstance().getValue("cura/active_machine")
|
if not self.getMachineManager().getMachineInstances():
|
||||||
if active_machine_pref:
|
|
||||||
for machine in self.getMachines():
|
|
||||||
if machine.getName() == active_machine_pref:
|
|
||||||
self.setActiveMachine(machine)
|
|
||||||
|
|
||||||
if not self.getActiveMachine():
|
|
||||||
self.setActiveMachine(self.getMachines()[0])
|
|
||||||
else:
|
|
||||||
self.requestAddPrinter.emit()
|
self.requestAddPrinter.emit()
|
||||||
|
|
||||||
|
|
||||||
if self._engine.rootObjects:
|
if self._engine.rootObjects:
|
||||||
self.closeSplash()
|
self.closeSplash()
|
||||||
|
|
||||||
for file in self.getCommandLineOption("file", []):
|
for file in self.getCommandLineOption("file", []):
|
||||||
job = ReadMeshJob(os.path.abspath(file))
|
self._openFile(file)
|
||||||
job.finished.connect(self._onFileLoaded)
|
|
||||||
job.start()
|
|
||||||
|
|
||||||
self.exec_()
|
self.exec_()
|
||||||
|
|
||||||
|
# Handle Qt events
|
||||||
|
def event(self, event):
|
||||||
|
if event.type() == QEvent.FileOpen:
|
||||||
|
self._openFile(event.file())
|
||||||
|
|
||||||
|
return super().event(event)
|
||||||
|
|
||||||
|
def getPrintInformation(self):
|
||||||
|
return self._print_information
|
||||||
|
|
||||||
def registerObjects(self, engine):
|
def registerObjects(self, engine):
|
||||||
engine.rootContext().setContextProperty("Printer", self)
|
engine.rootContext().setContextProperty("Printer", self)
|
||||||
self._print_information = PrintInformation.PrintInformation()
|
self._print_information = PrintInformation.PrintInformation()
|
||||||
@ -183,6 +209,8 @@ class CuraApplication(QtApplication):
|
|||||||
self._cura_actions = CuraActions.CuraActions(self)
|
self._cura_actions = CuraActions.CuraActions(self)
|
||||||
engine.rootContext().setContextProperty("CuraActions", self._cura_actions)
|
engine.rootContext().setContextProperty("CuraActions", self._cura_actions)
|
||||||
|
|
||||||
|
qmlRegisterUncreatableType(CuraApplication, "Cura", 1, 0, "ResourceTypes", "Just an Enum type")
|
||||||
|
|
||||||
def onSelectionChanged(self):
|
def onSelectionChanged(self):
|
||||||
if Selection.hasSelection():
|
if Selection.hasSelection():
|
||||||
if not self.getController().getActiveTool():
|
if not self.getController().getActiveTool():
|
||||||
@ -191,7 +219,7 @@ class CuraApplication(QtApplication):
|
|||||||
self._previous_active_tool = None
|
self._previous_active_tool = None
|
||||||
else:
|
else:
|
||||||
self.getController().setActiveTool("TranslateTool")
|
self.getController().setActiveTool("TranslateTool")
|
||||||
|
if Preferences.getInstance().getValue("view/center_on_select"):
|
||||||
self._camera_animation.setStart(self.getController().getTool("CameraTool").getOrigin())
|
self._camera_animation.setStart(self.getController().getTool("CameraTool").getOrigin())
|
||||||
self._camera_animation.setTarget(Selection.getSelectedObject(0).getWorldPosition())
|
self._camera_animation.setTarget(Selection.getSelectedObject(0).getWorldPosition())
|
||||||
self._camera_animation.start()
|
self._camera_animation.start()
|
||||||
@ -209,24 +237,15 @@ class CuraApplication(QtApplication):
|
|||||||
def getPlatformActivity(self):
|
def getPlatformActivity(self):
|
||||||
return self._platform_activity
|
return self._platform_activity
|
||||||
|
|
||||||
@pyqtSlot(bool)
|
def updatePlatformActivity(self, node = None):
|
||||||
def setPlatformActivity(self, activity):
|
count = 0
|
||||||
##Sets the _platform_activity variable on true or false depending on whether there is a mesh on the platform
|
|
||||||
if activity == True:
|
|
||||||
self._platform_activity = activity
|
|
||||||
elif activity == False:
|
|
||||||
nodes = []
|
|
||||||
for node in DepthFirstIterator(self.getController().getScene().getRoot()):
|
for node in DepthFirstIterator(self.getController().getScene().getRoot()):
|
||||||
if type(node) is not SceneNode or not node.getMeshData():
|
if type(node) is not SceneNode or not node.getMeshData():
|
||||||
continue
|
continue
|
||||||
nodes.append(node)
|
|
||||||
i = 0
|
count += 1
|
||||||
for node in nodes:
|
|
||||||
if not node.getMeshData():
|
self._platform_activity = True if count > 0 else False
|
||||||
continue
|
|
||||||
i += 1
|
|
||||||
if i <= 1: ## i == 0 when the meshes are removed using the deleteAll function; i == 1 when the last remaining mesh is removed using the deleteObject function
|
|
||||||
self._platform_activity = activity
|
|
||||||
self.activityChanged.emit()
|
self.activityChanged.emit()
|
||||||
|
|
||||||
## Remove an object from the scene
|
## Remove an object from the scene
|
||||||
@ -247,7 +266,6 @@ class CuraApplication(QtApplication):
|
|||||||
group_node = group_node.getParent()
|
group_node = group_node.getParent()
|
||||||
op = RemoveSceneNodeOperation(group_node)
|
op = RemoveSceneNodeOperation(group_node)
|
||||||
op.push()
|
op.push()
|
||||||
self.setPlatformActivity(False)
|
|
||||||
|
|
||||||
## Create a number of copies of existing object.
|
## Create a number of copies of existing object.
|
||||||
@pyqtSlot("quint64", int)
|
@pyqtSlot("quint64", int)
|
||||||
@ -260,22 +278,26 @@ class CuraApplication(QtApplication):
|
|||||||
if node:
|
if node:
|
||||||
op = GroupedOperation()
|
op = GroupedOperation()
|
||||||
for i in range(count):
|
for i in range(count):
|
||||||
new_node = SceneNode()
|
if node.getParent() and node.getParent().callDecoration("isGroup"):
|
||||||
new_node.setMeshData(node.getMeshData())
|
new_node = copy.deepcopy(node.getParent()) #Copy the group node.
|
||||||
new_node.setScale(node.getScale())
|
new_node.callDecoration("setConvexHull",None)
|
||||||
new_node.translate(Vector((i + 1) * node.getBoundingBox().width, 0, 0))
|
|
||||||
new_node.setSelectable(True)
|
op.addOperation(AddSceneNodeOperation(new_node,node.getParent().getParent()))
|
||||||
|
else:
|
||||||
|
new_node = copy.deepcopy(node)
|
||||||
|
new_node.callDecoration("setConvexHull", None)
|
||||||
op.addOperation(AddSceneNodeOperation(new_node, node.getParent()))
|
op.addOperation(AddSceneNodeOperation(new_node, node.getParent()))
|
||||||
|
|
||||||
op.push()
|
op.push()
|
||||||
|
|
||||||
## Center object on platform.
|
## Center object on platform.
|
||||||
@pyqtSlot("quint64")
|
@pyqtSlot("quint64")
|
||||||
def centerObject(self, object_id):
|
def centerObject(self, object_id):
|
||||||
node = self.getController().getScene().findObject(object_id)
|
node = self.getController().getScene().findObject(object_id)
|
||||||
|
if node.getParent() and node.getParent().callDecoration("isGroup"):
|
||||||
|
node = node.getParent()
|
||||||
if not node and object_id != 0: #Workaround for tool handles overlapping the selected object
|
if not node and object_id != 0: #Workaround for tool handles overlapping the selected object
|
||||||
node = Selection.getSelectedObject(0)
|
node = Selection.getSelectedObject(0)
|
||||||
|
|
||||||
if node:
|
if node:
|
||||||
op = SetTransformOperation(node, Vector())
|
op = SetTransformOperation(node, Vector())
|
||||||
op.push()
|
op.push()
|
||||||
@ -285,8 +307,12 @@ class CuraApplication(QtApplication):
|
|||||||
def deleteAll(self):
|
def deleteAll(self):
|
||||||
nodes = []
|
nodes = []
|
||||||
for node in DepthFirstIterator(self.getController().getScene().getRoot()):
|
for node in DepthFirstIterator(self.getController().getScene().getRoot()):
|
||||||
if type(node) is not SceneNode or not node.getMeshData():
|
if type(node) is not SceneNode:
|
||||||
continue
|
continue
|
||||||
|
if not node.getMeshData() and not node.callDecoration("isGroup"):
|
||||||
|
continue #Node that doesnt have a mesh and is not a group.
|
||||||
|
if node.getParent() and node.getParent().callDecoration("isGroup"):
|
||||||
|
continue #Grouped nodes don't need resetting as their parent (the group) is resetted)
|
||||||
nodes.append(node)
|
nodes.append(node)
|
||||||
if nodes:
|
if nodes:
|
||||||
op = GroupedOperation()
|
op = GroupedOperation()
|
||||||
@ -295,22 +321,28 @@ class CuraApplication(QtApplication):
|
|||||||
op.addOperation(RemoveSceneNodeOperation(node))
|
op.addOperation(RemoveSceneNodeOperation(node))
|
||||||
|
|
||||||
op.push()
|
op.push()
|
||||||
self.setPlatformActivity(False)
|
|
||||||
|
|
||||||
## Reset all translation on nodes with mesh data.
|
## Reset all translation on nodes with mesh data.
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def resetAllTranslation(self):
|
def resetAllTranslation(self):
|
||||||
nodes = []
|
nodes = []
|
||||||
for node in DepthFirstIterator(self.getController().getScene().getRoot()):
|
for node in DepthFirstIterator(self.getController().getScene().getRoot()):
|
||||||
if type(node) is not SceneNode or not node.getMeshData():
|
if type(node) is not SceneNode:
|
||||||
continue
|
continue
|
||||||
nodes.append(node)
|
if not node.getMeshData() and not node.callDecoration("isGroup"):
|
||||||
|
continue #Node that doesnt have a mesh and is not a group.
|
||||||
|
if node.getParent() and node.getParent().callDecoration("isGroup"):
|
||||||
|
continue #Grouped nodes don't need resetting as their parent (the group) is resetted)
|
||||||
|
|
||||||
|
nodes.append(node)
|
||||||
if nodes:
|
if nodes:
|
||||||
op = GroupedOperation()
|
op = GroupedOperation()
|
||||||
|
|
||||||
for node in nodes:
|
for node in nodes:
|
||||||
op.addOperation(SetTransformOperation(node, Vector()))
|
# Ensure that the object is above the build platform
|
||||||
|
move_distance = node.getBoundingBox().center.y
|
||||||
|
if move_distance <= 0:
|
||||||
|
move_distance = -node.getBoundingBox().bottom
|
||||||
|
op.addOperation(SetTransformOperation(node, Vector(0,move_distance,0)))
|
||||||
|
|
||||||
op.push()
|
op.push()
|
||||||
|
|
||||||
@ -319,15 +351,23 @@ class CuraApplication(QtApplication):
|
|||||||
def resetAll(self):
|
def resetAll(self):
|
||||||
nodes = []
|
nodes = []
|
||||||
for node in DepthFirstIterator(self.getController().getScene().getRoot()):
|
for node in DepthFirstIterator(self.getController().getScene().getRoot()):
|
||||||
if type(node) is not SceneNode or not node.getMeshData():
|
if type(node) is not SceneNode:
|
||||||
continue
|
continue
|
||||||
|
if not node.getMeshData() and not node.callDecoration("isGroup"):
|
||||||
|
continue #Node that doesnt have a mesh and is not a group.
|
||||||
|
if node.getParent() and node.getParent().callDecoration("isGroup"):
|
||||||
|
continue #Grouped nodes don't need resetting as their parent (the group) is resetted)
|
||||||
nodes.append(node)
|
nodes.append(node)
|
||||||
|
|
||||||
if nodes:
|
if nodes:
|
||||||
op = GroupedOperation()
|
op = GroupedOperation()
|
||||||
|
|
||||||
for node in nodes:
|
for node in nodes:
|
||||||
op.addOperation(SetTransformOperation(node, Vector(), Quaternion(), Vector(1, 1, 1)))
|
# Ensure that the object is above the build platform
|
||||||
|
move_distance = node.getBoundingBox().center.y
|
||||||
|
if move_distance <= 0:
|
||||||
|
move_distance = -node.getBoundingBox().bottom
|
||||||
|
op.addOperation(SetTransformOperation(node, Vector(0,move_distance,0), Quaternion(), Vector(1, 1, 1)))
|
||||||
|
|
||||||
op.push()
|
op.push()
|
||||||
|
|
||||||
@ -387,18 +427,18 @@ class CuraApplication(QtApplication):
|
|||||||
|
|
||||||
@pyqtSlot(str, result = "QVariant")
|
@pyqtSlot(str, result = "QVariant")
|
||||||
def getSettingValue(self, key):
|
def getSettingValue(self, key):
|
||||||
if not self.getActiveMachine():
|
if not self.getMachineManager().getActiveProfile():
|
||||||
return None
|
return None
|
||||||
|
return self.getMachineManager().getActiveProfile().getSettingValue(key)
|
||||||
return self.getActiveMachine().getSettingValueByKey(key)
|
#return self.getActiveMachine().getSettingValueByKey(key)
|
||||||
|
|
||||||
## Change setting by key value pair
|
## Change setting by key value pair
|
||||||
@pyqtSlot(str, "QVariant")
|
@pyqtSlot(str, "QVariant")
|
||||||
def setSettingValue(self, key, value):
|
def setSettingValue(self, key, value):
|
||||||
if not self.getActiveMachine():
|
if not self.getMachineManager().getActiveProfile():
|
||||||
return
|
return
|
||||||
|
|
||||||
self.getActiveMachine().setSettingValueByKey(key, value)
|
self.getMachineManager().getActiveProfile().setSettingValue(key, value)
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def mergeSelected(self):
|
def mergeSelected(self):
|
||||||
@ -412,7 +452,7 @@ class CuraApplication(QtApplication):
|
|||||||
# Reset the position of each node
|
# Reset the position of each node
|
||||||
for node in group_node.getChildren():
|
for node in group_node.getChildren():
|
||||||
new_position = node.getMeshData().getCenterPosition()
|
new_position = node.getMeshData().getCenterPosition()
|
||||||
new_position.setY(0)
|
new_position = new_position.scale(node.getScale())
|
||||||
node.setPosition(new_position)
|
node.setPosition(new_position)
|
||||||
|
|
||||||
# Use the previously found center of the group bounding box as the new location of the group
|
# Use the previously found center of the group bounding box as the new location of the group
|
||||||
@ -427,7 +467,9 @@ class CuraApplication(QtApplication):
|
|||||||
|
|
||||||
for node in Selection.getAllSelectedObjects():
|
for node in Selection.getAllSelectedObjects():
|
||||||
node.setParent(group_node)
|
node.setParent(group_node)
|
||||||
|
group_node.setCenterPosition(group_node.getBoundingBox().center)
|
||||||
|
#group_node.translate(Vector(0,group_node.getBoundingBox().center.y,0))
|
||||||
|
group_node.translate(group_node.getBoundingBox().center)
|
||||||
for node in group_node.getChildren():
|
for node in group_node.getChildren():
|
||||||
Selection.remove(node)
|
Selection.remove(node)
|
||||||
|
|
||||||
@ -446,6 +488,12 @@ class CuraApplication(QtApplication):
|
|||||||
|
|
||||||
for child in children_to_move:
|
for child in children_to_move:
|
||||||
child.setParent(node.getParent())
|
child.setParent(node.getParent())
|
||||||
|
print(node.getPosition())
|
||||||
|
child.translate(node.getPosition())
|
||||||
|
child.setPosition(child.getPosition().scale(node.getScale()))
|
||||||
|
child.scale(node.getScale())
|
||||||
|
child.rotate(node.getOrientation())
|
||||||
|
|
||||||
Selection.add(child)
|
Selection.add(child)
|
||||||
child.callDecoration("setConvexHull",None)
|
child.callDecoration("setConvexHull",None)
|
||||||
node.setParent(None)
|
node.setParent(None)
|
||||||
@ -454,37 +502,35 @@ class CuraApplication(QtApplication):
|
|||||||
Selection.remove(node)
|
Selection.remove(node)
|
||||||
|
|
||||||
def _onActiveMachineChanged(self):
|
def _onActiveMachineChanged(self):
|
||||||
machine = self.getActiveMachine()
|
machine = self.getMachineManager().getActiveMachineInstance()
|
||||||
if machine:
|
if machine:
|
||||||
Preferences.getInstance().setValue("cura/active_machine", machine.getName())
|
pass
|
||||||
|
#Preferences.getInstance().setValue("cura/active_machine", machine.getName())
|
||||||
|
|
||||||
self._volume.setWidth(machine.getSettingValueByKey("machine_width"))
|
#self._volume.setWidth(machine.getSettingValueByKey("machine_width"))
|
||||||
self._volume.setHeight(machine.getSettingValueByKey("machine_height"))
|
#self._volume.setHeight(machine.getSettingValueByKey("machine_height"))
|
||||||
self._volume.setDepth(machine.getSettingValueByKey("machine_depth"))
|
#self._volume.setDepth(machine.getSettingValueByKey("machine_depth"))
|
||||||
|
|
||||||
disallowed_areas = machine.getSettingValueByKey("machine_disallowed_areas")
|
#disallowed_areas = machine.getSettingValueByKey("machine_disallowed_areas")
|
||||||
areas = []
|
#areas = []
|
||||||
if disallowed_areas:
|
#if disallowed_areas:
|
||||||
for area in disallowed_areas:
|
#for area in disallowed_areas:
|
||||||
areas.append(Polygon(numpy.array(area, numpy.float32)))
|
#areas.append(Polygon(numpy.array(area, numpy.float32)))
|
||||||
|
|
||||||
self._volume.setDisallowedAreas(areas)
|
#self._volume.setDisallowedAreas(areas)
|
||||||
|
|
||||||
self._volume.rebuild()
|
#self._volume.rebuild()
|
||||||
|
|
||||||
offset = machine.getSettingValueByKey("machine_platform_offset")
|
#offset = machine.getSettingValueByKey("machine_platform_offset")
|
||||||
if offset:
|
#if offset:
|
||||||
self._platform.setPosition(Vector(offset[0], offset[1], offset[2]))
|
#self._platform.setPosition(Vector(offset[0], offset[1], offset[2]))
|
||||||
else:
|
#else:
|
||||||
self._platform.setPosition(Vector(0.0, 0.0, 0.0))
|
#self._platform.setPosition(Vector(0.0, 0.0, 0.0))
|
||||||
|
|
||||||
def _onFileLoaded(self, job):
|
def _onFileLoaded(self, job):
|
||||||
mesh = job.getResult()
|
node = job.getResult()
|
||||||
if mesh != None:
|
if node != None:
|
||||||
node = SceneNode()
|
|
||||||
|
|
||||||
node.setSelectable(True)
|
node.setSelectable(True)
|
||||||
node.setMeshData(mesh)
|
|
||||||
node.setName(os.path.basename(job.getFileName()))
|
node.setName(os.path.basename(job.getFileName()))
|
||||||
|
|
||||||
op = AddSceneNodeOperation(node, self.getController().getScene().getRoot())
|
op = AddSceneNodeOperation(node, self.getController().getScene().getRoot())
|
||||||
@ -510,4 +556,16 @@ class CuraApplication(QtApplication):
|
|||||||
self.recentFilesChanged.emit()
|
self.recentFilesChanged.emit()
|
||||||
|
|
||||||
def _reloadMeshFinished(self, job):
|
def _reloadMeshFinished(self, job):
|
||||||
job._node.setMeshData(job.getResult())
|
# TODO; This needs to be fixed properly. We now make the assumption that we only load a single mesh!
|
||||||
|
job._node.setMeshData(job.getResult().getMeshData())
|
||||||
|
#job.getResult().setParent(self.getController().getScene().getRoot())
|
||||||
|
#job._node.setParent(self.getController().getScene().getRoot())
|
||||||
|
#job._node.meshDataChanged.emit(job._node)
|
||||||
|
|
||||||
|
def _openFile(self, file):
|
||||||
|
job = ReadMeshJob(os.path.abspath(file))
|
||||||
|
job.finished.connect(self._onFileLoaded)
|
||||||
|
job.start()
|
||||||
|
|
||||||
|
def _onAddMachineRequested(self):
|
||||||
|
self.requestAddPrinter.emit()
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
# Cura is released under the terms of the AGPLv3 or higher.
|
# Cura is released under the terms of the AGPLv3 or higher.
|
||||||
|
|
||||||
from UM.Scene.Iterator import Iterator
|
from UM.Scene.Iterator import Iterator
|
||||||
|
from UM.Scene.SceneNode import SceneNode
|
||||||
from functools import cmp_to_key
|
from functools import cmp_to_key
|
||||||
from UM.Application import Application
|
from UM.Application import Application
|
||||||
|
|
||||||
@ -10,14 +11,17 @@ from UM.Application import Application
|
|||||||
# Take note that the list of nodes can have children (that may or may not contain mesh data)
|
# Take note that the list of nodes can have children (that may or may not contain mesh data)
|
||||||
class OneAtATimeIterator(Iterator.Iterator):
|
class OneAtATimeIterator(Iterator.Iterator):
|
||||||
def __init__(self, scene_node):
|
def __init__(self, scene_node):
|
||||||
super(OneAtATimeIterator, self).__init__(scene_node) # Call super to make multiple inheritence work.
|
super().__init__(scene_node) # Call super to make multiple inheritence work.
|
||||||
self._hit_map = [[]]
|
self._hit_map = [[]]
|
||||||
self._original_node_list = []
|
self._original_node_list = []
|
||||||
|
|
||||||
def _fillStack(self):
|
def _fillStack(self):
|
||||||
node_list = []
|
node_list = []
|
||||||
for node in self._scene_node.getChildren():
|
for node in self._scene_node.getChildren():
|
||||||
if node.getBoundingBox().height > Application.getInstance().getActiveMachine().getSettingValueByKey("gantry_height"):
|
if not type(node) is SceneNode:
|
||||||
|
continue
|
||||||
|
|
||||||
|
if node.getBoundingBox().height > Application.getInstance().getMachineManager().getActiveProfile().getSettingValue("gantry_height"):
|
||||||
return
|
return
|
||||||
if node.callDecoration("getConvexHull"):
|
if node.callDecoration("getConvexHull"):
|
||||||
node_list.append(node)
|
node_list.append(node)
|
||||||
@ -55,7 +59,7 @@ class OneAtATimeIterator(Iterator.Iterator):
|
|||||||
# We have no more nodes to check, so quit looking.
|
# We have no more nodes to check, so quit looking.
|
||||||
todo_node_list = None
|
todo_node_list = None
|
||||||
self._node_stack = new_order
|
self._node_stack = new_order
|
||||||
print(self._node_stack)
|
|
||||||
return
|
return
|
||||||
todo_node_list.append(_objectOrder(new_order, new_todo_list))
|
todo_node_list.append(_objectOrder(new_order, new_todo_list))
|
||||||
self._node_stack = [] #No result found!
|
self._node_stack = [] #No result found!
|
||||||
|
@ -6,12 +6,13 @@ from PyQt5.QtCore import QTimer
|
|||||||
from UM.Scene.SceneNode import SceneNode
|
from UM.Scene.SceneNode import SceneNode
|
||||||
from UM.Scene.Iterator.BreadthFirstIterator import BreadthFirstIterator
|
from UM.Scene.Iterator.BreadthFirstIterator import BreadthFirstIterator
|
||||||
from UM.Operations.TranslateOperation import TranslateOperation
|
from UM.Operations.TranslateOperation import TranslateOperation
|
||||||
from UM.Operations.ScaleToBoundsOperation import ScaleToBoundsOperation
|
|
||||||
from UM.Math.Float import Float
|
from UM.Math.Float import Float
|
||||||
from UM.Math.Vector import Vector
|
from UM.Math.Vector import Vector
|
||||||
from UM.Math.AxisAlignedBox import AxisAlignedBox
|
from UM.Math.AxisAlignedBox import AxisAlignedBox
|
||||||
from UM.Application import Application
|
from UM.Application import Application
|
||||||
from UM.Scene.Selection import Selection
|
from UM.Scene.Selection import Selection
|
||||||
|
from UM.Preferences import Preferences
|
||||||
|
|
||||||
from cura.ConvexHullDecorator import ConvexHullDecorator
|
from cura.ConvexHullDecorator import ConvexHullDecorator
|
||||||
|
|
||||||
from . import PlatformPhysicsOperation
|
from . import PlatformPhysicsOperation
|
||||||
@ -19,6 +20,7 @@ from . import ConvexHullJob
|
|||||||
|
|
||||||
import time
|
import time
|
||||||
import threading
|
import threading
|
||||||
|
import copy
|
||||||
|
|
||||||
class PlatformPhysics:
|
class PlatformPhysics:
|
||||||
def __init__(self, controller, volume):
|
def __init__(self, controller, volume):
|
||||||
@ -36,6 +38,8 @@ class PlatformPhysics:
|
|||||||
self._change_timer.setSingleShot(True)
|
self._change_timer.setSingleShot(True)
|
||||||
self._change_timer.timeout.connect(self._onChangeTimerFinished)
|
self._change_timer.timeout.connect(self._onChangeTimerFinished)
|
||||||
|
|
||||||
|
Preferences.getInstance().addPreference("physics/automatic_push_free", True)
|
||||||
|
|
||||||
def _onSceneChanged(self, source):
|
def _onSceneChanged(self, source):
|
||||||
self._change_timer.start()
|
self._change_timer.start()
|
||||||
|
|
||||||
@ -53,16 +57,22 @@ class PlatformPhysics:
|
|||||||
self._change_timer.start()
|
self._change_timer.start()
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
build_volume_bounding_box = copy.deepcopy(self._build_volume.getBoundingBox())
|
||||||
|
build_volume_bounding_box.setBottom(-9001) # Ignore intersections with the bottom
|
||||||
|
|
||||||
# Mark the node as outside the build volume if the bounding box test fails.
|
# Mark the node as outside the build volume if the bounding box test fails.
|
||||||
if self._build_volume.getBoundingBox().intersectsBox(bbox) != AxisAlignedBox.IntersectionResult.FullIntersection:
|
if build_volume_bounding_box.intersectsBox(bbox) != AxisAlignedBox.IntersectionResult.FullIntersection:
|
||||||
node._outside_buildarea = True
|
node._outside_buildarea = True
|
||||||
else:
|
else:
|
||||||
node._outside_buildarea = False
|
node._outside_buildarea = False
|
||||||
|
|
||||||
# Move the node upwards if the bottom is below the build platform.
|
# Move it downwards if bottom is above platform
|
||||||
move_vector = Vector()
|
move_vector = Vector()
|
||||||
if not Float.fuzzyCompare(bbox.bottom, 0.0):
|
if not (node.getParent() and node.getParent().callDecoration("isGroup")): #If an object is grouped, don't move it down
|
||||||
|
if bbox.bottom > 0:
|
||||||
move_vector.setY(-bbox.bottom)
|
move_vector.setY(-bbox.bottom)
|
||||||
|
#if not Float.fuzzyCompare(bbox.bottom, 0.0):
|
||||||
|
# pass#move_vector.setY(-bbox.bottom)
|
||||||
|
|
||||||
# If there is no convex hull for the node, start calculating it and continue.
|
# If there is no convex hull for the node, start calculating it and continue.
|
||||||
if not node.getDecorator(ConvexHullDecorator):
|
if not node.getDecorator(ConvexHullDecorator):
|
||||||
@ -76,7 +86,7 @@ class PlatformPhysics:
|
|||||||
|
|
||||||
elif Selection.isSelected(node):
|
elif Selection.isSelected(node):
|
||||||
pass
|
pass
|
||||||
else:
|
elif Preferences.getInstance().getValue("physics/automatic_push_free"):
|
||||||
# Check for collisions between convex hulls
|
# Check for collisions between convex hulls
|
||||||
for other_node in BreadthFirstIterator(root):
|
for other_node in BreadthFirstIterator(root):
|
||||||
# Ignore root, ourselves and anything that is not a normal SceneNode.
|
# Ignore root, ourselves and anything that is not a normal SceneNode.
|
||||||
@ -88,27 +98,41 @@ class PlatformPhysics:
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
# Ignore colissions within a group
|
# Ignore colissions within a group
|
||||||
if other_node.getParent().callDecoration("isGroup") is not None:
|
if other_node.getParent().callDecoration("isGroup") is not None or node.getParent().callDecoration("isGroup") is not None:
|
||||||
if node.getParent().callDecoration("isGroup") is other_node.getParent().callDecoration("isGroup"):
|
|
||||||
continue
|
continue
|
||||||
|
#if node.getParent().callDecoration("isGroup") is other_node.getParent().callDecoration("isGroup"):
|
||||||
|
# continue
|
||||||
|
|
||||||
# Ignore nodes that do not have the right properties set.
|
# Ignore nodes that do not have the right properties set.
|
||||||
if not other_node.callDecoration("getConvexHull") or not other_node.getBoundingBox():
|
if not other_node.callDecoration("getConvexHull") or not other_node.getBoundingBox():
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Check to see if the bounding boxes intersect. If not, we can ignore the node as there is no way the hull intersects.
|
# Check to see if the bounding boxes intersect. If not, we can ignore the node as there is no way the hull intersects.
|
||||||
if node.getBoundingBox().intersectsBox(other_node.getBoundingBox()) == AxisAlignedBox.IntersectionResult.NoIntersection:
|
#if node.getBoundingBox().intersectsBox(other_node.getBoundingBox()) == AxisAlignedBox.IntersectionResult.NoIntersection:
|
||||||
continue
|
# continue
|
||||||
|
|
||||||
# Get the overlap distance for both convex hulls. If this returns None, there is no intersection.
|
# Get the overlap distance for both convex hulls. If this returns None, there is no intersection.
|
||||||
|
try:
|
||||||
|
head_hull = node.callDecoration("getConvexHullHead")
|
||||||
|
if head_hull:
|
||||||
|
overlap = head_hull.intersectsPolygon(other_node.callDecoration("getConvexHull"))
|
||||||
|
if not overlap:
|
||||||
|
other_head_hull = other_node.callDecoration("getConvexHullHead")
|
||||||
|
if other_head_hull:
|
||||||
|
overlap = node.callDecoration("getConvexHull").intersectsPolygon(other_head_hull)
|
||||||
|
else:
|
||||||
overlap = node.callDecoration("getConvexHull").intersectsPolygon(other_node.callDecoration("getConvexHull"))
|
overlap = node.callDecoration("getConvexHull").intersectsPolygon(other_node.callDecoration("getConvexHull"))
|
||||||
|
except:
|
||||||
|
overlap = None #It can sometimes occur that the caclulated convex hull has no size, in which case there is no overlap.
|
||||||
|
|
||||||
if overlap is None:
|
if overlap is None:
|
||||||
continue
|
continue
|
||||||
|
move_vector.setX(overlap[0] * 1.01)
|
||||||
move_vector.setX(overlap[0] * 1.1)
|
move_vector.setZ(overlap[1] * 1.01)
|
||||||
move_vector.setZ(overlap[1] * 1.1)
|
|
||||||
convex_hull = node.callDecoration("getConvexHull")
|
convex_hull = node.callDecoration("getConvexHull")
|
||||||
if convex_hull:
|
if convex_hull:
|
||||||
|
if not convex_hull.isValid():
|
||||||
|
return
|
||||||
# Check for collisions between disallowed areas and the object
|
# Check for collisions between disallowed areas and the object
|
||||||
for area in self._build_volume.getDisallowedAreas():
|
for area in self._build_volume.getDisallowedAreas():
|
||||||
overlap = convex_hull.intersectsPolygon(area)
|
overlap = convex_hull.intersectsPolygon(area)
|
||||||
|
@ -40,48 +40,13 @@ class PrintInformation(QObject):
|
|||||||
def __init__(self, parent = None):
|
def __init__(self, parent = None):
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
|
|
||||||
self._enabled = False
|
|
||||||
|
|
||||||
self._minimum_print_time = Duration(None, self)
|
|
||||||
self._current_print_time = Duration(None, self)
|
self._current_print_time = Duration(None, self)
|
||||||
self._maximum_print_time = Duration(None, self)
|
|
||||||
|
|
||||||
self._material_amount = -1
|
self._material_amount = -1
|
||||||
|
|
||||||
self._time_quality_value = 50
|
|
||||||
self._time_quality_changed_timer = QTimer()
|
|
||||||
self._time_quality_changed_timer.setInterval(500)
|
|
||||||
self._time_quality_changed_timer.setSingleShot(True)
|
|
||||||
self._time_quality_changed_timer.timeout.connect(self._updateTimeQualitySettings)
|
|
||||||
|
|
||||||
self._interpolation_settings = {
|
|
||||||
"layer_height": { "minimum": "low", "maximum": "high", "curve": "linear", "precision": 2 },
|
|
||||||
"fill_sparse_density": { "minimum": "low", "maximum": "high", "curve": "linear", "precision": 0 }
|
|
||||||
}
|
|
||||||
|
|
||||||
self._low_quality_settings = None
|
|
||||||
self._current_settings = None
|
|
||||||
self._high_quality_settings = None
|
|
||||||
|
|
||||||
self._slice_pass = None
|
|
||||||
self._slice_reason = None
|
|
||||||
|
|
||||||
Application.getInstance().activeMachineChanged.connect(self._onActiveMachineChanged)
|
|
||||||
self._onActiveMachineChanged()
|
|
||||||
|
|
||||||
Application.getInstance().getController().getScene().sceneChanged.connect(self._onSceneChanged)
|
|
||||||
|
|
||||||
self._backend = Application.getInstance().getBackend()
|
self._backend = Application.getInstance().getBackend()
|
||||||
if self._backend:
|
if self._backend:
|
||||||
self._backend.printDurationMessage.connect(self._onPrintDurationMessage)
|
self._backend.printDurationMessage.connect(self._onPrintDurationMessage)
|
||||||
self._backend.slicingStarted.connect(self._onSlicingStarted)
|
|
||||||
self._backend.slicingCancelled.connect(self._onSlicingCancelled)
|
|
||||||
|
|
||||||
minimumPrintTimeChanged = pyqtSignal()
|
|
||||||
|
|
||||||
@pyqtProperty(Duration, notify = minimumPrintTimeChanged)
|
|
||||||
def minimumPrintTime(self):
|
|
||||||
return self._minimum_print_time
|
|
||||||
|
|
||||||
currentPrintTimeChanged = pyqtSignal()
|
currentPrintTimeChanged = pyqtSignal()
|
||||||
|
|
||||||
@ -89,145 +54,18 @@ class PrintInformation(QObject):
|
|||||||
def currentPrintTime(self):
|
def currentPrintTime(self):
|
||||||
return self._current_print_time
|
return self._current_print_time
|
||||||
|
|
||||||
maximumPrintTimeChanged = pyqtSignal()
|
|
||||||
|
|
||||||
@pyqtProperty(Duration, notify = maximumPrintTimeChanged)
|
|
||||||
def maximumPrintTime(self):
|
|
||||||
return self._maximum_print_time
|
|
||||||
|
|
||||||
materialAmountChanged = pyqtSignal()
|
materialAmountChanged = pyqtSignal()
|
||||||
|
|
||||||
@pyqtProperty(float, notify = materialAmountChanged)
|
@pyqtProperty(float, notify = materialAmountChanged)
|
||||||
def materialAmount(self):
|
def materialAmount(self):
|
||||||
return self._material_amount
|
return self._material_amount
|
||||||
|
|
||||||
timeQualityValueChanged = pyqtSignal()
|
|
||||||
|
|
||||||
@pyqtProperty(int, notify = timeQualityValueChanged)
|
|
||||||
def timeQualityValue(self):
|
|
||||||
return self._time_quality_value
|
|
||||||
|
|
||||||
def setEnabled(self, enabled):
|
|
||||||
if enabled != self._enabled:
|
|
||||||
self._enabled = enabled
|
|
||||||
|
|
||||||
if self._enabled:
|
|
||||||
self._updateTimeQualitySettings()
|
|
||||||
self._onSlicingStarted()
|
|
||||||
|
|
||||||
self.enabledChanged.emit()
|
|
||||||
|
|
||||||
enabledChanged = pyqtSignal()
|
|
||||||
@pyqtProperty(bool, fset = setEnabled, notify = enabledChanged)
|
|
||||||
def enabled(self):
|
|
||||||
return self._enabled
|
|
||||||
|
|
||||||
@pyqtSlot(int)
|
|
||||||
def setTimeQualityValue(self, value):
|
|
||||||
if value != self._time_quality_value:
|
|
||||||
self._time_quality_value = value
|
|
||||||
self.timeQualityValueChanged.emit()
|
|
||||||
|
|
||||||
self._time_quality_changed_timer.start()
|
|
||||||
|
|
||||||
def _onSlicingStarted(self):
|
|
||||||
if self._slice_pass is None:
|
|
||||||
self._slice_pass = self.SlicePass.CurrentSettings
|
|
||||||
|
|
||||||
if self._slice_reason is None:
|
|
||||||
self._slice_reason = self.SliceReason.Other
|
|
||||||
|
|
||||||
if self._slice_pass == self.SlicePass.CurrentSettings and self._slice_reason != self.SliceReason.SettingChanged:
|
|
||||||
self._minimum_print_time.setDuration(-1)
|
|
||||||
self.minimumPrintTimeChanged.emit()
|
|
||||||
self._maximum_print_time.setDuration(-1)
|
|
||||||
self.maximumPrintTimeChanged.emit()
|
|
||||||
|
|
||||||
def _onPrintDurationMessage(self, time, amount):
|
def _onPrintDurationMessage(self, time, amount):
|
||||||
if self._slice_pass == self.SlicePass.CurrentSettings:
|
#if self._slice_pass == self.SlicePass.CurrentSettings:
|
||||||
self._current_print_time.setDuration(time)
|
self._current_print_time.setDuration(time)
|
||||||
self.currentPrintTimeChanged.emit()
|
self.currentPrintTimeChanged.emit()
|
||||||
|
|
||||||
# Material amount is sent as an amount of mm^3, so calculate length from that
|
# Material amount is sent as an amount of mm^3, so calculate length from that
|
||||||
r = self._current_settings.getSettingValueByKey("material_diameter") / 2
|
r = Application.getInstance().getMachineManager().getActiveProfile().getSettingValue("material_diameter") / 2
|
||||||
self._material_amount = round((amount / (math.pi * r ** 2)) / 1000, 2)
|
self._material_amount = round((amount / (math.pi * r ** 2)) / 1000, 2)
|
||||||
self.materialAmountChanged.emit()
|
self.materialAmountChanged.emit()
|
||||||
|
|
||||||
if not self._enabled:
|
|
||||||
return
|
|
||||||
|
|
||||||
if self._slice_reason != self.SliceReason.SettingChanged or not self._minimum_print_time.valid or not self._maximum_print_time.valid:
|
|
||||||
self._slice_pass = self.SlicePass.LowQualitySettings
|
|
||||||
self._backend.slice(settings = self._low_quality_settings, save_gcode = False, save_polygons = False, force_restart = False, report_progress = False)
|
|
||||||
else:
|
|
||||||
self._slice_pass = None
|
|
||||||
self._slice_reason = None
|
|
||||||
elif self._slice_pass == self.SlicePass.LowQualitySettings:
|
|
||||||
self._minimum_print_time.setDuration(time)
|
|
||||||
self.minimumPrintTimeChanged.emit()
|
|
||||||
|
|
||||||
self._slice_pass = self.SlicePass.HighQualitySettings
|
|
||||||
self._backend.slice(settings = self._high_quality_settings, save_gcode = False, save_polygons = False, force_restart = False, report_progress = False)
|
|
||||||
elif self._slice_pass == self.SlicePass.HighQualitySettings:
|
|
||||||
self._maximum_print_time.setDuration(time)
|
|
||||||
self.maximumPrintTimeChanged.emit()
|
|
||||||
|
|
||||||
self._slice_pass = None
|
|
||||||
self._slice_reason = None
|
|
||||||
|
|
||||||
def _onActiveMachineChanged(self):
|
|
||||||
if self._current_settings:
|
|
||||||
self._current_settings.settingChanged.disconnect(self._onSettingChanged)
|
|
||||||
|
|
||||||
self._current_settings = Application.getInstance().getActiveMachine()
|
|
||||||
|
|
||||||
if self._current_settings:
|
|
||||||
self._current_settings.settingChanged.connect(self._onSettingChanged)
|
|
||||||
self._low_quality_settings = None
|
|
||||||
self._high_quality_settings = None
|
|
||||||
self._updateTimeQualitySettings()
|
|
||||||
|
|
||||||
self._slice_reason = self.SliceReason.ActiveMachineChanged
|
|
||||||
|
|
||||||
def _updateTimeQualitySettings(self):
|
|
||||||
if not self._current_settings or not self._enabled:
|
|
||||||
return
|
|
||||||
|
|
||||||
if not self._low_quality_settings:
|
|
||||||
self._low_quality_settings = MachineSettings()
|
|
||||||
self._low_quality_settings.loadSettingsFromFile(Resources.getPath(Resources.SettingsLocation, self._current_settings.getTypeID() + ".json"))
|
|
||||||
self._low_quality_settings.loadValuesFromFile(Resources.getPath(Resources.SettingsLocation, "profiles", "low_quality.conf"))
|
|
||||||
|
|
||||||
if not self._high_quality_settings:
|
|
||||||
self._high_quality_settings = MachineSettings()
|
|
||||||
self._high_quality_settings.loadSettingsFromFile(Resources.getPath(Resources.SettingsLocation, self._current_settings.getTypeID() + ".json"))
|
|
||||||
self._high_quality_settings.loadValuesFromFile(Resources.getPath(Resources.SettingsLocation, "profiles", "high_quality.conf"))
|
|
||||||
|
|
||||||
for key, options in self._interpolation_settings.items():
|
|
||||||
minimum_value = None
|
|
||||||
if options["minimum"] == "low":
|
|
||||||
minimum_value = self._low_quality_settings.getSettingValueByKey(key)
|
|
||||||
elif options["minimum"] == "high":
|
|
||||||
minimum_value = self._high_quality_settings.getSettingValueByKey(key)
|
|
||||||
else:
|
|
||||||
continue
|
|
||||||
|
|
||||||
maximum_value = None
|
|
||||||
if options["maximum"] == "low":
|
|
||||||
maximum_value = self._low_quality_settings.getSettingValueByKey(key)
|
|
||||||
elif options["maximum"] == "high":
|
|
||||||
maximum_value = self._high_quality_settings.getSettingValueByKey(key)
|
|
||||||
else:
|
|
||||||
continue
|
|
||||||
|
|
||||||
setting_value = round(minimum_value + (maximum_value - minimum_value) * (self._time_quality_value / 100), options["precision"])
|
|
||||||
self._current_settings.setSettingValueByKey(key, setting_value)
|
|
||||||
|
|
||||||
def _onSceneChanged(self, source):
|
|
||||||
self._slice_reason = self.SliceReason.SceneChanged
|
|
||||||
|
|
||||||
def _onSettingChanged(self, source):
|
|
||||||
self._slice_reason = self.SliceReason.SettingChanged
|
|
||||||
|
|
||||||
def _onSlicingCancelled(self):
|
|
||||||
self._slice_pass = None
|
|
||||||
|
15
cura_app.py
@ -3,12 +3,15 @@
|
|||||||
# 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.
|
||||||
|
|
||||||
try:
|
import sys
|
||||||
import cura.CuraApplication
|
|
||||||
|
|
||||||
app = cura.CuraApplication.CuraApplication.getInstance()
|
def exceptHook(type, value, traceback):
|
||||||
app.run()
|
|
||||||
except Exception as e:
|
|
||||||
import cura.CrashHandler
|
import cura.CrashHandler
|
||||||
cura.CrashHandler.show()
|
cura.CrashHandler.show(type, value, traceback)
|
||||||
|
|
||||||
|
sys.excepthook = exceptHook
|
||||||
|
|
||||||
|
import cura.CuraApplication
|
||||||
|
|
||||||
|
app = cura.CuraApplication.CuraApplication.getInstance()
|
||||||
|
app.run()
|
||||||
|
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 625 B After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 15 KiB |
BIN
icons/cura.icns
BIN
icons/cura.ico
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 361 KiB |
@ -1,5 +1,5 @@
|
|||||||
!ifndef VERSION
|
!ifndef VERSION
|
||||||
!define VERSION '15.05.97'
|
!define VERSION '15.09.80'
|
||||||
!endif
|
!endif
|
||||||
|
|
||||||
; The name of the installer
|
; The name of the installer
|
||||||
@ -45,7 +45,7 @@ SetCompressor /SOLID lzma
|
|||||||
!define MUI_FINISHPAGE_RUN_FUNCTION "LaunchLink"
|
!define MUI_FINISHPAGE_RUN_FUNCTION "LaunchLink"
|
||||||
|
|
||||||
;Add an option to show release notes
|
;Add an option to show release notes
|
||||||
!define MUI_FINISHPAGE_SHOWREADME "$INSTDIR\release_notes.txt"
|
!define MUI_FINISHPAGE_SHOWREADME "$INSTDIR\plugins\ChangeLogPlugin\changelog.txt"
|
||||||
|
|
||||||
; Pages
|
; Pages
|
||||||
;!insertmacro MUI_PAGE_WELCOME
|
;!insertmacro MUI_PAGE_WELCOME
|
||||||
@ -111,24 +111,24 @@ Section "Install Visual Studio 2010 Redistributable"
|
|||||||
|
|
||||||
SectionEnd
|
SectionEnd
|
||||||
|
|
||||||
;Section "Install Arduino Drivers"
|
Section "Install Arduino Drivers"
|
||||||
; ; Set output path to the driver directory.
|
; Set output path to the driver directory.
|
||||||
; SetOutPath "$INSTDIR\drivers\"
|
SetOutPath "$INSTDIR\drivers\"
|
||||||
; File /r "drivers\"
|
File /r "drivers\"
|
||||||
;
|
|
||||||
; ${If} ${RunningX64}
|
${If} ${RunningX64}
|
||||||
; IfSilent +2
|
IfSilent +2
|
||||||
; ExecWait '"$INSTDIR\drivers\dpinst64.exe" /lm'
|
ExecWait '"$INSTDIR\drivers\dpinst64.exe" /lm'
|
||||||
; ${Else}
|
${Else}
|
||||||
; IfSilent +2
|
IfSilent +2
|
||||||
; ExecWait '"$INSTDIR\drivers\dpinst32.exe" /lm'
|
ExecWait '"$INSTDIR\drivers\dpinst32.exe" /lm'
|
||||||
; ${EndIf}
|
${EndIf}
|
||||||
;SectionEnd
|
SectionEnd
|
||||||
|
|
||||||
Section "Open STL files with Cura"
|
Section "Open STL files with Cura"
|
||||||
WriteRegStr HKCR .stl "" "Cura STL model file"
|
WriteRegStr HKCR .stl "" "Cura STL model file"
|
||||||
DeleteRegValue HKCR .stl "Content Type"
|
DeleteRegValue HKCR .stl "Content Type"
|
||||||
WriteRegStr HKCR "Cura STL model file\DefaultIcon" "" "$INSTDIR\resources\stl.ico,0"
|
WriteRegStr HKCR "Cura STL model file\DefaultIcon" "" "$INSTDIR\Cura.exe,0"
|
||||||
WriteRegStr HKCR "Cura STL model file\shell" "" "open"
|
WriteRegStr HKCR "Cura STL model file\shell" "" "open"
|
||||||
WriteRegStr HKCR "Cura STL model file\shell\open\command" "" '"$INSTDIR\Cura.exe" "%1"'
|
WriteRegStr HKCR "Cura STL model file\shell\open\command" "" '"$INSTDIR\Cura.exe" "%1"'
|
||||||
SectionEnd
|
SectionEnd
|
||||||
@ -136,7 +136,7 @@ SectionEnd
|
|||||||
Section /o "Open OBJ files with Cura"
|
Section /o "Open OBJ files with Cura"
|
||||||
WriteRegStr HKCR .obj "" "Cura OBJ model file"
|
WriteRegStr HKCR .obj "" "Cura OBJ model file"
|
||||||
DeleteRegValue HKCR .obj "Content Type"
|
DeleteRegValue HKCR .obj "Content Type"
|
||||||
WriteRegStr HKCR "Cura OBJ model file\DefaultIcon" "" "$INSTDIR\resources\stl.ico,0"
|
WriteRegStr HKCR "Cura OBJ model file\DefaultIcon" "" "$INSTDIR\Cura.exe,0"
|
||||||
WriteRegStr HKCR "Cura OBJ model file\shell" "" "open"
|
WriteRegStr HKCR "Cura OBJ model file\shell" "" "open"
|
||||||
WriteRegStr HKCR "Cura OBJ model file\shell\open\command" "" '"$INSTDIR\Cura.exe" "%1"'
|
WriteRegStr HKCR "Cura OBJ model file\shell\open\command" "" '"$INSTDIR\Cura.exe" "%1"'
|
||||||
SectionEnd
|
SectionEnd
|
||||||
|
124
plugins/3MFReader/ThreeMFReader.py
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
# Copyright (c) 2015 Ultimaker B.V.
|
||||||
|
# Cura is released under the terms of the AGPLv3 or higher.
|
||||||
|
|
||||||
|
from UM.Mesh.MeshReader import MeshReader
|
||||||
|
from UM.Mesh.MeshData import MeshData
|
||||||
|
from UM.Logger import Logger
|
||||||
|
from UM.Math.Matrix import Matrix
|
||||||
|
from UM.Math.Vector import Vector
|
||||||
|
from UM.Scene.SceneNode import SceneNode
|
||||||
|
from UM.Scene.GroupDecorator import GroupDecorator
|
||||||
|
from UM.Math.Quaternion import Quaternion
|
||||||
|
|
||||||
|
|
||||||
|
import os
|
||||||
|
import struct
|
||||||
|
import math
|
||||||
|
from os import listdir
|
||||||
|
import zipfile
|
||||||
|
|
||||||
|
import xml.etree.ElementTree as ET
|
||||||
|
|
||||||
|
## Base implementation for reading 3MF files. Has no support for textures. Only loads meshes!
|
||||||
|
class ThreeMFReader(MeshReader):
|
||||||
|
def __init__(self):
|
||||||
|
super(ThreeMFReader, self).__init__()
|
||||||
|
self._supported_extension = ".3mf"
|
||||||
|
|
||||||
|
self._namespaces = {
|
||||||
|
"3mf": "http://schemas.microsoft.com/3dmanufacturing/core/2015/02",
|
||||||
|
"cura": "http://software.ultimaker.com/xml/cura/3mf/2015/10"
|
||||||
|
}
|
||||||
|
|
||||||
|
def read(self, file_name):
|
||||||
|
result = None
|
||||||
|
extension = os.path.splitext(file_name)[1]
|
||||||
|
if extension.lower() == self._supported_extension:
|
||||||
|
result = SceneNode()
|
||||||
|
# The base object of 3mf is a zipped archive.
|
||||||
|
archive = zipfile.ZipFile(file_name, 'r')
|
||||||
|
try:
|
||||||
|
root = ET.parse(archive.open("3D/3dmodel.model"))
|
||||||
|
|
||||||
|
# There can be multiple objects, try to load all of them.
|
||||||
|
objects = root.findall("./3mf:resources/3mf:object", self._namespaces)
|
||||||
|
for object in objects:
|
||||||
|
mesh = MeshData()
|
||||||
|
node = SceneNode()
|
||||||
|
vertex_list = []
|
||||||
|
#for vertex in object.mesh.vertices.vertex:
|
||||||
|
for vertex in object.findall(".//3mf:vertex", self._namespaces):
|
||||||
|
vertex_list.append([vertex.get("x"), vertex.get("y"), vertex.get("z")])
|
||||||
|
|
||||||
|
triangles = object.findall(".//3mf:triangle", self._namespaces)
|
||||||
|
|
||||||
|
mesh.reserveFaceCount(len(triangles))
|
||||||
|
|
||||||
|
#for triangle in object.mesh.triangles.triangle:
|
||||||
|
for triangle in triangles:
|
||||||
|
v1 = int(triangle.get("v1"))
|
||||||
|
v2 = int(triangle.get("v2"))
|
||||||
|
v3 = int(triangle.get("v3"))
|
||||||
|
mesh.addFace(vertex_list[v1][0],vertex_list[v1][1],vertex_list[v1][2],vertex_list[v2][0],vertex_list[v2][1],vertex_list[v2][2],vertex_list[v3][0],vertex_list[v3][1],vertex_list[v3][2])
|
||||||
|
#TODO: We currently do not check for normals and simply recalculate them.
|
||||||
|
mesh.calculateNormals()
|
||||||
|
node.setMeshData(mesh)
|
||||||
|
node.setSelectable(True)
|
||||||
|
|
||||||
|
transformation = root.findall("./3mf:build/3mf:item[@objectid='{0}']".format(object.get("id")), self._namespaces)
|
||||||
|
if transformation:
|
||||||
|
transformation = transformation[0]
|
||||||
|
|
||||||
|
if transformation.get("transform"):
|
||||||
|
splitted_transformation = transformation.get("transform").split()
|
||||||
|
## Transformation is saved as:
|
||||||
|
## M00 M01 M02 0.0
|
||||||
|
## M10 M11 M12 0.0
|
||||||
|
## M20 M21 M22 0.0
|
||||||
|
## M30 M31 M32 1.0
|
||||||
|
## We switch the row & cols as that is how everyone else uses matrices!
|
||||||
|
temp_mat = Matrix()
|
||||||
|
# Rotation & Scale
|
||||||
|
temp_mat._data[0,0] = splitted_transformation[0]
|
||||||
|
temp_mat._data[1,0] = splitted_transformation[1]
|
||||||
|
temp_mat._data[2,0] = splitted_transformation[2]
|
||||||
|
temp_mat._data[0,1] = splitted_transformation[3]
|
||||||
|
temp_mat._data[1,1] = splitted_transformation[4]
|
||||||
|
temp_mat._data[2,1] = splitted_transformation[5]
|
||||||
|
temp_mat._data[0,2] = splitted_transformation[6]
|
||||||
|
temp_mat._data[1,2] = splitted_transformation[7]
|
||||||
|
temp_mat._data[2,2] = splitted_transformation[8]
|
||||||
|
|
||||||
|
# Translation
|
||||||
|
temp_mat._data[0,3] = splitted_transformation[9]
|
||||||
|
temp_mat._data[1,3] = splitted_transformation[10]
|
||||||
|
temp_mat._data[2,3] = splitted_transformation[11]
|
||||||
|
|
||||||
|
node.setPosition(Vector(temp_mat.at(0,3), temp_mat.at(1,3), temp_mat.at(2,3)))
|
||||||
|
|
||||||
|
temp_quaternion = Quaternion()
|
||||||
|
temp_quaternion.setByMatrix(temp_mat)
|
||||||
|
node.setOrientation(temp_quaternion)
|
||||||
|
|
||||||
|
# Magical scale extraction
|
||||||
|
S2 = temp_mat.getTransposed().multiply(temp_mat)
|
||||||
|
scale_x = math.sqrt(S2.at(0,0))
|
||||||
|
scale_y = math.sqrt(S2.at(1,1))
|
||||||
|
scale_z = math.sqrt(S2.at(2,2))
|
||||||
|
node.setScale(Vector(scale_x,scale_y,scale_z))
|
||||||
|
|
||||||
|
# We use a different coordinate frame, so rotate.
|
||||||
|
rotation = Quaternion.fromAngleAxis(-0.5 * math.pi, Vector(1,0,0))
|
||||||
|
node.rotate(rotation)
|
||||||
|
result.addChild(node)
|
||||||
|
|
||||||
|
#If there is more then one object, group them.
|
||||||
|
try:
|
||||||
|
if len(objects) > 1:
|
||||||
|
group_decorator = GroupDecorator()
|
||||||
|
result.addDecorator(group_decorator)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
except Exception as e:
|
||||||
|
Logger.log("e" ,"exception occured in 3mf reader: %s" , e)
|
||||||
|
return result
|
25
plugins/3MFReader/__init__.py
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
# Copyright (c) 2015 Ultimaker B.V.
|
||||||
|
# Cura is released under the terms of the AGPLv3 or higher.
|
||||||
|
|
||||||
|
from UM.i18n import i18nCatalog
|
||||||
|
catalog = i18nCatalog("cura")
|
||||||
|
|
||||||
|
from . import ThreeMFReader
|
||||||
|
|
||||||
|
def getMetaData():
|
||||||
|
return {
|
||||||
|
"plugin": {
|
||||||
|
"name": catalog.i18nc("@label", "3MF Reader"),
|
||||||
|
"author": "Ultimaker",
|
||||||
|
"version": "1.0",
|
||||||
|
"description": catalog.i18nc("@info:whatsthis", "Provides support for reading 3MF files."),
|
||||||
|
"api": 2
|
||||||
|
},
|
||||||
|
"mesh_reader": {
|
||||||
|
"extension": "3mf",
|
||||||
|
"description": catalog.i18nc("@item:inlistbox", "3MF File")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def register(app):
|
||||||
|
return { "mesh_reader": ThreeMFReader.ThreeMFReader() }
|
99
plugins/ChangeLogPlugin/ChangeLog.py
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
# Copyright (c) 2015 Ultimaker B.V.
|
||||||
|
# Cura is released under the terms of the AGPLv3 or higher.
|
||||||
|
|
||||||
|
from UM.i18n import i18nCatalog
|
||||||
|
from UM.Extension import Extension
|
||||||
|
from UM.Preferences import Preferences
|
||||||
|
from UM.Application import Application
|
||||||
|
from UM.PluginRegistry import PluginRegistry
|
||||||
|
from UM.Version import Version
|
||||||
|
|
||||||
|
from PyQt5.QtQuick import QQuickView
|
||||||
|
from PyQt5.QtQml import QQmlComponent, QQmlContext
|
||||||
|
from PyQt5.QtCore import QUrl, pyqtSlot, QObject
|
||||||
|
|
||||||
|
import os.path
|
||||||
|
import collections
|
||||||
|
|
||||||
|
catalog = i18nCatalog("cura")
|
||||||
|
|
||||||
|
class ChangeLog(Extension, QObject,):
|
||||||
|
def __init__(self, parent = None):
|
||||||
|
QObject.__init__(self, parent)
|
||||||
|
Extension.__init__(self)
|
||||||
|
self._changelog_window = None
|
||||||
|
self._changelog_context = None
|
||||||
|
version_string = Application.getInstance().getVersion()
|
||||||
|
if version_string is not "master":
|
||||||
|
self._version = Version(version_string)
|
||||||
|
else:
|
||||||
|
self._version = None
|
||||||
|
self._change_logs = None
|
||||||
|
Application.getInstance().engineCreatedSignal.connect(self._onEngineCreated)
|
||||||
|
Preferences.getInstance().addPreference("general/latest_version_changelog_shown", "15.05.90") #First version of CURA with uranium
|
||||||
|
#self.showChangelog()
|
||||||
|
|
||||||
|
def getChangeLogs(self):
|
||||||
|
if not self._change_logs:
|
||||||
|
self.loadChangeLogs()
|
||||||
|
return self._change_logs
|
||||||
|
|
||||||
|
@pyqtSlot(result = str)
|
||||||
|
def getChangeLogString(self):
|
||||||
|
logs = self.getChangeLogs()
|
||||||
|
latest_version = Version(Preferences.getInstance().getValue("general/latest_version_changelog_shown"))
|
||||||
|
result = ""
|
||||||
|
for version in logs:
|
||||||
|
result += "<h1>" + str(version) + "</h1><br>"
|
||||||
|
result += ""
|
||||||
|
for change in logs[version]:
|
||||||
|
result += "<b>" + str(change) + "</b><br>"
|
||||||
|
for line in logs[version][change]:
|
||||||
|
result += str(line) + "<br>"
|
||||||
|
result += "<br>"
|
||||||
|
|
||||||
|
pass
|
||||||
|
return result
|
||||||
|
|
||||||
|
def loadChangeLogs(self):
|
||||||
|
self._change_logs = collections.OrderedDict()
|
||||||
|
with open(os.path.join(PluginRegistry.getInstance().getPluginPath("ChangeLogPlugin"), "ChangeLog.txt"), 'r',-1, "utf-8") as f:
|
||||||
|
open_version = None
|
||||||
|
open_header = None
|
||||||
|
for line in f:
|
||||||
|
line = line.replace("\n","")
|
||||||
|
if "[" in line and "]" in line:
|
||||||
|
line = line.replace("[","")
|
||||||
|
line = line.replace("]","")
|
||||||
|
open_version = Version(line)
|
||||||
|
self._change_logs[Version(line)] = collections.OrderedDict()
|
||||||
|
elif line.startswith("*"):
|
||||||
|
open_header = line.replace("*","")
|
||||||
|
self._change_logs[open_version][open_header] = []
|
||||||
|
else:
|
||||||
|
if line != "":
|
||||||
|
self._change_logs[open_version][open_header].append(line)
|
||||||
|
|
||||||
|
def _onEngineCreated(self):
|
||||||
|
if not self._version:
|
||||||
|
return #We're on dev branch.
|
||||||
|
if self._version > Preferences.getInstance().getValue("general/latest_version_changelog_shown"):
|
||||||
|
self.showChangelog()
|
||||||
|
|
||||||
|
def showChangelog(self):
|
||||||
|
if not self._changelog_window:
|
||||||
|
self.createChangelogWindow()
|
||||||
|
self._changelog_window.show()
|
||||||
|
Preferences.getInstance().setValue("general/latest_version_changelog_shown", Application.getInstance().getVersion())
|
||||||
|
|
||||||
|
def hideChangelog(self):
|
||||||
|
if self._changelog_window:
|
||||||
|
self._changelog_window.hide()
|
||||||
|
|
||||||
|
def createChangelogWindow(self):
|
||||||
|
path = QUrl.fromLocalFile(os.path.join(PluginRegistry.getInstance().getPluginPath("ChangeLogPlugin"), "ChangeLog.qml"))
|
||||||
|
component = QQmlComponent(Application.getInstance()._engine, path)
|
||||||
|
self._changelog_context = QQmlContext(Application.getInstance()._engine.rootContext())
|
||||||
|
self._changelog_context.setContextProperty("manager", self)
|
||||||
|
self._changelog_window = component.create(self._changelog_context)
|
||||||
|
#print(self._changelog_window)
|
36
plugins/ChangeLogPlugin/ChangeLog.qml
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
// Copyright (c) 2015 Ultimaker B.V.
|
||||||
|
// Cura is released under the terms of the AGPLv3 or higher.
|
||||||
|
|
||||||
|
import QtQuick 2.1
|
||||||
|
import QtQuick.Controls 1.1
|
||||||
|
import QtQuick.Layouts 1.1
|
||||||
|
import QtQuick.Window 2.1
|
||||||
|
|
||||||
|
import UM 1.1 as UM
|
||||||
|
|
||||||
|
UM.Dialog
|
||||||
|
{
|
||||||
|
id: base
|
||||||
|
width: 300 * Screen.devicePixelRatio;
|
||||||
|
height: 500 * Screen.devicePixelRatio;
|
||||||
|
title: "Changelog"
|
||||||
|
|
||||||
|
ScrollView
|
||||||
|
{
|
||||||
|
width: parent.width
|
||||||
|
height: parent.height - 25
|
||||||
|
Text
|
||||||
|
{
|
||||||
|
text: manager.getChangeLogString()
|
||||||
|
width:base.width - 35
|
||||||
|
wrapMode: Text.Wrap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Button
|
||||||
|
{
|
||||||
|
anchors.bottom:parent.bottom
|
||||||
|
text: "close"
|
||||||
|
onClicked: base.hide()
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
}
|
||||||
|
}
|
44
plugins/ChangeLogPlugin/ChangeLog.txt
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
[15.10.0]
|
||||||
|
*All at Once/One at a Time
|
||||||
|
Cura’s default mode is set to All At Once. You can print multiple objects faster with the option print objects One At A Time. This can be changed in Advanced Settings. Please note that in One At A Time mode, grouped objects will still be printed as a single object.
|
||||||
|
|
||||||
|
*Setting Profiles
|
||||||
|
Now you can create preferred setting favourites and share them with others.
|
||||||
|
|
||||||
|
*Post-Processing Plugin
|
||||||
|
This plugin supports post-processing on the GCode generated by the engine – allowing for custom scripts. For example, Pause At Height and Tweak At Z.
|
||||||
|
|
||||||
|
*Support for Bed Levelling and other wizards
|
||||||
|
We have restored the Bed Levelling function and several other wizards that were previously available for the Ultimaker Original. Additionally, these are ready to be used with machines from other vendors (BQ, Rep Rap neo).
|
||||||
|
|
||||||
|
*Third-Party Printer Profiles
|
||||||
|
We received printer profiles for third-party vendors (BQ, Rep Rap neo) from the community (thanks guys!). These have been included in this release.
|
||||||
|
|
||||||
|
*3MF File Loading Support (New)
|
||||||
|
We’re happy to report we now support loading 3MF files. This is a new file format similar to AMF, but freely available.
|
||||||
|
|
||||||
|
*Output Device API for Developers (New)
|
||||||
|
The Storage Device API has now been replaced with the Output Device API for saving files. It’s designed to make it easier for anyone that wants to write a plugin giving them some form of output device, whether it’s a printer or a web service.
|
||||||
|
|
||||||
|
*Improved Cut-Off Object Bottom (New)
|
||||||
|
We’ve added a feature than allows you to move objects below the build plate. You can either correct a model with a rough bottom, or print only a part of an object. Please note that the implementation greatly differs from the old one where it was a setting.
|
||||||
|
|
||||||
|
*Improved File Saving (new)
|
||||||
|
We’re happy to report that the way file saving is handled has received a huge overhaul. Now the default action is to save everything on the build plate to a file.
|
||||||
|
|
||||||
|
*Select Multiple Objects (New)
|
||||||
|
You now have the freedom to select and manipulate multiple objects at the same time.
|
||||||
|
|
||||||
|
*Grouping (New)
|
||||||
|
You can now group objects together to make it easier to manipulate multiple objects.
|
||||||
|
|
||||||
|
*Per-Object Settings (New)
|
||||||
|
You can now select different profiles for different objects and in advance mode override individual settings.
|
||||||
|
|
||||||
|
*64-bit Windows Builds (New)
|
||||||
|
Cura now allows 64-bit Windows builds in addition to the 32-bit builds. For users running the 64-bit version of Windows, you can now load models in more detail.
|
||||||
|
|
||||||
|
*Fuzzy skin mode (New)
|
||||||
|
A new engine feature that enables objects to be printed as if they have a fuzzy skin.
|
||||||
|
|
||||||
|
*Z-seam alignment (New)
|
21
plugins/ChangeLogPlugin/__init__.py
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
# Copyright (c) 2015 Ultimaker B.V.
|
||||||
|
# Cura is released under the terms of the AGPLv3 or higher.
|
||||||
|
|
||||||
|
from . import ChangeLog
|
||||||
|
|
||||||
|
from UM.i18n import i18nCatalog
|
||||||
|
catalog = i18nCatalog("cura")
|
||||||
|
|
||||||
|
def getMetaData():
|
||||||
|
return {
|
||||||
|
"plugin": {
|
||||||
|
"name": catalog.i18nc("@label", "Change Log"),
|
||||||
|
"author": "Ultimaker",
|
||||||
|
"version": "1.0",
|
||||||
|
"description": catalog.i18nc("@info:whatsthis", "Shows changes since latest checked version"),
|
||||||
|
"api": 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def register(app):
|
||||||
|
return {"extension": ChangeLog.ChangeLog()}
|
@ -10,6 +10,8 @@ from UM.Math.Vector import Vector
|
|||||||
from UM.Signal import Signal
|
from UM.Signal import Signal
|
||||||
from UM.Logger import Logger
|
from UM.Logger import Logger
|
||||||
from UM.Resources import Resources
|
from UM.Resources import Resources
|
||||||
|
from UM.Settings.SettingOverrideDecorator import SettingOverrideDecorator
|
||||||
|
from UM.Message import Message
|
||||||
|
|
||||||
from cura.OneAtATimeIterator import OneAtATimeIterator
|
from cura.OneAtATimeIterator import OneAtATimeIterator
|
||||||
from . import Cura_pb2
|
from . import Cura_pb2
|
||||||
@ -22,6 +24,9 @@ import numpy
|
|||||||
|
|
||||||
from PyQt5.QtCore import QTimer
|
from PyQt5.QtCore import QTimer
|
||||||
|
|
||||||
|
from UM.i18n import i18nCatalog
|
||||||
|
catalog = i18nCatalog("cura")
|
||||||
|
|
||||||
class CuraEngineBackend(Backend):
|
class CuraEngineBackend(Backend):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
@ -44,9 +49,10 @@ class CuraEngineBackend(Backend):
|
|||||||
self._onActiveViewChanged()
|
self._onActiveViewChanged()
|
||||||
self._stored_layer_data = None
|
self._stored_layer_data = None
|
||||||
|
|
||||||
self._settings = None
|
|
||||||
Application.getInstance().activeMachineChanged.connect(self._onActiveMachineChanged)
|
self._profile = None
|
||||||
self._onActiveMachineChanged()
|
Application.getInstance().getMachineManager().activeProfileChanged.connect(self._onActiveProfileChanged)
|
||||||
|
self._onActiveProfileChanged()
|
||||||
|
|
||||||
self._change_timer = QTimer()
|
self._change_timer = QTimer()
|
||||||
self._change_timer.setInterval(500)
|
self._change_timer.setInterval(500)
|
||||||
@ -68,10 +74,15 @@ class CuraEngineBackend(Backend):
|
|||||||
|
|
||||||
self._enabled = True
|
self._enabled = True
|
||||||
|
|
||||||
|
self._message = None
|
||||||
|
|
||||||
self.backendConnected.connect(self._onBackendConnected)
|
self.backendConnected.connect(self._onBackendConnected)
|
||||||
|
|
||||||
|
## Get the command that is used to call the engine.
|
||||||
|
# This is usefull for debugging and used to actually start the engine
|
||||||
|
# \return list of commands and args / parameters.
|
||||||
def getEngineCommand(self):
|
def getEngineCommand(self):
|
||||||
return [Preferences.getInstance().getValue("backend/location"),"connect", "127.0.0.1:{0}".format(self._port), "-j", Resources.getPath(Resources.SettingsLocation, "fdmprinter.json"), "-vv"]
|
return [Preferences.getInstance().getValue("backend/location"), "connect", "127.0.0.1:{0}".format(self._port), "-j", Resources.getPath(Resources.MachineDefinitions, "fdmprinter.json"), "-vv"]
|
||||||
|
|
||||||
## Emitted when we get a message containing print duration and material amount. This also implies the slicing has finished.
|
## Emitted when we get a message containing print duration and material amount. This also implies the slicing has finished.
|
||||||
# \param time The amount of time the print will take.
|
# \param time The amount of time the print will take.
|
||||||
@ -112,9 +123,9 @@ class CuraEngineBackend(Backend):
|
|||||||
pass
|
pass
|
||||||
self.slicingCancelled.emit()
|
self.slicingCancelled.emit()
|
||||||
return
|
return
|
||||||
|
Logger.log("d", "Preparing to send slice data to engine.")
|
||||||
object_groups = []
|
object_groups = []
|
||||||
if self._settings.getSettingValueByKey("print_sequence") == "One at a time":
|
if self._profile.getSettingValue("print_sequence") == "one_at_a_time":
|
||||||
for node in OneAtATimeIterator(self._scene.getRoot()):
|
for node in OneAtATimeIterator(self._scene.getRoot()):
|
||||||
temp_list = []
|
temp_list = []
|
||||||
children = node.getAllChildren()
|
children = node.getAllChildren()
|
||||||
@ -130,6 +141,7 @@ class CuraEngineBackend(Backend):
|
|||||||
if not getattr(node, "_outside_buildarea", False):
|
if not getattr(node, "_outside_buildarea", False):
|
||||||
temp_list.append(node)
|
temp_list.append(node)
|
||||||
if len(temp_list) == 0:
|
if len(temp_list) == 0:
|
||||||
|
self.processingProgress.emit(0.0)
|
||||||
return
|
return
|
||||||
object_groups.append(temp_list)
|
object_groups.append(temp_list)
|
||||||
#for node in DepthFirstIterator(self._scene.getRoot()):
|
#for node in DepthFirstIterator(self._scene.getRoot()):
|
||||||
@ -138,19 +150,39 @@ class CuraEngineBackend(Backend):
|
|||||||
# objects.append(node)
|
# objects.append(node)
|
||||||
|
|
||||||
if len(object_groups) == 0:
|
if len(object_groups) == 0:
|
||||||
|
if self._message:
|
||||||
|
self._message.hide()
|
||||||
|
self._message = None
|
||||||
return #No point in slicing an empty build plate
|
return #No point in slicing an empty build plate
|
||||||
|
|
||||||
if kwargs.get("settings", self._settings).hasErrorValue():
|
if kwargs.get("profile", self._profile).hasErrorValue():
|
||||||
|
Logger.log('w', "Profile has error values. Aborting slicing")
|
||||||
|
if self._message:
|
||||||
|
self._message.hide()
|
||||||
|
self._message = None
|
||||||
|
self._message = Message(catalog.i18nc("@info:status", "Unable to slice. Please check your setting values for errors."))
|
||||||
|
self._message.show()
|
||||||
return #No slicing if we have error values since those are by definition illegal values.
|
return #No slicing if we have error values since those are by definition illegal values.
|
||||||
|
# Remove existing layer data (if any)
|
||||||
|
for node in DepthFirstIterator(self._scene.getRoot()):
|
||||||
|
if type(node) is SceneNode and node.getMeshData():
|
||||||
|
if node.callDecoration("getLayerData"):
|
||||||
|
Application.getInstance().getController().getScene().getRoot().removeChild(node)
|
||||||
|
break
|
||||||
|
Application.getInstance().getController().getScene().gcode_list = None
|
||||||
self._slicing = True
|
self._slicing = True
|
||||||
self.slicingStarted.emit()
|
self.slicingStarted.emit()
|
||||||
|
|
||||||
self._report_progress = kwargs.get("report_progress", True)
|
self._report_progress = kwargs.get("report_progress", True)
|
||||||
if self._report_progress:
|
if self._report_progress:
|
||||||
self.processingProgress.emit(0.0)
|
self.processingProgress.emit(0.0)
|
||||||
|
if not self._message:
|
||||||
|
self._message = Message(catalog.i18nc("@info:status", "Slicing..."), 0, False, -1)
|
||||||
|
self._message.show()
|
||||||
|
else:
|
||||||
|
self._message.setProgress(-1)
|
||||||
|
|
||||||
self._sendSettings(kwargs.get("settings", self._settings))
|
self._sendSettings(kwargs.get("profile", self._profile))
|
||||||
|
|
||||||
self._scene.acquireLock()
|
self._scene.acquireLock()
|
||||||
|
|
||||||
@ -178,7 +210,14 @@ class CuraEngineBackend(Backend):
|
|||||||
verts[:,1] *= -1
|
verts[:,1] *= -1
|
||||||
obj.vertices = verts.tostring()
|
obj.vertices = verts.tostring()
|
||||||
|
|
||||||
|
self._handlePerObjectSettings(object, obj)
|
||||||
|
|
||||||
|
# Hack to add per-object settings also to the "MeshGroup" in CuraEngine
|
||||||
|
# We really should come up with a better solution for this.
|
||||||
|
self._handlePerObjectSettings(group[0], group_message)
|
||||||
|
|
||||||
self._scene.releaseLock()
|
self._scene.releaseLock()
|
||||||
|
Logger.log("d", "Sending data to engine for slicing.")
|
||||||
self._socket.sendMessage(slice_message)
|
self._socket.sendMessage(slice_message)
|
||||||
|
|
||||||
def _onSceneChanged(self, source):
|
def _onSceneChanged(self, source):
|
||||||
@ -190,13 +229,13 @@ class CuraEngineBackend(Backend):
|
|||||||
|
|
||||||
self._onChanged()
|
self._onChanged()
|
||||||
|
|
||||||
def _onActiveMachineChanged(self):
|
def _onActiveProfileChanged(self):
|
||||||
if self._settings:
|
if self._profile:
|
||||||
self._settings.settingChanged.disconnect(self._onSettingChanged)
|
self._profile.settingValueChanged.disconnect(self._onSettingChanged)
|
||||||
|
|
||||||
self._settings = Application.getInstance().getActiveMachine()
|
self._profile = Application.getInstance().getMachineManager().getActiveProfile()
|
||||||
if self._settings:
|
if self._profile:
|
||||||
self._settings.settingChanged.connect(self._onSettingChanged)
|
self._profile.settingValueChanged.connect(self._onSettingChanged)
|
||||||
self._onChanged()
|
self._onChanged()
|
||||||
|
|
||||||
def _onSettingChanged(self, setting):
|
def _onSettingChanged(self, setting):
|
||||||
@ -214,6 +253,14 @@ class CuraEngineBackend(Backend):
|
|||||||
if message.amount >= 0.99:
|
if message.amount >= 0.99:
|
||||||
self._slicing = False
|
self._slicing = False
|
||||||
|
|
||||||
|
if self._message:
|
||||||
|
self._message.setProgress(100)
|
||||||
|
self._message.hide()
|
||||||
|
self._message = None
|
||||||
|
|
||||||
|
if self._message:
|
||||||
|
self._message.setProgress(round(message.amount * 100))
|
||||||
|
|
||||||
if self._report_progress:
|
if self._report_progress:
|
||||||
self.processingProgress.emit(message.amount)
|
self.processingProgress.emit(message.amount)
|
||||||
|
|
||||||
@ -241,18 +288,22 @@ class CuraEngineBackend(Backend):
|
|||||||
self._socket.registerMessageType(6, Cura_pb2.SettingList)
|
self._socket.registerMessageType(6, Cura_pb2.SettingList)
|
||||||
self._socket.registerMessageType(7, Cura_pb2.GCodePrefix)
|
self._socket.registerMessageType(7, Cura_pb2.GCodePrefix)
|
||||||
|
|
||||||
|
## Manually triggers a reslice
|
||||||
|
def forceSlice(self):
|
||||||
|
self._change_timer.start()
|
||||||
|
|
||||||
def _onChanged(self):
|
def _onChanged(self):
|
||||||
if not self._settings:
|
if not self._profile:
|
||||||
return
|
return
|
||||||
|
|
||||||
self._change_timer.start()
|
self._change_timer.start()
|
||||||
|
|
||||||
def _sendSettings(self, settings):
|
def _sendSettings(self, profile):
|
||||||
msg = Cura_pb2.SettingList()
|
msg = Cura_pb2.SettingList()
|
||||||
for setting in settings.getAllSettings(include_machine=True):
|
for key, value in profile.getAllSettingValues(include_machine = True).items():
|
||||||
s = msg.settings.add()
|
s = msg.settings.add()
|
||||||
s.name = setting.getKey()
|
s.name = key
|
||||||
s.value = str(setting.getValue()).encode("utf-8")
|
s.value = str(value).encode("utf-8")
|
||||||
|
|
||||||
self._socket.sendMessage(msg)
|
self._socket.sendMessage(msg)
|
||||||
|
|
||||||
@ -262,10 +313,10 @@ class CuraEngineBackend(Backend):
|
|||||||
self._restart = False
|
self._restart = False
|
||||||
|
|
||||||
def _onToolOperationStarted(self, tool):
|
def _onToolOperationStarted(self, tool):
|
||||||
self._enabled = False
|
self._enabled = False # Do not reslice when a tool is doing it's 'thing'
|
||||||
|
|
||||||
def _onToolOperationStopped(self, tool):
|
def _onToolOperationStopped(self, tool):
|
||||||
self._enabled = True
|
self._enabled = True # Tool stop, start listening for changes again.
|
||||||
self._onChanged()
|
self._onChanged()
|
||||||
|
|
||||||
def _onActiveViewChanged(self):
|
def _onActiveViewChanged(self):
|
||||||
@ -278,3 +329,20 @@ class CuraEngineBackend(Backend):
|
|||||||
job.start()
|
job.start()
|
||||||
else:
|
else:
|
||||||
self._layer_view_active = False
|
self._layer_view_active = False
|
||||||
|
|
||||||
|
def _handlePerObjectSettings(self, node, message):
|
||||||
|
profile = node.callDecoration("getProfile")
|
||||||
|
if profile:
|
||||||
|
for key, value in profile.getChangedSettingValues().items():
|
||||||
|
setting = message.settings.add()
|
||||||
|
setting.name = key
|
||||||
|
setting.value = str(value).encode()
|
||||||
|
|
||||||
|
object_settings = node.callDecoration("getAllSettingValues")
|
||||||
|
if not object_settings:
|
||||||
|
return
|
||||||
|
|
||||||
|
for key, value in object_settings.items():
|
||||||
|
setting = message.settings.add()
|
||||||
|
setting.name = key
|
||||||
|
setting.value = str(value).encode()
|
||||||
|
@ -18,7 +18,7 @@ _sym_db = _symbol_database.Default()
|
|||||||
DESCRIPTOR = _descriptor.FileDescriptor(
|
DESCRIPTOR = _descriptor.FileDescriptor(
|
||||||
name='Cura.proto',
|
name='Cura.proto',
|
||||||
package='cura.proto',
|
package='cura.proto',
|
||||||
serialized_pb=_b('\n\nCura.proto\x12\ncura.proto\"1\n\nObjectList\x12#\n\x07objects\x18\x01 \x03(\x0b\x32\x12.cura.proto.Object\"5\n\x05Slice\x12,\n\x0cobject_lists\x18\x01 \x03(\x0b\x32\x16.cura.proto.ObjectList\"o\n\x06Object\x12\n\n\x02id\x18\x01 \x01(\x03\x12\x10\n\x08vertices\x18\x02 \x01(\x0c\x12\x0f\n\x07normals\x18\x03 \x01(\x0c\x12\x0f\n\x07indices\x18\x04 \x01(\x0c\x12%\n\x08settings\x18\x05 \x03(\x0b\x32\x13.cura.proto.Setting\"\x1a\n\x08Progress\x12\x0e\n\x06\x61mount\x18\x01 \x01(\x02\"=\n\x10SlicedObjectList\x12)\n\x07objects\x18\x01 \x03(\x0b\x32\x18.cura.proto.SlicedObject\"=\n\x0cSlicedObject\x12\n\n\x02id\x18\x01 \x01(\x03\x12!\n\x06layers\x18\x02 \x03(\x0b\x32\x11.cura.proto.Layer\"]\n\x05Layer\x12\n\n\x02id\x18\x01 \x01(\x05\x12\x0e\n\x06height\x18\x02 \x01(\x02\x12\x11\n\tthickness\x18\x03 \x01(\x02\x12%\n\x08polygons\x18\x04 \x03(\x0b\x32\x13.cura.proto.Polygon\"\xe1\x01\n\x07Polygon\x12&\n\x04type\x18\x01 \x01(\x0e\x32\x18.cura.proto.Polygon.Type\x12\x0e\n\x06points\x18\x02 \x01(\x0c\x12\x12\n\nline_width\x18\x03 \x01(\x02\"\x89\x01\n\x04Type\x12\x0c\n\x08NoneType\x10\x00\x12\x0e\n\nInset0Type\x10\x01\x12\x0e\n\nInsetXType\x10\x02\x12\x0c\n\x08SkinType\x10\x03\x12\x0f\n\x0bSupportType\x10\x04\x12\r\n\tSkirtType\x10\x05\x12\x0e\n\nInfillType\x10\x06\x12\x15\n\x11SupportInfillType\x10\x07\"&\n\nGCodeLayer\x12\n\n\x02id\x18\x01 \x01(\x03\x12\x0c\n\x04\x64\x61ta\x18\x02 \x01(\x0c\"D\n\x0fObjectPrintTime\x12\n\n\x02id\x18\x01 \x01(\x03\x12\x0c\n\x04time\x18\x02 \x01(\x02\x12\x17\n\x0fmaterial_amount\x18\x03 \x01(\x02\"4\n\x0bSettingList\x12%\n\x08settings\x18\x01 \x03(\x0b\x32\x13.cura.proto.Setting\"&\n\x07Setting\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x0c\"\x1b\n\x0bGCodePrefix\x12\x0c\n\x04\x64\x61ta\x18\x02 \x01(\x0c\x62\x06proto3')
|
serialized_pb=_b('\n\nCura.proto\x12\ncura.proto\"X\n\nObjectList\x12#\n\x07objects\x18\x01 \x03(\x0b\x32\x12.cura.proto.Object\x12%\n\x08settings\x18\x02 \x03(\x0b\x32\x13.cura.proto.Setting\"5\n\x05Slice\x12,\n\x0cobject_lists\x18\x01 \x03(\x0b\x32\x16.cura.proto.ObjectList\"o\n\x06Object\x12\n\n\x02id\x18\x01 \x01(\x03\x12\x10\n\x08vertices\x18\x02 \x01(\x0c\x12\x0f\n\x07normals\x18\x03 \x01(\x0c\x12\x0f\n\x07indices\x18\x04 \x01(\x0c\x12%\n\x08settings\x18\x05 \x03(\x0b\x32\x13.cura.proto.Setting\"\x1a\n\x08Progress\x12\x0e\n\x06\x61mount\x18\x01 \x01(\x02\"=\n\x10SlicedObjectList\x12)\n\x07objects\x18\x01 \x03(\x0b\x32\x18.cura.proto.SlicedObject\"=\n\x0cSlicedObject\x12\n\n\x02id\x18\x01 \x01(\x03\x12!\n\x06layers\x18\x02 \x03(\x0b\x32\x11.cura.proto.Layer\"]\n\x05Layer\x12\n\n\x02id\x18\x01 \x01(\x05\x12\x0e\n\x06height\x18\x02 \x01(\x02\x12\x11\n\tthickness\x18\x03 \x01(\x02\x12%\n\x08polygons\x18\x04 \x03(\x0b\x32\x13.cura.proto.Polygon\"\xe1\x01\n\x07Polygon\x12&\n\x04type\x18\x01 \x01(\x0e\x32\x18.cura.proto.Polygon.Type\x12\x0e\n\x06points\x18\x02 \x01(\x0c\x12\x12\n\nline_width\x18\x03 \x01(\x02\"\x89\x01\n\x04Type\x12\x0c\n\x08NoneType\x10\x00\x12\x0e\n\nInset0Type\x10\x01\x12\x0e\n\nInsetXType\x10\x02\x12\x0c\n\x08SkinType\x10\x03\x12\x0f\n\x0bSupportType\x10\x04\x12\r\n\tSkirtType\x10\x05\x12\x0e\n\nInfillType\x10\x06\x12\x15\n\x11SupportInfillType\x10\x07\"&\n\nGCodeLayer\x12\n\n\x02id\x18\x01 \x01(\x03\x12\x0c\n\x04\x64\x61ta\x18\x02 \x01(\x0c\"D\n\x0fObjectPrintTime\x12\n\n\x02id\x18\x01 \x01(\x03\x12\x0c\n\x04time\x18\x02 \x01(\x02\x12\x17\n\x0fmaterial_amount\x18\x03 \x01(\x02\"4\n\x0bSettingList\x12%\n\x08settings\x18\x01 \x03(\x0b\x32\x13.cura.proto.Setting\"&\n\x07Setting\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x0c\"\x1b\n\x0bGCodePrefix\x12\x0c\n\x04\x64\x61ta\x18\x02 \x01(\x0c\x62\x06proto3')
|
||||||
)
|
)
|
||||||
_sym_db.RegisterFileDescriptor(DESCRIPTOR)
|
_sym_db.RegisterFileDescriptor(DESCRIPTOR)
|
||||||
|
|
||||||
@ -65,8 +65,8 @@ _POLYGON_TYPE = _descriptor.EnumDescriptor(
|
|||||||
],
|
],
|
||||||
containing_type=None,
|
containing_type=None,
|
||||||
options=None,
|
options=None,
|
||||||
serialized_start=583,
|
serialized_start=622,
|
||||||
serialized_end=720,
|
serialized_end=759,
|
||||||
)
|
)
|
||||||
_sym_db.RegisterEnumDescriptor(_POLYGON_TYPE)
|
_sym_db.RegisterEnumDescriptor(_POLYGON_TYPE)
|
||||||
|
|
||||||
@ -85,6 +85,13 @@ _OBJECTLIST = _descriptor.Descriptor(
|
|||||||
message_type=None, enum_type=None, containing_type=None,
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
is_extension=False, extension_scope=None,
|
is_extension=False, extension_scope=None,
|
||||||
options=None),
|
options=None),
|
||||||
|
_descriptor.FieldDescriptor(
|
||||||
|
name='settings', full_name='cura.proto.ObjectList.settings', index=1,
|
||||||
|
number=2, type=11, cpp_type=10, label=3,
|
||||||
|
has_default_value=False, default_value=[],
|
||||||
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
|
is_extension=False, extension_scope=None,
|
||||||
|
options=None),
|
||||||
],
|
],
|
||||||
extensions=[
|
extensions=[
|
||||||
],
|
],
|
||||||
@ -97,7 +104,7 @@ _OBJECTLIST = _descriptor.Descriptor(
|
|||||||
oneofs=[
|
oneofs=[
|
||||||
],
|
],
|
||||||
serialized_start=26,
|
serialized_start=26,
|
||||||
serialized_end=75,
|
serialized_end=114,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -126,8 +133,8 @@ _SLICE = _descriptor.Descriptor(
|
|||||||
extension_ranges=[],
|
extension_ranges=[],
|
||||||
oneofs=[
|
oneofs=[
|
||||||
],
|
],
|
||||||
serialized_start=77,
|
serialized_start=116,
|
||||||
serialized_end=130,
|
serialized_end=169,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -184,8 +191,8 @@ _OBJECT = _descriptor.Descriptor(
|
|||||||
extension_ranges=[],
|
extension_ranges=[],
|
||||||
oneofs=[
|
oneofs=[
|
||||||
],
|
],
|
||||||
serialized_start=132,
|
serialized_start=171,
|
||||||
serialized_end=243,
|
serialized_end=282,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -214,8 +221,8 @@ _PROGRESS = _descriptor.Descriptor(
|
|||||||
extension_ranges=[],
|
extension_ranges=[],
|
||||||
oneofs=[
|
oneofs=[
|
||||||
],
|
],
|
||||||
serialized_start=245,
|
serialized_start=284,
|
||||||
serialized_end=271,
|
serialized_end=310,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -244,8 +251,8 @@ _SLICEDOBJECTLIST = _descriptor.Descriptor(
|
|||||||
extension_ranges=[],
|
extension_ranges=[],
|
||||||
oneofs=[
|
oneofs=[
|
||||||
],
|
],
|
||||||
serialized_start=273,
|
serialized_start=312,
|
||||||
serialized_end=334,
|
serialized_end=373,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -281,8 +288,8 @@ _SLICEDOBJECT = _descriptor.Descriptor(
|
|||||||
extension_ranges=[],
|
extension_ranges=[],
|
||||||
oneofs=[
|
oneofs=[
|
||||||
],
|
],
|
||||||
serialized_start=336,
|
serialized_start=375,
|
||||||
serialized_end=397,
|
serialized_end=436,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -332,8 +339,8 @@ _LAYER = _descriptor.Descriptor(
|
|||||||
extension_ranges=[],
|
extension_ranges=[],
|
||||||
oneofs=[
|
oneofs=[
|
||||||
],
|
],
|
||||||
serialized_start=399,
|
serialized_start=438,
|
||||||
serialized_end=492,
|
serialized_end=531,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -377,8 +384,8 @@ _POLYGON = _descriptor.Descriptor(
|
|||||||
extension_ranges=[],
|
extension_ranges=[],
|
||||||
oneofs=[
|
oneofs=[
|
||||||
],
|
],
|
||||||
serialized_start=495,
|
serialized_start=534,
|
||||||
serialized_end=720,
|
serialized_end=759,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -414,8 +421,8 @@ _GCODELAYER = _descriptor.Descriptor(
|
|||||||
extension_ranges=[],
|
extension_ranges=[],
|
||||||
oneofs=[
|
oneofs=[
|
||||||
],
|
],
|
||||||
serialized_start=722,
|
serialized_start=761,
|
||||||
serialized_end=760,
|
serialized_end=799,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -458,8 +465,8 @@ _OBJECTPRINTTIME = _descriptor.Descriptor(
|
|||||||
extension_ranges=[],
|
extension_ranges=[],
|
||||||
oneofs=[
|
oneofs=[
|
||||||
],
|
],
|
||||||
serialized_start=762,
|
serialized_start=801,
|
||||||
serialized_end=830,
|
serialized_end=869,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -488,8 +495,8 @@ _SETTINGLIST = _descriptor.Descriptor(
|
|||||||
extension_ranges=[],
|
extension_ranges=[],
|
||||||
oneofs=[
|
oneofs=[
|
||||||
],
|
],
|
||||||
serialized_start=832,
|
serialized_start=871,
|
||||||
serialized_end=884,
|
serialized_end=923,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -525,8 +532,8 @@ _SETTING = _descriptor.Descriptor(
|
|||||||
extension_ranges=[],
|
extension_ranges=[],
|
||||||
oneofs=[
|
oneofs=[
|
||||||
],
|
],
|
||||||
serialized_start=886,
|
serialized_start=925,
|
||||||
serialized_end=924,
|
serialized_end=963,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -555,11 +562,12 @@ _GCODEPREFIX = _descriptor.Descriptor(
|
|||||||
extension_ranges=[],
|
extension_ranges=[],
|
||||||
oneofs=[
|
oneofs=[
|
||||||
],
|
],
|
||||||
serialized_start=926,
|
serialized_start=965,
|
||||||
serialized_end=953,
|
serialized_end=992,
|
||||||
)
|
)
|
||||||
|
|
||||||
_OBJECTLIST.fields_by_name['objects'].message_type = _OBJECT
|
_OBJECTLIST.fields_by_name['objects'].message_type = _OBJECT
|
||||||
|
_OBJECTLIST.fields_by_name['settings'].message_type = _SETTING
|
||||||
_SLICE.fields_by_name['object_lists'].message_type = _OBJECTLIST
|
_SLICE.fields_by_name['object_lists'].message_type = _OBJECTLIST
|
||||||
_OBJECT.fields_by_name['settings'].message_type = _SETTING
|
_OBJECT.fields_by_name['settings'].message_type = _SETTING
|
||||||
_SLICEDOBJECTLIST.fields_by_name['objects'].message_type = _SLICEDOBJECT
|
_SLICEDOBJECTLIST.fields_by_name['objects'].message_type = _SLICEDOBJECT
|
||||||
|
@ -28,6 +28,7 @@ class LayerData(MeshData):
|
|||||||
self._layers[layer].polygons.append(p)
|
self._layers[layer].polygons.append(p)
|
||||||
|
|
||||||
def getLayer(self, layer):
|
def getLayer(self, layer):
|
||||||
|
if layer in self._layers:
|
||||||
return self._layers[layer]
|
return self._layers[layer]
|
||||||
|
|
||||||
def getLayers(self):
|
def getLayers(self):
|
||||||
@ -216,7 +217,7 @@ class Polygon():
|
|||||||
elif self._type == self.SkirtType:
|
elif self._type == self.SkirtType:
|
||||||
return Color(0.0, 1.0, 1.0, 1.0)
|
return Color(0.0, 1.0, 1.0, 1.0)
|
||||||
elif self._type == self.InfillType:
|
elif self._type == self.InfillType:
|
||||||
return Color(1.0, 1.0, 0.0, 1.0)
|
return Color(1.0, 0.74, 0.0, 1.0)
|
||||||
elif self._type == self.SupportInfillType:
|
elif self._type == self.SupportInfillType:
|
||||||
return Color(0.0, 1.0, 1.0, 1.0)
|
return Color(0.0, 1.0, 1.0, 1.0)
|
||||||
else:
|
else:
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
from UM.Scene.SceneNodeDecorator import SceneNodeDecorator
|
from UM.Scene.SceneNodeDecorator import SceneNodeDecorator
|
||||||
|
|
||||||
|
## Simple decorator to indicate a scene node holds layer data.
|
||||||
class LayerDataDecorator(SceneNodeDecorator):
|
class LayerDataDecorator(SceneNodeDecorator):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
from UM.Job import Job
|
from UM.Job import Job
|
||||||
from UM.Application import Application
|
from UM.Application import Application
|
||||||
|
|
||||||
|
|
||||||
class ProcessGCodeLayerJob(Job):
|
class ProcessGCodeLayerJob(Job):
|
||||||
def __init__(self, message):
|
def __init__(self, message):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
@ -27,7 +27,7 @@ class ProcessSlicedObjectListJob(Job):
|
|||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
if Application.getInstance().getController().getActiveView().getPluginId() == "LayerView":
|
if Application.getInstance().getController().getActiveView().getPluginId() == "LayerView":
|
||||||
self._progress = Message(catalog.i18nc("Layers View mode", "Layers"), 0, False, 0)
|
self._progress = Message(catalog.i18nc("@info:status", "Processing Layers"), 0, False, -1)
|
||||||
self._progress.show()
|
self._progress.show()
|
||||||
|
|
||||||
Application.getInstance().getController().activeViewChanged.connect(self._onActiveViewChanged)
|
Application.getInstance().getController().activeViewChanged.connect(self._onActiveViewChanged)
|
||||||
@ -43,18 +43,15 @@ class ProcessSlicedObjectListJob(Job):
|
|||||||
else:
|
else:
|
||||||
objectIdMap[id(node)] = node
|
objectIdMap[id(node)] = node
|
||||||
|
|
||||||
settings = Application.getInstance().getActiveMachine()
|
settings = Application.getInstance().getMachineManager().getActiveProfile()
|
||||||
layerHeight = settings.getSettingValueByKey("layer_height")
|
layerHeight = settings.getSettingValue("layer_height")
|
||||||
|
|
||||||
center = None
|
center = None
|
||||||
if not settings.getSettingValueByKey("machine_center_is_zero"):
|
if not settings.getSettingValue("machine_center_is_zero"):
|
||||||
center = numpy.array([settings.getSettingValueByKey("machine_width") / 2, 0.0, -settings.getSettingValueByKey("machine_depth") / 2])
|
center = numpy.array([settings.getSettingValue("machine_width") / 2, 0.0, -settings.getSettingValue("machine_depth") / 2])
|
||||||
else:
|
else:
|
||||||
center = numpy.array([0.0, 0.0, 0.0])
|
center = numpy.array([0.0, 0.0, 0.0])
|
||||||
|
|
||||||
if self._progress:
|
|
||||||
self._progress.setProgress(2)
|
|
||||||
|
|
||||||
mesh = MeshData()
|
mesh = MeshData()
|
||||||
layer_data = LayerData.LayerData()
|
layer_data = LayerData.LayerData()
|
||||||
for object in self._message.objects:
|
for object in self._message.objects:
|
||||||
@ -80,14 +77,10 @@ class ProcessSlicedObjectListJob(Job):
|
|||||||
|
|
||||||
layer_data.addPolygon(layer.id, polygon.type, points, polygon.line_width)
|
layer_data.addPolygon(layer.id, polygon.type, points, polygon.line_width)
|
||||||
|
|
||||||
if self._progress:
|
|
||||||
self._progress.setProgress(50)
|
|
||||||
|
|
||||||
# We are done processing all the layers we got from the engine, now create a mesh out of the data
|
# We are done processing all the layers we got from the engine, now create a mesh out of the data
|
||||||
layer_data.build()
|
layer_data.build()
|
||||||
|
|
||||||
if self._progress:
|
|
||||||
self._progress.setProgress(100)
|
|
||||||
|
|
||||||
#Add layerdata decorator to scene node to indicate that the node has layerdata
|
#Add layerdata decorator to scene node to indicate that the node has layerdata
|
||||||
decorator = LayerDataDecorator.LayerDataDecorator()
|
decorator = LayerDataDecorator.LayerDataDecorator()
|
||||||
@ -108,7 +101,7 @@ class ProcessSlicedObjectListJob(Job):
|
|||||||
if self.isRunning():
|
if self.isRunning():
|
||||||
if Application.getInstance().getController().getActiveView().getPluginId() == "LayerView":
|
if Application.getInstance().getController().getActiveView().getPluginId() == "LayerView":
|
||||||
if not self._progress:
|
if not self._progress:
|
||||||
self._progress = Message(catalog.i18nc("Layers View mode", "Layers"), 0, False, 0)
|
self._progress = Message(catalog.i18nc("@info:status", "Processing Layers"), 0, False, 0)
|
||||||
self._progress.show()
|
self._progress.show()
|
||||||
else:
|
else:
|
||||||
if self._progress:
|
if self._progress:
|
||||||
|
@ -10,9 +10,9 @@ catalog = i18nCatalog("cura")
|
|||||||
def getMetaData():
|
def getMetaData():
|
||||||
return {
|
return {
|
||||||
"plugin": {
|
"plugin": {
|
||||||
"name": "CuraEngine Backend",
|
"name": catalog.i18nc("@label", "CuraEngine Backend"),
|
||||||
"author": "Ultimaker",
|
"author": "Ultimaker",
|
||||||
"description": catalog.i18nc("CuraEngine backend plugin description", "Provides the link to the CuraEngine slicing backend"),
|
"description": catalog.i18nc("@info:whatsthis", "Provides the link to the CuraEngine slicing backend"),
|
||||||
"api": 2
|
"api": 2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,17 +9,17 @@ catalog = i18nCatalog("cura")
|
|||||||
def getMetaData():
|
def getMetaData():
|
||||||
return {
|
return {
|
||||||
"plugin": {
|
"plugin": {
|
||||||
"name": "GCode Writer",
|
"name": catalog.i18nc("@label", "GCode Writer"),
|
||||||
"author": "Ultimaker",
|
"author": "Ultimaker",
|
||||||
"version": "1.0",
|
"version": "1.0",
|
||||||
"description": catalog.i18nc("GCode Writer Plugin Description", "Writes GCode to a file"),
|
"description": catalog.i18nc("@info:whatsthis", "Writes GCode to a file"),
|
||||||
"api": 2
|
"api": 2
|
||||||
},
|
},
|
||||||
|
|
||||||
"mesh_writer": {
|
"mesh_writer": {
|
||||||
"output": [{
|
"output": [{
|
||||||
"extension": "gcode",
|
"extension": "gcode",
|
||||||
"description": catalog.i18nc("GCode Writer File Description", "GCode File"),
|
"description": catalog.i18nc("@item:inlistbox", "GCode File"),
|
||||||
"mime_type": "text/x-gcode",
|
"mime_type": "text/x-gcode",
|
||||||
"mode": GCodeWriter.GCodeWriter.OutputMode.TextMode
|
"mode": GCodeWriter.GCodeWriter.OutputMode.TextMode
|
||||||
}]
|
}]
|
||||||
|
@ -13,6 +13,8 @@ from UM.Mesh.MeshData import MeshData
|
|||||||
|
|
||||||
from cura.ConvexHullNode import ConvexHullNode
|
from cura.ConvexHullNode import ConvexHullNode
|
||||||
|
|
||||||
|
from PyQt5 import QtCore, QtWidgets
|
||||||
|
|
||||||
from . import LayerViewProxy
|
from . import LayerViewProxy
|
||||||
|
|
||||||
## View used to display g-code paths.
|
## View used to display g-code paths.
|
||||||
@ -52,10 +54,10 @@ class LayerView(View):
|
|||||||
renderer.setRenderSelection(False)
|
renderer.setRenderSelection(False)
|
||||||
|
|
||||||
if not self._material:
|
if not self._material:
|
||||||
self._material = renderer.createMaterial(Resources.getPath(Resources.ShadersLocation, "basic.vert"), Resources.getPath(Resources.ShadersLocation, "vertexcolor.frag"))
|
self._material = renderer.createMaterial(Resources.getPath(Resources.Shaders, "basic.vert"), Resources.getPath(Resources.Shaders, "vertexcolor.frag"))
|
||||||
self._material.setUniformValue("u_color", [1.0, 0.0, 0.0, 1.0])
|
self._material.setUniformValue("u_color", [1.0, 0.0, 0.0, 1.0])
|
||||||
|
|
||||||
self._selection_material = renderer.createMaterial(Resources.getPath(Resources.ShadersLocation, "basic.vert"), Resources.getPath(Resources.ShadersLocation, "color.frag"))
|
self._selection_material = renderer.createMaterial(Resources.getPath(Resources.Shaders, "basic.vert"), Resources.getPath(Resources.Shaders, "color.frag"))
|
||||||
self._selection_material.setUniformValue("u_color", Color(35, 35, 35, 128))
|
self._selection_material.setUniformValue("u_color", Color(35, 35, 35, 128))
|
||||||
|
|
||||||
for node in DepthFirstIterator(scene.getRoot()):
|
for node in DepthFirstIterator(scene.getRoot()):
|
||||||
@ -92,10 +94,12 @@ class LayerView(View):
|
|||||||
layer = self._current_layer_num - i
|
layer = self._current_layer_num - i
|
||||||
if layer < 0:
|
if layer < 0:
|
||||||
continue
|
continue
|
||||||
|
try:
|
||||||
layer_mesh = layer_data.getLayer(layer).createMesh()
|
layer_mesh = layer_data.getLayer(layer).createMesh()
|
||||||
if not layer_mesh or layer_mesh.getVertices() is None:
|
if not layer_mesh or layer_mesh.getVertices() is None:
|
||||||
continue
|
continue
|
||||||
|
except:
|
||||||
|
continue
|
||||||
|
|
||||||
self._current_layer_mesh.addVertices(layer_mesh.getVertices())
|
self._current_layer_mesh.addVertices(layer_mesh.getVertices())
|
||||||
|
|
||||||
@ -160,8 +164,12 @@ class LayerView(View):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
def event(self, event):
|
def event(self, event):
|
||||||
if event.type == Event.KeyPressEvent:
|
modifiers = QtWidgets.QApplication.keyboardModifiers()
|
||||||
|
ctrl_is_active = modifiers == QtCore.Qt.ControlModifier
|
||||||
|
if event.type == Event.KeyPressEvent and ctrl_is_active:
|
||||||
if event.key == KeyEvent.UpKey:
|
if event.key == KeyEvent.UpKey:
|
||||||
self.setLayer(self._current_layer_num + 1)
|
self.setLayer(self._current_layer_num + 1)
|
||||||
|
return True
|
||||||
if event.key == KeyEvent.DownKey:
|
if event.key == KeyEvent.DownKey:
|
||||||
self.setLayer(self._current_layer_num - 1)
|
self.setLayer(self._current_layer_num - 1)
|
||||||
|
return True
|
||||||
|
@ -19,7 +19,7 @@ Item
|
|||||||
width: 10
|
width: 10
|
||||||
height: 250
|
height: 250
|
||||||
anchors.right : parent.right
|
anchors.right : parent.right
|
||||||
anchors.rightMargin: UM.Theme.sizes.slider_layerview_margin.width
|
anchors.rightMargin: UM.Theme.sizes.slider_layerview_margin.width/2
|
||||||
orientation: Qt.Vertical
|
orientation: Qt.Vertical
|
||||||
minimumValue: 0;
|
minimumValue: 0;
|
||||||
maximumValue: UM.LayerView.numLayers;
|
maximumValue: UM.LayerView.numLayers;
|
||||||
@ -38,14 +38,16 @@ Item
|
|||||||
height: UM.Theme.sizes.slider_layerview_background_extension.height
|
height: UM.Theme.sizes.slider_layerview_background_extension.height
|
||||||
color: UM.Theme.colors.slider_text_background
|
color: UM.Theme.colors.slider_text_background
|
||||||
}
|
}
|
||||||
UM.AngledCornerRectangle {
|
Rectangle {
|
||||||
anchors.right : parent.right
|
anchors.right : parent.right
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
z: slider.z - 1
|
z: slider.z - 1
|
||||||
cornerSize: UM.Theme.sizes.default_margin.width;
|
|
||||||
width: UM.Theme.sizes.slider_layerview_background.width
|
width: UM.Theme.sizes.slider_layerview_background.width
|
||||||
height: slider.height + UM.Theme.sizes.default_margin.height * 2
|
height: slider.height + UM.Theme.sizes.default_margin.height * 2
|
||||||
color: UM.Theme.colors.slider_text_background
|
color: UM.Theme.colors.tool_panel_background;
|
||||||
|
border.width: UM.Theme.sizes.default_lining.width
|
||||||
|
border.color: UM.Theme.colors.lining
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
id: sliderMouseArea
|
id: sliderMouseArea
|
||||||
property double manualStepSize: slider.maximumValue / 11
|
property double manualStepSize: slider.maximumValue / 11
|
||||||
|
@ -16,12 +16,13 @@ class LayerViewProxy(QObject):
|
|||||||
@pyqtProperty(bool, notify = activityChanged)
|
@pyqtProperty(bool, notify = activityChanged)
|
||||||
def getLayerActivity(self):
|
def getLayerActivity(self):
|
||||||
active_view = self._controller.getActiveView()
|
active_view = self._controller.getActiveView()
|
||||||
|
if type(active_view) == LayerView.LayerView.LayerView:
|
||||||
return active_view.getActivity()
|
return active_view.getActivity()
|
||||||
|
|
||||||
@pyqtProperty(int, notify = maxLayersChanged)
|
@pyqtProperty(int, notify = maxLayersChanged)
|
||||||
def numLayers(self):
|
def numLayers(self):
|
||||||
active_view = self._controller.getActiveView()
|
active_view = self._controller.getActiveView()
|
||||||
#print("num max layers " , active_view.getMaxLayers())
|
if type(active_view) == LayerView.LayerView.LayerView:
|
||||||
return active_view.getMaxLayers()
|
return active_view.getMaxLayers()
|
||||||
#return 100
|
#return 100
|
||||||
|
|
||||||
|
@ -10,14 +10,14 @@ catalog = i18nCatalog("cura")
|
|||||||
def getMetaData():
|
def getMetaData():
|
||||||
return {
|
return {
|
||||||
"plugin": {
|
"plugin": {
|
||||||
"name": "Layer View",
|
"name": catalog.i18nc("@label", "Layer View"),
|
||||||
"author": "Ultimaker",
|
"author": "Ultimaker",
|
||||||
"version": "1.0",
|
"version": "1.0",
|
||||||
"description": catalog.i18nc("Layer View plugin description", "Provides the Layer view."),
|
"description": catalog.i18nc("@info:whatsthis", "Provides the Layer view."),
|
||||||
"api": 2
|
"api": 2
|
||||||
},
|
},
|
||||||
"view": {
|
"view": {
|
||||||
"name": catalog.i18nc("Layers View mode", "Layers"),
|
"name": catalog.i18nc("@item:inlistbox", "Layers"),
|
||||||
"view_panel": "LayerView.qml"
|
"view_panel": "LayerView.qml"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,8 +13,8 @@ import os
|
|||||||
import plistlib
|
import plistlib
|
||||||
|
|
||||||
## Support for removable devices on Mac OSX
|
## Support for removable devices on Mac OSX
|
||||||
class OSXRemovableDrives(RemovableDrivePlugin.RemovableDrivePlugin):
|
class OSXRemovableDrivePlugin(RemovableDrivePlugin.RemovableDrivePlugin):
|
||||||
def run(self):
|
def checkRemovableDrives(self):
|
||||||
drives = {}
|
drives = {}
|
||||||
p = subprocess.Popen(["system_profiler", "SPUSBDataType", "-xml"], stdout=subprocess.PIPE)
|
p = subprocess.Popen(["system_profiler", "SPUSBDataType", "-xml"], stdout=subprocess.PIPE)
|
||||||
plist = plistlib.loads(p.communicate()[0])
|
plist = plistlib.loads(p.communicate()[0])
|
||||||
@ -41,6 +41,8 @@ class OSXRemovableDrives(RemovableDrivePlugin.RemovableDrivePlugin):
|
|||||||
volume = vol["mount_point"]
|
volume = vol["mount_point"]
|
||||||
drives[volume] = os.path.basename(volume)
|
drives[volume] = os.path.basename(volume)
|
||||||
|
|
||||||
|
return drives
|
||||||
|
|
||||||
def performEjectDevice(self, device):
|
def performEjectDevice(self, device):
|
||||||
p = subprocess.Popen(["diskutil", "eject", path], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
p = subprocess.Popen(["diskutil", "eject", path], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||||
output = p.communicate()
|
output = p.communicate()
|
||||||
|
@ -10,15 +10,15 @@ from UM.OutputDevice.OutputDevice import OutputDevice
|
|||||||
from UM.OutputDevice import OutputDeviceError
|
from UM.OutputDevice import OutputDeviceError
|
||||||
|
|
||||||
from UM.i18n import i18nCatalog
|
from UM.i18n import i18nCatalog
|
||||||
catalog = i18nCatalog("uranium")
|
catalog = i18nCatalog("cura")
|
||||||
|
|
||||||
class RemovableDriveOutputDevice(OutputDevice):
|
class RemovableDriveOutputDevice(OutputDevice):
|
||||||
def __init__(self, device_id, device_name):
|
def __init__(self, device_id, device_name):
|
||||||
super().__init__(device_id)
|
super().__init__(device_id)
|
||||||
|
|
||||||
self.setName(device_name)
|
self.setName(device_name)
|
||||||
self.setShortDescription(catalog.i18nc("", "Save to Removable Drive"))
|
self.setShortDescription(catalog.i18nc("@action:button", "Save to Removable Drive"))
|
||||||
self.setDescription(catalog.i18nc("", "Save to Removable Drive {0}").format(device_name))
|
self.setDescription(catalog.i18nc("@item:inlistbox", "Save to Removable Drive {0}").format(device_name))
|
||||||
self.setIconName("save_sd")
|
self.setIconName("save_sd")
|
||||||
self.setPriority(1)
|
self.setPriority(1)
|
||||||
|
|
||||||
@ -49,7 +49,7 @@ class RemovableDriveOutputDevice(OutputDevice):
|
|||||||
job.progress.connect(self._onProgress)
|
job.progress.connect(self._onProgress)
|
||||||
job.finished.connect(self._onFinished)
|
job.finished.connect(self._onFinished)
|
||||||
|
|
||||||
message = Message(catalog.i18nc("", "Saving to Removable Drive {0}").format(self.getName()), 0, False, -1)
|
message = Message(catalog.i18nc("@info:progress", "Saving to Removable Drive <filename>{0}</filename>").format(self.getName()), 0, False, -1)
|
||||||
message.show()
|
message.show()
|
||||||
|
|
||||||
job._message = message
|
job._message = message
|
||||||
@ -70,13 +70,13 @@ class RemovableDriveOutputDevice(OutputDevice):
|
|||||||
job._message = None
|
job._message = None
|
||||||
self.writeFinished.emit(self)
|
self.writeFinished.emit(self)
|
||||||
if job.getResult():
|
if job.getResult():
|
||||||
message = Message(catalog.i18nc("", "Saved to Removable Drive {0} as {1}").format(self.getName(), os.path.basename(job.getFileName())))
|
message = Message(catalog.i18nc("@info:status", "Saved to Removable Drive {0} as {1}").format(self.getName(), os.path.basename(job.getFileName())))
|
||||||
message.addAction("eject", catalog.i18nc("", "Eject"), "eject", catalog.i18nc("", "Eject removable device {0}").format(self.getName()))
|
message.addAction("eject", catalog.i18nc("@action:button", "Eject"), "eject", catalog.i18nc("@action", "Eject removable device {0}").format(self.getName()))
|
||||||
message.actionTriggered.connect(self._onActionTriggered)
|
message.actionTriggered.connect(self._onActionTriggered)
|
||||||
message.show()
|
message.show()
|
||||||
self.writeSuccess.emit(self)
|
self.writeSuccess.emit(self)
|
||||||
else:
|
else:
|
||||||
message = Message(catalog.i18nc("", "Could not save to removable drive {0}: {1}").format(self.getName(), str(job.getError())))
|
message = Message(catalog.i18nc("@info:status", "Could not save to removable drive {0}: {1}").format(self.getName(), str(job.getError())))
|
||||||
message.show()
|
message.show()
|
||||||
self.writeError.emit(self)
|
self.writeError.emit(self)
|
||||||
job.getStream().close()
|
job.getStream().close()
|
||||||
|
@ -11,7 +11,7 @@ from UM.OutputDevice.OutputDevicePlugin import OutputDevicePlugin
|
|||||||
from . import RemovableDriveOutputDevice
|
from . import RemovableDriveOutputDevice
|
||||||
|
|
||||||
from UM.i18n import i18nCatalog
|
from UM.i18n import i18nCatalog
|
||||||
catalog = i18nCatalog("uranium")
|
catalog = i18nCatalog("cura")
|
||||||
|
|
||||||
class RemovableDrivePlugin(OutputDevicePlugin):
|
class RemovableDrivePlugin(OutputDevicePlugin):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
@ -39,10 +39,10 @@ class RemovableDrivePlugin(OutputDevicePlugin):
|
|||||||
def ejectDevice(self, device):
|
def ejectDevice(self, device):
|
||||||
result = self.performEjectDevice(device)
|
result = self.performEjectDevice(device)
|
||||||
if result:
|
if result:
|
||||||
message = Message(catalog.i18n("Ejected {0}. You can now safely remove the drive.").format(device.getName()))
|
message = Message(catalog.i18nc("@info:status", "Ejected {0}. You can now safely remove the drive.").format(device.getName()))
|
||||||
message.show()
|
message.show()
|
||||||
else:
|
else:
|
||||||
message = Message(catalog.i18n("Failed to eject {0}. Maybe it is still in use?").format(device.getName()))
|
message = Message(catalog.i18nc("@info:status", "Failed to eject {0}. Maybe it is still in use?").format(device.getName()))
|
||||||
message.show()
|
message.show()
|
||||||
|
|
||||||
def performEjectDevice(self, device):
|
def performEjectDevice(self, device):
|
||||||
|
@ -16,7 +16,7 @@ import os
|
|||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
from UM.i18n import i18nCatalog
|
from UM.i18n import i18nCatalog
|
||||||
catalog = i18nCatalog("uranium")
|
catalog = i18nCatalog("cura")
|
||||||
|
|
||||||
# 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.
|
||||||
@ -55,7 +55,7 @@ class WindowsRemovableDrivePlugin(RemovableDrivePlugin.RemovableDrivePlugin):
|
|||||||
volume_name = name_buffer.value
|
volume_name = name_buffer.value
|
||||||
|
|
||||||
if not volume_name:
|
if not volume_name:
|
||||||
volume_name = catalog.i18nc("Default name for removable device", "Removable Drive")
|
volume_name = catalog.i18nc("@item:intext", "Removable Drive")
|
||||||
|
|
||||||
# Certain readers will report themselves as a volume even when there is no card inserted, but will show an
|
# Certain readers will report themselves as a volume even when there is no card inserted, but will show an
|
||||||
# "No volume in drive" warning when trying to call GetDiskFreeSpace. However, they will not report a valid
|
# "No volume in drive" warning when trying to call GetDiskFreeSpace. However, they will not report a valid
|
||||||
@ -88,10 +88,13 @@ class WindowsRemovableDrivePlugin(RemovableDrivePlugin.RemovableDrivePlugin):
|
|||||||
|
|
||||||
result = None
|
result = None
|
||||||
# Then, try and tell it to eject
|
# Then, try and tell it to eject
|
||||||
|
try:
|
||||||
if not windll.kernel32.DeviceIoControl(handle, IOCTL_STORAGE_EJECT_MEDIA, None, None, None, None, None, None):
|
if not windll.kernel32.DeviceIoControl(handle, IOCTL_STORAGE_EJECT_MEDIA, None, None, None, None, None, None):
|
||||||
result = False
|
result = False
|
||||||
else:
|
else:
|
||||||
result = True
|
result = True
|
||||||
|
except Exception as e:
|
||||||
|
result = False
|
||||||
|
|
||||||
# Finally, close the handle
|
# Finally, close the handle
|
||||||
windll.kernel32.CloseHandle(handle)
|
windll.kernel32.CloseHandle(handle)
|
||||||
|
@ -4,14 +4,14 @@
|
|||||||
import platform
|
import platform
|
||||||
|
|
||||||
from UM.i18n import i18nCatalog
|
from UM.i18n import i18nCatalog
|
||||||
catalog = i18nCatalog("uranium")
|
catalog = i18nCatalog("cura")
|
||||||
|
|
||||||
def getMetaData():
|
def getMetaData():
|
||||||
return {
|
return {
|
||||||
"plugin": {
|
"plugin": {
|
||||||
"name": catalog.i18nc("Removable Drive Output Device Plugin name", "Removable Drive Output Device Plugin"),
|
"name": catalog.i18nc("@label", "Removable Drive Output Device Plugin"),
|
||||||
"author": "Ultimaker B.V.",
|
"author": "Ultimaker B.V.",
|
||||||
"description": catalog.i18nc("Removable Drive Output Device Plugin description", "Provides removable drive hotplugging and writing support"),
|
"description": catalog.i18nc("@info:whatsthis", "Provides removable drive hotplugging and writing support"),
|
||||||
"version": "1.0",
|
"version": "1.0",
|
||||||
"api": 2
|
"api": 2
|
||||||
}
|
}
|
||||||
|
121
plugins/SliceInfoPlugin/SliceInfo.py
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
# Copyright (c) 2015 Ultimaker B.V.
|
||||||
|
# Cura is released under the terms of the AGPLv3 or higher.
|
||||||
|
|
||||||
|
from UM.Extension import Extension
|
||||||
|
from UM.Application import Application
|
||||||
|
from UM.Preferences import Preferences
|
||||||
|
from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator
|
||||||
|
from UM.Scene.SceneNode import SceneNode
|
||||||
|
from UM.Message import Message
|
||||||
|
from UM.i18n import i18nCatalog
|
||||||
|
|
||||||
|
import collections
|
||||||
|
import json
|
||||||
|
import os.path
|
||||||
|
import copy
|
||||||
|
import platform
|
||||||
|
import math
|
||||||
|
import urllib.request
|
||||||
|
import urllib.parse
|
||||||
|
|
||||||
|
catalog = i18nCatalog("cura")
|
||||||
|
|
||||||
|
|
||||||
|
## 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
|
||||||
|
# no model files are being sent (Just a SHA256 hash of the model).
|
||||||
|
class SliceInfo(Extension):
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__()
|
||||||
|
Application.getInstance().getOutputDeviceManager().writeStarted.connect(self._onWriteStarted)
|
||||||
|
Preferences.getInstance().addPreference("info/send_slice_info", True)
|
||||||
|
Preferences.getInstance().addPreference("info/asked_send_slice_info", False)
|
||||||
|
|
||||||
|
if not Preferences.getInstance().getValue("info/asked_send_slice_info"):
|
||||||
|
self.send_slice_info_message = Message(catalog.i18nc("@info", "Cura automatically sends slice info. You can disable this in preferences"), lifetime = 0, dismissable = False)
|
||||||
|
self.send_slice_info_message.addAction("Dismiss", catalog.i18nc("@action:button", "Dismiss"), None, "")
|
||||||
|
self.send_slice_info_message.actionTriggered.connect(self.messageActionTriggered)
|
||||||
|
self.send_slice_info_message.show()
|
||||||
|
|
||||||
|
def messageActionTriggered(self, message_id, action_id):
|
||||||
|
self.send_slice_info_message.hide()
|
||||||
|
Preferences.getInstance().setValue("info/asked_send_slice_info", True)
|
||||||
|
|
||||||
|
def _onWriteStarted(self, output_device):
|
||||||
|
if not Preferences.getInstance().getValue("info/send_slice_info"):
|
||||||
|
return # Do nothing, user does not want to send data
|
||||||
|
settings = Application.getInstance().getMachineManager().getActiveProfile()
|
||||||
|
|
||||||
|
# Load all machine definitions and put them in machine_settings dict
|
||||||
|
#setting_file_name = Application.getInstance().getActiveMachineInstance().getMachineSettings()._json_file
|
||||||
|
machine_settings = {}
|
||||||
|
#with open(setting_file_name, "rt", -1, "utf-8") as f:
|
||||||
|
# data = json.load(f, object_pairs_hook = collections.OrderedDict)
|
||||||
|
#machine_settings[os.path.basename(setting_file_name)] = copy.deepcopy(data)
|
||||||
|
active_machine_definition= Application.getInstance().getMachineManager().getActiveMachineInstance().getMachineDefinition()
|
||||||
|
data = active_machine_definition._json_data
|
||||||
|
# Loop through inherited json files
|
||||||
|
setting_file_name = active_machine_definition._path
|
||||||
|
while True:
|
||||||
|
if "inherits" in data:
|
||||||
|
inherited_setting_file_name = os.path.dirname(setting_file_name) + "/" + data["inherits"]
|
||||||
|
with open(inherited_setting_file_name, "rt", -1, "utf-8") as f:
|
||||||
|
data = json.load(f, object_pairs_hook = collections.OrderedDict)
|
||||||
|
machine_settings[os.path.basename(inherited_setting_file_name)] = copy.deepcopy(data)
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
|
||||||
|
|
||||||
|
profile_values = settings.getChangedSettings()
|
||||||
|
|
||||||
|
# Get total material used (in mm^3)
|
||||||
|
print_information = Application.getInstance().getPrintInformation()
|
||||||
|
material_radius = 0.5 * settings.getSettingValue("material_diameter")
|
||||||
|
material_used = math.pi * material_radius * material_radius * print_information.materialAmount #Volume of material used
|
||||||
|
|
||||||
|
# Get model information (bounding boxes, hashes and transformation matrix)
|
||||||
|
models_info = []
|
||||||
|
for node in DepthFirstIterator(Application.getInstance().getController().getScene().getRoot()):
|
||||||
|
if type(node) is SceneNode and node.getMeshData() and node.getMeshData().getVertices() is not None:
|
||||||
|
if not getattr(node, "_outside_buildarea", False):
|
||||||
|
model_info = {}
|
||||||
|
model_info["hash"] = node.getMeshData().getHash()
|
||||||
|
model_info["bounding_box"] = {}
|
||||||
|
model_info["bounding_box"]["minimum"] = {}
|
||||||
|
model_info["bounding_box"]["minimum"]["x"] = node.getBoundingBox().minimum.x
|
||||||
|
model_info["bounding_box"]["minimum"]["y"] = node.getBoundingBox().minimum.y
|
||||||
|
model_info["bounding_box"]["minimum"]["z"] = node.getBoundingBox().minimum.z
|
||||||
|
|
||||||
|
model_info["bounding_box"]["maximum"] = {}
|
||||||
|
model_info["bounding_box"]["maximum"]["x"] = node.getBoundingBox().maximum.x
|
||||||
|
model_info["bounding_box"]["maximum"]["y"] = node.getBoundingBox().maximum.y
|
||||||
|
model_info["bounding_box"]["maximum"]["z"] = node.getBoundingBox().maximum.z
|
||||||
|
model_info["transformation"] = str(node.getWorldTransformation().getData())
|
||||||
|
|
||||||
|
models_info.append(model_info)
|
||||||
|
|
||||||
|
# Bundle the collected data
|
||||||
|
submitted_data = {
|
||||||
|
"processor": platform.processor(),
|
||||||
|
"machine": platform.machine(),
|
||||||
|
"platform": platform.platform(),
|
||||||
|
"machine_settings": json.dumps(machine_settings),
|
||||||
|
"version": Application.getInstance().getVersion(),
|
||||||
|
"modelhash": "None",
|
||||||
|
"printtime": str(print_information.currentPrintTime),
|
||||||
|
"filament": material_used,
|
||||||
|
"language": Preferences.getInstance().getValue("general/language"),
|
||||||
|
"materials_profiles ": {}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Convert data to bytes
|
||||||
|
submitted_data = urllib.parse.urlencode(submitted_data)
|
||||||
|
binary_data = submitted_data.encode('utf-8')
|
||||||
|
|
||||||
|
# Submit data
|
||||||
|
try:
|
||||||
|
f = urllib.request.urlopen("https://stats.youmagine.com/curastats/slice", data = binary_data, timeout = 1)
|
||||||
|
except Exception as e:
|
||||||
|
print("Exception occured", e)
|
||||||
|
|
||||||
|
f.close()
|
19
plugins/SliceInfoPlugin/__init__.py
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
# Copyright (c) 2015 Ultimaker B.V.
|
||||||
|
# Cura is released under the terms of the AGPLv3 or higher.
|
||||||
|
from . import SliceInfo
|
||||||
|
from UM.i18n import i18nCatalog
|
||||||
|
catalog = i18nCatalog("cura")
|
||||||
|
|
||||||
|
def getMetaData():
|
||||||
|
return {
|
||||||
|
"plugin": {
|
||||||
|
"name": catalog.i18nc("@label", "Slice info"),
|
||||||
|
"author": "Ultimaker",
|
||||||
|
"version": "1.0",
|
||||||
|
"description": catalog.i18nc("@info:whatsthis", "Submits anonymous slice info. Can be disabled through preferences."),
|
||||||
|
"api": 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def register(app):
|
||||||
|
return { "extension": SliceInfo.SliceInfo()}
|
@ -6,13 +6,15 @@ import QtQuick.Controls 1.1
|
|||||||
import QtQuick.Layouts 1.1
|
import QtQuick.Layouts 1.1
|
||||||
import QtQuick.Window 2.1
|
import QtQuick.Window 2.1
|
||||||
|
|
||||||
import UM 1.0 as UM
|
import UM 1.1 as UM
|
||||||
|
|
||||||
UM.Dialog {
|
UM.Dialog
|
||||||
|
{
|
||||||
width: 500 * Screen.devicePixelRatio;
|
width: 500 * Screen.devicePixelRatio;
|
||||||
height: 100 * Screen.devicePixelRatio;
|
height: 100 * Screen.devicePixelRatio;
|
||||||
|
modality: Qt.NonModal
|
||||||
|
|
||||||
title: "Print with USB"
|
title: catalog.i18nc("@title:window", "Print with USB")
|
||||||
|
|
||||||
Column
|
Column
|
||||||
{
|
{
|
||||||
@ -23,18 +25,20 @@ UM.Dialog {
|
|||||||
Text
|
Text
|
||||||
{
|
{
|
||||||
//: USB Printing dialog label, %1 is head temperature
|
//: USB Printing dialog label, %1 is head temperature
|
||||||
text: qsTr("Extruder Temperature %1").arg(manager.extruderTemperature)
|
text: catalog.i18nc("@label","Extruder Temperature %1").arg(manager.extruderTemperature)
|
||||||
}
|
}
|
||||||
Text
|
Text
|
||||||
{
|
{
|
||||||
//: USB Printing dialog label, %1 is bed temperature
|
//: USB Printing dialog label, %1 is bed temperature
|
||||||
text: qsTr("Bed Temperature %1").arg(manager.bedTemperature)
|
text: catalog.i18nc("@label","Bed Temperature %1").arg(manager.bedTemperature)
|
||||||
}
|
}
|
||||||
Text
|
Text
|
||||||
{
|
{
|
||||||
text: "" + manager.error
|
text: "" + manager.error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UM.I18nCatalog{id: catalog; name:"cura"}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ProgressBar
|
ProgressBar
|
||||||
@ -50,16 +54,17 @@ UM.Dialog {
|
|||||||
}
|
}
|
||||||
|
|
||||||
rightButtons: [
|
rightButtons: [
|
||||||
Button {
|
Button
|
||||||
|
{
|
||||||
//: USB Printing dialog start print button
|
//: USB Printing dialog start print button
|
||||||
text: qsTr("Print");
|
text: catalog.i18nc("@action:button","Print");
|
||||||
onClicked: { manager.startPrint() }
|
onClicked: { manager.startPrint() }
|
||||||
enabled: manager.progress == 0 ? true : false
|
enabled: manager.progress == 0 ? true : false
|
||||||
},
|
},
|
||||||
Button
|
Button
|
||||||
{
|
{
|
||||||
//: USB Printing dialog cancel print button
|
//: USB Printing dialog cancel print button
|
||||||
text: qsTr("Cancel");
|
text: catalog.i18nc("@action:button","Cancel");
|
||||||
onClicked: { manager.cancelPrint() }
|
onClicked: { manager.cancelPrint() }
|
||||||
enabled: manager.progress == 0 ? false: true
|
enabled: manager.progress == 0 ? false: true
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@ import QtQuick 2.2
|
|||||||
import QtQuick.Window 2.2
|
import QtQuick.Window 2.2
|
||||||
import QtQuick.Controls 1.2
|
import QtQuick.Controls 1.2
|
||||||
|
|
||||||
import UM 1.0 as UM
|
import UM 1.1 as UM
|
||||||
|
|
||||||
UM.Dialog
|
UM.Dialog
|
||||||
{
|
{
|
||||||
@ -17,15 +17,16 @@ UM.Dialog
|
|||||||
visible: true;
|
visible: true;
|
||||||
modality: Qt.ApplicationModal;
|
modality: Qt.ApplicationModal;
|
||||||
|
|
||||||
title: "Firmware Update";
|
title: catalog.i18nc("@title:window","Firmware Update");
|
||||||
|
|
||||||
Column
|
Column
|
||||||
{
|
{
|
||||||
anchors.fill: parent;
|
anchors.fill: parent;
|
||||||
|
|
||||||
Text
|
Label
|
||||||
|
{
|
||||||
|
anchors
|
||||||
{
|
{
|
||||||
anchors {
|
|
||||||
left: parent.left;
|
left: parent.left;
|
||||||
right: parent.right;
|
right: parent.right;
|
||||||
}
|
}
|
||||||
@ -34,17 +35,17 @@ UM.Dialog
|
|||||||
if (manager.progress == 0)
|
if (manager.progress == 0)
|
||||||
{
|
{
|
||||||
//: Firmware update status label
|
//: Firmware update status label
|
||||||
return qsTr("Starting firmware update, this may take a while.")
|
return catalog.i18nc("@label","Starting firmware update, this may take a while.")
|
||||||
}
|
}
|
||||||
else if (manager.progress > 99)
|
else if (manager.progress > 99)
|
||||||
{
|
{
|
||||||
//: Firmware update status label
|
//: Firmware update status label
|
||||||
return qsTr("Firmware update completed.")
|
return catalog.i18nc("@label","Firmware update completed.")
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//: Firmware update status label
|
//: Firmware update status label
|
||||||
return qsTr("Updating firmware.")
|
return catalog.i18nc("@label","Updating firmware.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -57,21 +58,26 @@ UM.Dialog
|
|||||||
value: manager.progress
|
value: manager.progress
|
||||||
minimumValue: 0;
|
minimumValue: 0;
|
||||||
maximumValue: 100;
|
maximumValue: 100;
|
||||||
anchors {
|
anchors
|
||||||
|
{
|
||||||
left: parent.left;
|
left: parent.left;
|
||||||
right: parent.right;
|
right: parent.right;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SystemPalette {
|
SystemPalette
|
||||||
|
{
|
||||||
id: palette;
|
id: palette;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UM.I18nCatalog { id: catalog; name: "cura"; }
|
||||||
}
|
}
|
||||||
|
|
||||||
rightButtons: [
|
rightButtons: [
|
||||||
Button {
|
Button
|
||||||
text: "Close";
|
{
|
||||||
|
text: catalog.i18nc("@action:button","Close");
|
||||||
enabled: manager.progress >= 100;
|
enabled: manager.progress >= 100;
|
||||||
onClicked: base.visible = false;
|
onClicked: base.visible = false;
|
||||||
}
|
}
|
||||||
|
@ -8,15 +8,34 @@ import time
|
|||||||
import queue
|
import queue
|
||||||
import re
|
import re
|
||||||
import functools
|
import functools
|
||||||
|
import os
|
||||||
|
import os.path
|
||||||
|
|
||||||
from UM.Application import Application
|
from UM.Application import Application
|
||||||
from UM.Signal import Signal, SignalEmitter
|
from UM.Signal import Signal, SignalEmitter
|
||||||
from UM.Resources import Resources
|
from UM.Resources import Resources
|
||||||
from UM.Logger import Logger
|
from UM.Logger import Logger
|
||||||
|
from UM.OutputDevice.OutputDevice import OutputDevice
|
||||||
|
from UM.OutputDevice import OutputDeviceError
|
||||||
|
from UM.PluginRegistry import PluginRegistry
|
||||||
|
|
||||||
class PrinterConnection(SignalEmitter):
|
from PyQt5.QtQuick import QQuickView
|
||||||
def __init__(self, serial_port):
|
from PyQt5.QtQml import QQmlComponent, QQmlContext
|
||||||
super().__init__()
|
from PyQt5.QtCore import QUrl, QObject, pyqtSlot, pyqtProperty, pyqtSignal, Qt
|
||||||
|
|
||||||
|
from UM.i18n import i18nCatalog
|
||||||
|
catalog = i18nCatalog("cura")
|
||||||
|
|
||||||
|
class PrinterConnection(OutputDevice, QObject, SignalEmitter):
|
||||||
|
def __init__(self, serial_port, parent = None):
|
||||||
|
QObject.__init__(self, parent)
|
||||||
|
OutputDevice.__init__(self, serial_port)
|
||||||
|
SignalEmitter.__init__(self)
|
||||||
|
#super().__init__(serial_port)
|
||||||
|
self.setName(catalog.i18nc("@item:inmenu", "USB printing"))
|
||||||
|
self.setShortDescription(catalog.i18nc("@action:button", "Print with USB"))
|
||||||
|
self.setDescription(catalog.i18nc("@info:tooltip", "Print with USB"))
|
||||||
|
self.setIconName("print")
|
||||||
|
|
||||||
self._serial = None
|
self._serial = None
|
||||||
self._serial_port = serial_port
|
self._serial_port = serial_port
|
||||||
@ -25,6 +44,9 @@ class PrinterConnection(SignalEmitter):
|
|||||||
self._connect_thread = threading.Thread(target = self._connect)
|
self._connect_thread = threading.Thread(target = self._connect)
|
||||||
self._connect_thread.daemon = True
|
self._connect_thread.daemon = True
|
||||||
|
|
||||||
|
self._end_stop_thread = threading.Thread(target = self._pollEndStop)
|
||||||
|
self._end_stop_thread.deamon = True
|
||||||
|
|
||||||
# Printer is connected
|
# Printer is connected
|
||||||
self._is_connected = False
|
self._is_connected = False
|
||||||
|
|
||||||
@ -33,7 +55,7 @@ class PrinterConnection(SignalEmitter):
|
|||||||
|
|
||||||
# The baud checking is done by sending a number of m105 commands to the printer and waiting for a readable
|
# The baud checking is done by sending a number of m105 commands to the printer and waiting for a readable
|
||||||
# response. If the baudrate is correct, this should make sense, else we get giberish.
|
# response. If the baudrate is correct, this should make sense, else we get giberish.
|
||||||
self._required_responses_auto_baud = 10
|
self._required_responses_auto_baud = 3
|
||||||
|
|
||||||
self._progress = 0
|
self._progress = 0
|
||||||
|
|
||||||
@ -41,7 +63,7 @@ class PrinterConnection(SignalEmitter):
|
|||||||
self._listen_thread.daemon = True
|
self._listen_thread.daemon = True
|
||||||
|
|
||||||
self._update_firmware_thread = threading.Thread(target= self._updateFirmware)
|
self._update_firmware_thread = threading.Thread(target= self._updateFirmware)
|
||||||
self._update_firmware_thread.demon = True
|
self._update_firmware_thread.deamon = True
|
||||||
|
|
||||||
self._heatup_wait_start_time = time.time()
|
self._heatup_wait_start_time = time.time()
|
||||||
|
|
||||||
@ -78,6 +100,14 @@ class PrinterConnection(SignalEmitter):
|
|||||||
# Current Z stage location
|
# Current Z stage location
|
||||||
self._current_z = 0
|
self._current_z = 0
|
||||||
|
|
||||||
|
self._x_min_endstop_pressed = False
|
||||||
|
self._y_min_endstop_pressed = False
|
||||||
|
self._z_min_endstop_pressed = False
|
||||||
|
|
||||||
|
self._x_max_endstop_pressed = False
|
||||||
|
self._y_max_endstop_pressed = False
|
||||||
|
self._z_max_endstop_pressed = False
|
||||||
|
|
||||||
# In order to keep the connection alive we request the temperature every so often from a different extruder.
|
# In order to keep the connection alive we request the temperature every so often from a different extruder.
|
||||||
# This index is the extruder we requested data from the last time.
|
# This index is the extruder we requested data from the last time.
|
||||||
self._temperature_requested_extruder_index = 0
|
self._temperature_requested_extruder_index = 0
|
||||||
@ -86,6 +116,31 @@ class PrinterConnection(SignalEmitter):
|
|||||||
|
|
||||||
self._firmware_file_name = None
|
self._firmware_file_name = None
|
||||||
|
|
||||||
|
self._control_view = None
|
||||||
|
|
||||||
|
onError = pyqtSignal()
|
||||||
|
progressChanged = pyqtSignal()
|
||||||
|
extruderTemperatureChanged = pyqtSignal()
|
||||||
|
bedTemperatureChanged = pyqtSignal()
|
||||||
|
|
||||||
|
endstopStateChanged = pyqtSignal(str ,bool, arguments = ["key","state"])
|
||||||
|
|
||||||
|
@pyqtProperty(float, notify = progressChanged)
|
||||||
|
def progress(self):
|
||||||
|
return self._progress
|
||||||
|
|
||||||
|
@pyqtProperty(float, notify = extruderTemperatureChanged)
|
||||||
|
def extruderTemperature(self):
|
||||||
|
return self._extruder_temperatures[0]
|
||||||
|
|
||||||
|
@pyqtProperty(float, notify = bedTemperatureChanged)
|
||||||
|
def bedTemperature(self):
|
||||||
|
return self._bed_temperature
|
||||||
|
|
||||||
|
@pyqtProperty(str, notify = onError)
|
||||||
|
def error(self):
|
||||||
|
return self._error_state
|
||||||
|
|
||||||
# TODO: Might need to add check that extruders can not be changed when it started printing or loading these settings from settings object
|
# TODO: Might need to add check that extruders can not be changed when it started printing or loading these settings from settings object
|
||||||
def setNumExtuders(self, num):
|
def setNumExtuders(self, num):
|
||||||
self._extruder_count = num
|
self._extruder_count = num
|
||||||
@ -98,11 +153,18 @@ class PrinterConnection(SignalEmitter):
|
|||||||
return False
|
return False
|
||||||
return self._is_printing
|
return self._is_printing
|
||||||
|
|
||||||
|
@pyqtSlot()
|
||||||
|
def startPrint(self):
|
||||||
|
self.writeStarted.emit(self)
|
||||||
|
gcode_list = getattr( Application.getInstance().getController().getScene(), "gcode_list")
|
||||||
|
self.printGCode(gcode_list)
|
||||||
|
|
||||||
## Start a print based on a g-code.
|
## Start a print based on a g-code.
|
||||||
# \param gcode_list List with gcode (strings).
|
# \param gcode_list List with gcode (strings).
|
||||||
def printGCode(self, gcode_list):
|
def printGCode(self, gcode_list):
|
||||||
if self.isPrinting() or not self._is_connected:
|
if self.isPrinting() or not self._is_connected:
|
||||||
Logger.log("d", "Printer is busy or not connected, aborting print")
|
Logger.log("d", "Printer is busy or not connected, aborting print")
|
||||||
|
self.writeError.emit(self)
|
||||||
return
|
return
|
||||||
|
|
||||||
self._gcode.clear()
|
self._gcode.clear()
|
||||||
@ -119,6 +181,8 @@ class PrinterConnection(SignalEmitter):
|
|||||||
for i in range(0, 4): #Push first 4 entries before accepting other inputs
|
for i in range(0, 4): #Push first 4 entries before accepting other inputs
|
||||||
self._sendNextGcodeLine()
|
self._sendNextGcodeLine()
|
||||||
|
|
||||||
|
self.writeFinished.emit(self)
|
||||||
|
|
||||||
## Get the serial port string of this connection.
|
## Get the serial port string of this connection.
|
||||||
# \return serial port
|
# \return serial port
|
||||||
def getSerialPort(self):
|
def getSerialPort(self):
|
||||||
@ -162,6 +226,8 @@ class PrinterConnection(SignalEmitter):
|
|||||||
|
|
||||||
self.setProgress(100, 100)
|
self.setProgress(100, 100)
|
||||||
|
|
||||||
|
self.firmwareUpdateComplete.emit()
|
||||||
|
|
||||||
## Upload new firmware to machine
|
## Upload new firmware to machine
|
||||||
# \param filename full path of firmware file to be uploaded
|
# \param filename full path of firmware file to be uploaded
|
||||||
def updateFirmware(self, file_name):
|
def updateFirmware(self, file_name):
|
||||||
@ -169,6 +235,20 @@ class PrinterConnection(SignalEmitter):
|
|||||||
self._firmware_file_name = file_name
|
self._firmware_file_name = file_name
|
||||||
self._update_firmware_thread.start()
|
self._update_firmware_thread.start()
|
||||||
|
|
||||||
|
@pyqtSlot()
|
||||||
|
def startPollEndstop(self):
|
||||||
|
self._poll_endstop = True
|
||||||
|
self._end_stop_thread.start()
|
||||||
|
|
||||||
|
@pyqtSlot()
|
||||||
|
def stopPollEndstop(self):
|
||||||
|
self._poll_endstop = False
|
||||||
|
|
||||||
|
def _pollEndStop(self):
|
||||||
|
while self._is_connected and self._poll_endstop:
|
||||||
|
self.sendCommand("M119")
|
||||||
|
time.sleep(0.5)
|
||||||
|
|
||||||
## Private connect function run by thread. Can be started by calling connect.
|
## Private connect function run by thread. Can be started by calling connect.
|
||||||
def _connect(self):
|
def _connect(self):
|
||||||
Logger.log("d", "Attempting to connect to %s", self._serial_port)
|
Logger.log("d", "Attempting to connect to %s", self._serial_port)
|
||||||
@ -182,29 +262,24 @@ class PrinterConnection(SignalEmitter):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
Logger.log("i", "Could not establish connection on %s, unknown reasons. Device is not arduino based." % self._serial_port)
|
Logger.log("i", "Could not establish connection on %s, unknown reasons. Device is not arduino based." % self._serial_port)
|
||||||
|
|
||||||
if not self._serial:
|
|
||||||
self._is_connecting = False
|
|
||||||
Logger.log("i", "Could not establish connection on %s, unknown reasons.", self._serial_port)
|
|
||||||
return
|
|
||||||
|
|
||||||
# If the programmer connected, we know its an atmega based version. Not all that usefull, but it does give some debugging information.
|
# If the programmer connected, we know its an atmega based version. Not all that usefull, but it does give some debugging information.
|
||||||
for baud_rate in self._getBaudrateList(): # Cycle all baud rates (auto detect)
|
for baud_rate in self._getBaudrateList(): # Cycle all baud rates (auto detect)
|
||||||
|
Logger.log("d","Attempting to connect to printer with serial %s on baud rate %s", self._serial_port, baud_rate)
|
||||||
if self._serial is None:
|
if self._serial is None:
|
||||||
try:
|
try:
|
||||||
self._serial = serial.Serial(str(self._serial_port), baud_rate, timeout=3, writeTimeout=10000)
|
self._serial = serial.Serial(str(self._serial_port), baud_rate, timeout = 3, writeTimeout = 10000)
|
||||||
except serial.SerialException:
|
except serial.SerialException:
|
||||||
Logger.log("i", "Could not open port %s" % self._serial_port)
|
#Logger.log("i", "Could not open port %s" % self._serial_port)
|
||||||
return
|
continue
|
||||||
else:
|
else:
|
||||||
if not self.setBaudRate(baud_rate):
|
if not self.setBaudRate(baud_rate):
|
||||||
continue # Could not set the baud rate, go to the next
|
continue # Could not set the baud rate, go to the next
|
||||||
|
|
||||||
time.sleep(1.5) # Ensure that we are not talking to the bootloader. 1.5 sec seems to be the magic number
|
time.sleep(1.5) # Ensure that we are not talking to the bootloader. 1.5 sec seems to be the magic number
|
||||||
sucesfull_responses = 0
|
sucesfull_responses = 0
|
||||||
timeout_time = time.time() + 15
|
timeout_time = time.time() + 5
|
||||||
self._serial.write(b"\n")
|
self._serial.write(b"\n")
|
||||||
self._sendCommand("M105") # Request temperature, as this should (if baudrate is correct) result in a command with "T:" in it
|
self._sendCommand("M105") # Request temperature, as this should (if baudrate is correct) result in a command with "T:" in it
|
||||||
|
|
||||||
while timeout_time > time.time():
|
while timeout_time > time.time():
|
||||||
line = self._readline()
|
line = self._readline()
|
||||||
if line is None:
|
if line is None:
|
||||||
@ -213,7 +288,6 @@ class PrinterConnection(SignalEmitter):
|
|||||||
|
|
||||||
if b"T:" in line:
|
if b"T:" in line:
|
||||||
self._serial.timeout = 0.5
|
self._serial.timeout = 0.5
|
||||||
self._sendCommand("M105")
|
|
||||||
sucesfull_responses += 1
|
sucesfull_responses += 1
|
||||||
if sucesfull_responses >= self._required_responses_auto_baud:
|
if sucesfull_responses >= self._required_responses_auto_baud:
|
||||||
self._serial.timeout = 2 #Reset serial timeout
|
self._serial.timeout = 2 #Reset serial timeout
|
||||||
@ -221,6 +295,8 @@ class PrinterConnection(SignalEmitter):
|
|||||||
Logger.log("i", "Established printer connection on port %s" % self._serial_port)
|
Logger.log("i", "Established printer connection on port %s" % self._serial_port)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
self._sendCommand("M105") # Send M105 as long as we are listening, otherwise we end up in an undefined state
|
||||||
|
|
||||||
Logger.log("e", "Baud rate detection for %s failed", self._serial_port)
|
Logger.log("e", "Baud rate detection for %s failed", self._serial_port)
|
||||||
self.close() # Unable to connect, wrap up.
|
self.close() # Unable to connect, wrap up.
|
||||||
self.setIsConnected(False)
|
self.setIsConnected(False)
|
||||||
@ -240,15 +316,6 @@ class PrinterConnection(SignalEmitter):
|
|||||||
self.connectionStateChanged.emit(self._serial_port)
|
self.connectionStateChanged.emit(self._serial_port)
|
||||||
if self._is_connected:
|
if self._is_connected:
|
||||||
self._listen_thread.start() #Start listening
|
self._listen_thread.start() #Start listening
|
||||||
#Application.getInstance().addOutputDevice(self._serial_port, {
|
|
||||||
#"id": self._serial_port,
|
|
||||||
#"function": self.printGCode,
|
|
||||||
#"shortDescription": "Print with USB",
|
|
||||||
#"description": "Print with USB {0}".format(self._serial_port),
|
|
||||||
#"icon": "save",
|
|
||||||
#"priority": 1
|
|
||||||
#})
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
Logger.log("w", "Printer connection state was not changed")
|
Logger.log("w", "Printer connection state was not changed")
|
||||||
|
|
||||||
@ -262,6 +329,9 @@ class PrinterConnection(SignalEmitter):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
pass # This should work, but it does fail sometimes for some reason
|
pass # This should work, but it does fail sometimes for some reason
|
||||||
|
|
||||||
|
self._connect_thread = threading.Thread(target=self._connect)
|
||||||
|
self._connect_thread.daemon = True
|
||||||
|
|
||||||
if self._serial is not None:
|
if self._serial is not None:
|
||||||
self.setIsConnected(False)
|
self.setIsConnected(False)
|
||||||
try:
|
try:
|
||||||
@ -270,11 +340,32 @@ class PrinterConnection(SignalEmitter):
|
|||||||
pass
|
pass
|
||||||
self._serial.close()
|
self._serial.close()
|
||||||
|
|
||||||
|
self._listen_thread = threading.Thread(target=self._listen)
|
||||||
|
self._listen_thread.daemon = True
|
||||||
self._serial = None
|
self._serial = None
|
||||||
|
|
||||||
def isConnected(self):
|
def isConnected(self):
|
||||||
return self._is_connected
|
return self._is_connected
|
||||||
|
|
||||||
|
@pyqtSlot(int)
|
||||||
|
def heatupNozzle(self, temperature):
|
||||||
|
Logger.log("d", "Setting nozzle temperature to %s", temperature)
|
||||||
|
self._sendCommand("M104 S%s" % temperature)
|
||||||
|
|
||||||
|
@pyqtSlot(int)
|
||||||
|
def heatupBed(self, temperature):
|
||||||
|
Logger.log("d", "Setting bed temperature to %s", temperature)
|
||||||
|
self._sendCommand("M140 S%s" % temperature)
|
||||||
|
|
||||||
|
@pyqtSlot("long", "long","long")
|
||||||
|
def moveHead(self, x, y, z):
|
||||||
|
Logger.log("d","Moving head to %s, %s , %s", x, y, z)
|
||||||
|
self._sendCommand("G0 X%s Y%s Z%s"%(x,y,z))
|
||||||
|
|
||||||
|
@pyqtSlot()
|
||||||
|
def homeHead(self):
|
||||||
|
self._sendCommand("G28")
|
||||||
|
|
||||||
## Directly send the command, withouth checking connection state (eg; printing).
|
## Directly send the command, withouth checking connection state (eg; printing).
|
||||||
# \param cmd string with g-code
|
# \param cmd string with g-code
|
||||||
def _sendCommand(self, cmd):
|
def _sendCommand(self, cmd):
|
||||||
@ -296,10 +387,9 @@ class PrinterConnection(SignalEmitter):
|
|||||||
self._target_bed_temperature = float(re.search("S([0-9]+)", cmd).group(1))
|
self._target_bed_temperature = float(re.search("S([0-9]+)", cmd).group(1))
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
#Logger.log("i","Sending: %s" % (cmd))
|
|
||||||
try:
|
try:
|
||||||
command = (cmd + "\n").encode()
|
command = (cmd + "\n").encode()
|
||||||
#self._serial.write(b"\n")
|
self._serial.write(b"\n")
|
||||||
self._serial.write(command)
|
self._serial.write(command)
|
||||||
except serial.SerialTimeoutException:
|
except serial.SerialTimeoutException:
|
||||||
Logger.log("w","Serial timeout while writing to serial port, trying again.")
|
Logger.log("w","Serial timeout while writing to serial port, trying again.")
|
||||||
@ -319,6 +409,21 @@ class PrinterConnection(SignalEmitter):
|
|||||||
def __del__(self):
|
def __del__(self):
|
||||||
self.close()
|
self.close()
|
||||||
|
|
||||||
|
def createControlInterface(self):
|
||||||
|
if self._control_view is None:
|
||||||
|
path = QUrl.fromLocalFile(os.path.join(PluginRegistry.getInstance().getPluginPath("USBPrinting"), "ControlWindow.qml"))
|
||||||
|
component = QQmlComponent(Application.getInstance()._engine, path)
|
||||||
|
self._control_context = QQmlContext(Application.getInstance()._engine.rootContext())
|
||||||
|
self._control_context.setContextProperty("manager", self)
|
||||||
|
self._control_view = component.create(self._control_context)
|
||||||
|
|
||||||
|
## Show control interface.
|
||||||
|
# This will create the view if its not already created.
|
||||||
|
def showControlInterface(self):
|
||||||
|
if self._control_view is None:
|
||||||
|
self.createControlInterface()
|
||||||
|
self._control_view.show()
|
||||||
|
|
||||||
## Send a command to printer.
|
## Send a command to printer.
|
||||||
# \param cmd string with g-code
|
# \param cmd string with g-code
|
||||||
def sendCommand(self, cmd):
|
def sendCommand(self, cmd):
|
||||||
@ -331,9 +436,7 @@ class PrinterConnection(SignalEmitter):
|
|||||||
# \param error String with the error message.
|
# \param error String with the error message.
|
||||||
def _setErrorState(self, error):
|
def _setErrorState(self, error):
|
||||||
self._error_state = error
|
self._error_state = error
|
||||||
self.onError.emit(error)
|
self.onError.emit()
|
||||||
|
|
||||||
onError = Signal()
|
|
||||||
|
|
||||||
## Private function to set the temperature of an extruder
|
## Private function to set the temperature of an extruder
|
||||||
# \param index index of the extruder
|
# \param index index of the extruder
|
||||||
@ -341,21 +444,33 @@ class PrinterConnection(SignalEmitter):
|
|||||||
def _setExtruderTemperature(self, index, temperature):
|
def _setExtruderTemperature(self, index, temperature):
|
||||||
try:
|
try:
|
||||||
self._extruder_temperatures[index] = temperature
|
self._extruder_temperatures[index] = temperature
|
||||||
self.onExtruderTemperatureChange.emit(self._serial_port, index, temperature)
|
self.extruderTemperatureChanged.emit()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
onExtruderTemperatureChange = Signal()
|
|
||||||
|
|
||||||
## Private function to set the temperature of the bed.
|
## Private function to set the temperature of the bed.
|
||||||
# As all printers (as of time of writing) only support a single heated bed,
|
# As all printers (as of time of writing) only support a single heated bed,
|
||||||
# these are not indexed as with extruders.
|
# these are not indexed as with extruders.
|
||||||
def _setBedTemperature(self, temperature):
|
def _setBedTemperature(self, temperature):
|
||||||
self._bed_temperature = temperature
|
self._bed_temperature = temperature
|
||||||
self.onBedTemperatureChange.emit(self._serial_port,temperature)
|
self.bedTemperatureChanged.emit()
|
||||||
|
|
||||||
onBedTemperatureChange = Signal()
|
def requestWrite(self, node):
|
||||||
|
self.showControlInterface()
|
||||||
|
|
||||||
|
def _setEndstopState(self, endstop_key, value):
|
||||||
|
if endstop_key == b'x_min':
|
||||||
|
if self._x_min_endstop_pressed != value:
|
||||||
|
self.endstopStateChanged.emit('x_min', value)
|
||||||
|
self._x_min_endstop_pressed = value
|
||||||
|
elif endstop_key == b'y_min':
|
||||||
|
if self._y_min_endstop_pressed != value:
|
||||||
|
self.endstopStateChanged.emit('y_min', value)
|
||||||
|
self._y_min_endstop_pressed = value
|
||||||
|
elif endstop_key == b'z_min':
|
||||||
|
if self._z_min_endstop_pressed != value:
|
||||||
|
self.endstopStateChanged.emit('z_min', value)
|
||||||
|
self._z_min_endstop_pressed = value
|
||||||
|
|
||||||
## Listen thread function.
|
## Listen thread function.
|
||||||
def _listen(self):
|
def _listen(self):
|
||||||
@ -368,6 +483,14 @@ class PrinterConnection(SignalEmitter):
|
|||||||
if line is None:
|
if line is None:
|
||||||
break # None is only returned when something went wrong. Stop listening
|
break # None is only returned when something went wrong. Stop listening
|
||||||
|
|
||||||
|
if time.time() > temperature_request_timeout:
|
||||||
|
if self._extruder_count > 0:
|
||||||
|
self._temperature_requested_extruder_index = (self._temperature_requested_extruder_index + 1) % self._extruder_count
|
||||||
|
self.sendCommand("M105 T%d" % (self._temperature_requested_extruder_index))
|
||||||
|
else:
|
||||||
|
self.sendCommand("M105")
|
||||||
|
temperature_request_timeout = time.time() + 5
|
||||||
|
|
||||||
if line.startswith(b"Error:"):
|
if line.startswith(b"Error:"):
|
||||||
# Oh YEAH, consistency.
|
# Oh YEAH, consistency.
|
||||||
# Marlin reports an MIN/MAX temp error as "Error:x\n: Extruder switched off. MAXTEMP triggered !\n"
|
# Marlin reports an MIN/MAX temp error as "Error:x\n: Extruder switched off. MAXTEMP triggered !\n"
|
||||||
@ -392,16 +515,11 @@ class PrinterConnection(SignalEmitter):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
pass
|
pass
|
||||||
#TODO: temperature changed callback
|
#TODO: temperature changed callback
|
||||||
|
elif b"_min" in line or b"_max" in line:
|
||||||
|
tag, value = line.split(b':', 1)
|
||||||
|
self._setEndstopState(tag,(b'H' in value or b'TRIGGERED' in value))
|
||||||
|
|
||||||
if self._is_printing:
|
if self._is_printing:
|
||||||
if time.time() > temperature_request_timeout: # When printing, request temperature every 5 seconds.
|
|
||||||
if self._extruder_count > 0:
|
|
||||||
self._temperature_requested_extruder_index = (self._temperature_requested_extruder_index + 1) % self._extruder_count
|
|
||||||
self.sendCommand("M105 T%d" % (self._temperature_requested_extruder_index))
|
|
||||||
else:
|
|
||||||
self.sendCommand("M105")
|
|
||||||
temperature_request_timeout = time.time() + 5
|
|
||||||
|
|
||||||
if line == b"" and time.time() > ok_timeout:
|
if line == b"" and time.time() > ok_timeout:
|
||||||
line = b"ok" # Force a timeout (basicly, send next command)
|
line = b"ok" # Force a timeout (basicly, send next command)
|
||||||
|
|
||||||
@ -453,17 +571,16 @@ class PrinterConnection(SignalEmitter):
|
|||||||
self._sendCommand("N%d%s*%d" % (self._gcode_position, line, checksum))
|
self._sendCommand("N%d%s*%d" % (self._gcode_position, line, checksum))
|
||||||
self._gcode_position += 1
|
self._gcode_position += 1
|
||||||
self.setProgress(( self._gcode_position / len(self._gcode)) * 100)
|
self.setProgress(( self._gcode_position / len(self._gcode)) * 100)
|
||||||
self.progressChanged.emit(self._progress, self._serial_port)
|
self.progressChanged.emit()
|
||||||
|
|
||||||
progressChanged = Signal()
|
|
||||||
|
|
||||||
## Set the progress of the print.
|
## Set the progress of the print.
|
||||||
# It will be normalized (based on max_progress) to range 0 - 100
|
# It will be normalized (based on max_progress) to range 0 - 100
|
||||||
def setProgress(self, progress, max_progress = 100):
|
def setProgress(self, progress, max_progress = 100):
|
||||||
self._progress = (progress / max_progress) * 100 #Convert to scale of 0-100
|
self._progress = (progress / max_progress) * 100 #Convert to scale of 0-100
|
||||||
self.progressChanged.emit(self._progress, self._serial_port)
|
self.progressChanged.emit()
|
||||||
|
|
||||||
## Cancel the current print. Printer connection wil continue to listen.
|
## Cancel the current print. Printer connection wil continue to listen.
|
||||||
|
@pyqtSlot()
|
||||||
def cancelPrint(self):
|
def cancelPrint(self):
|
||||||
self._gcode_position = 0
|
self._gcode_position = 0
|
||||||
self.setProgress(0)
|
self.setProgress(0)
|
||||||
@ -494,5 +611,12 @@ class PrinterConnection(SignalEmitter):
|
|||||||
## Create a list of baud rates at which we can communicate.
|
## Create a list of baud rates at which we can communicate.
|
||||||
# \return list of int
|
# \return list of int
|
||||||
def _getBaudrateList(self):
|
def _getBaudrateList(self):
|
||||||
ret = [250000, 230400, 115200, 57600, 38400, 19200, 9600]
|
ret = [115200, 250000, 230400, 57600, 38400, 19200, 9600]
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
def _onFirmwareUpdateComplete(self):
|
||||||
|
self._update_firmware_thread.join()
|
||||||
|
self._update_firmware_thread = threading.Thread(target= self._updateFirmware)
|
||||||
|
self._update_firmware_thread.deamon = True
|
||||||
|
|
||||||
|
self.connect()
|
||||||
|
@ -9,6 +9,10 @@ from UM.Scene.SceneNode import SceneNode
|
|||||||
from UM.Resources import Resources
|
from UM.Resources import Resources
|
||||||
from UM.Logger import Logger
|
from UM.Logger import Logger
|
||||||
from UM.PluginRegistry import PluginRegistry
|
from UM.PluginRegistry import PluginRegistry
|
||||||
|
from UM.OutputDevice.OutputDevicePlugin import OutputDevicePlugin
|
||||||
|
from UM.Qt.ListModel import ListModel
|
||||||
|
|
||||||
|
from cura.CuraApplication import CuraApplication
|
||||||
|
|
||||||
import threading
|
import threading
|
||||||
import platform
|
import platform
|
||||||
@ -22,37 +26,50 @@ from UM.Extension import Extension
|
|||||||
from PyQt5.QtQuick import QQuickView
|
from PyQt5.QtQuick import QQuickView
|
||||||
from PyQt5.QtQml import QQmlComponent, QQmlContext
|
from PyQt5.QtQml import QQmlComponent, QQmlContext
|
||||||
from PyQt5.QtCore import QUrl, QObject, pyqtSlot, pyqtProperty, pyqtSignal, Qt
|
from PyQt5.QtCore import QUrl, QObject, pyqtSlot, pyqtProperty, pyqtSignal, Qt
|
||||||
|
|
||||||
from UM.i18n import i18nCatalog
|
from UM.i18n import i18nCatalog
|
||||||
i18n_catalog = i18nCatalog("cura")
|
i18n_catalog = i18nCatalog("cura")
|
||||||
|
|
||||||
class USBPrinterManager(QObject, SignalEmitter, Extension):
|
class USBPrinterManager(QObject, SignalEmitter, OutputDevicePlugin, Extension):
|
||||||
def __init__(self, parent = None):
|
def __init__(self, parent = None):
|
||||||
super().__init__(parent)
|
QObject.__init__(self, parent)
|
||||||
|
SignalEmitter.__init__(self)
|
||||||
|
OutputDevicePlugin.__init__(self)
|
||||||
|
Extension.__init__(self)
|
||||||
self._serial_port_list = []
|
self._serial_port_list = []
|
||||||
self._printer_connections = []
|
self._printer_connections = {}
|
||||||
self._check_ports_thread = threading.Thread(target = self._updateConnectionList)
|
self._printer_connections_model = None
|
||||||
self._check_ports_thread.daemon = True
|
self._update_thread = threading.Thread(target = self._updateThread)
|
||||||
self._check_ports_thread.start()
|
self._update_thread.setDaemon(True)
|
||||||
|
|
||||||
self._progress = 0
|
self._check_updates = True
|
||||||
|
|
||||||
self._control_view = None
|
|
||||||
self._firmware_view = None
|
self._firmware_view = None
|
||||||
self._extruder_temp = 0
|
|
||||||
self._bed_temp = 0
|
|
||||||
self._error_message = ""
|
|
||||||
|
|
||||||
## Add menu item to top menu of the application.
|
## Add menu item to top menu of the application.
|
||||||
self.setMenuName("Firmware")
|
self.setMenuName(i18n_catalog.i18nc("@title:menu","Firmware"))
|
||||||
self.addMenuItem(i18n_catalog.i18n("Update Firmware"), self.updateAllFirmware)
|
self.addMenuItem(i18n_catalog.i18nc("@item:inmenu", "Update Firmware"), self.updateAllFirmware)
|
||||||
|
|
||||||
Application.getInstance().applicationShuttingDown.connect(self._onApplicationShuttingDown)
|
Application.getInstance().applicationShuttingDown.connect(self.stop)
|
||||||
|
self.addConnectionSignal.connect(self.addConnection) #Because the model needs to be created in the same thread as the QMLEngine, we use a signal.
|
||||||
|
|
||||||
pyqtError = pyqtSignal(str, arguments = ["error"])
|
addConnectionSignal = Signal()
|
||||||
processingProgress = pyqtSignal(float, arguments = ["amount"])
|
printerConnectionStateChanged = pyqtSignal()
|
||||||
pyqtExtruderTemperature = pyqtSignal(float, arguments = ["amount"])
|
|
||||||
pyqtBedTemperature = pyqtSignal(float, arguments = ["amount"])
|
def start(self):
|
||||||
|
self._check_updates = True
|
||||||
|
self._update_thread.start()
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
self._check_updates = False
|
||||||
|
try:
|
||||||
|
self._update_thread.join()
|
||||||
|
except RuntimeError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def _updateThread(self):
|
||||||
|
while self._check_updates:
|
||||||
|
result = self.getSerialPortList(only_list_usb = True)
|
||||||
|
self._addRemovePorts(result)
|
||||||
|
time.sleep(5)
|
||||||
|
|
||||||
## Show firmware interface.
|
## Show firmware interface.
|
||||||
# This will create the view if its not already created.
|
# This will create the view if its not already created.
|
||||||
@ -67,80 +84,38 @@ class USBPrinterManager(QObject, SignalEmitter, Extension):
|
|||||||
|
|
||||||
self._firmware_view.show()
|
self._firmware_view.show()
|
||||||
|
|
||||||
## Show control interface.
|
|
||||||
# This will create the view if its not already created.
|
|
||||||
def spawnControlInterface(self,serial_port):
|
|
||||||
if self._control_view is None:
|
|
||||||
path = QUrl.fromLocalFile(os.path.join(PluginRegistry.getInstance().getPluginPath("USBPrinting"), "ControlWindow.qml"))
|
|
||||||
|
|
||||||
component = QQmlComponent(Application.getInstance()._engine, path)
|
|
||||||
self._control_context = QQmlContext(Application.getInstance()._engine.rootContext())
|
|
||||||
self._control_context.setContextProperty("manager", self)
|
|
||||||
|
|
||||||
self._control_view = component.create(self._control_context)
|
|
||||||
|
|
||||||
self._control_view.show()
|
|
||||||
|
|
||||||
@pyqtProperty(float,notify = processingProgress)
|
|
||||||
def progress(self):
|
|
||||||
return self._progress
|
|
||||||
|
|
||||||
@pyqtProperty(float,notify = pyqtExtruderTemperature)
|
|
||||||
def extruderTemperature(self):
|
|
||||||
return self._extruder_temp
|
|
||||||
|
|
||||||
@pyqtProperty(float,notify = pyqtBedTemperature)
|
|
||||||
def bedTemperature(self):
|
|
||||||
return self._bed_temp
|
|
||||||
|
|
||||||
@pyqtProperty(str,notify = pyqtError)
|
|
||||||
def error(self):
|
|
||||||
return self._error_message
|
|
||||||
|
|
||||||
## Check all serial ports and create a PrinterConnection object for them.
|
|
||||||
# Note that this does not validate if the serial ports are actually usable!
|
|
||||||
# This (the validation) is only done when the connect function is called.
|
|
||||||
def _updateConnectionList(self):
|
|
||||||
while True:
|
|
||||||
temp_serial_port_list = self.getSerialPortList(only_list_usb = True)
|
|
||||||
if temp_serial_port_list != self._serial_port_list: # Something changed about the list since we last changed something.
|
|
||||||
disconnected_ports = [port for port in self._serial_port_list if port not in temp_serial_port_list ]
|
|
||||||
self._serial_port_list = temp_serial_port_list
|
|
||||||
for serial_port in self._serial_port_list:
|
|
||||||
if self.getConnectionByPort(serial_port) is None: # If it doesn't already exist, add it
|
|
||||||
if not os.path.islink(serial_port): # Only add the connection if it's a non symbolic link
|
|
||||||
connection = PrinterConnection.PrinterConnection(serial_port)
|
|
||||||
connection.connect()
|
|
||||||
connection.connectionStateChanged.connect(self.serialConectionStateCallback)
|
|
||||||
connection.progressChanged.connect(self.onProgress)
|
|
||||||
connection.onExtruderTemperatureChange.connect(self.onExtruderTemperature)
|
|
||||||
connection.onBedTemperatureChange.connect(self.onBedTemperature)
|
|
||||||
connection.onError.connect(self.onError)
|
|
||||||
self._printer_connections.append(connection)
|
|
||||||
|
|
||||||
for serial_port in disconnected_ports: # Close connections and remove them from list.
|
|
||||||
connection = self.getConnectionByPort(serial_port)
|
|
||||||
if connection != None:
|
|
||||||
self._printer_connections.remove(connection)
|
|
||||||
connection.close()
|
|
||||||
time.sleep(5) # Throttle, as we don"t need this information to be updated every single second.
|
|
||||||
|
|
||||||
def updateAllFirmware(self):
|
def updateAllFirmware(self):
|
||||||
self.spawnFirmwareInterface("")
|
self.spawnFirmwareInterface("")
|
||||||
for printer_connection in self._printer_connections:
|
for printer_connection in self._printer_connections:
|
||||||
try:
|
try:
|
||||||
printer_connection.updateFirmware(Resources.getPath(Resources.FirmwareLocation, self._getDefaultFirmwareName()))
|
self._printer_connections[printer_connection].updateFirmware(Resources.getPath(CuraApplication.ResourceTypes.Firmware, self._getDefaultFirmwareName()))
|
||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
@pyqtSlot(str, result = bool)
|
||||||
def updateFirmwareBySerial(self, serial_port):
|
def updateFirmwareBySerial(self, serial_port):
|
||||||
printer_connection = self.getConnectionByPort(serial_port)
|
if serial_port in self._printer_connections:
|
||||||
if printer_connection is not None:
|
self.spawnFirmwareInterface(self._printer_connections[serial_port].getSerialPort())
|
||||||
self.spawnFirmwareInterface(printer_connection.getSerialPort())
|
try:
|
||||||
printer_connection.updateFirmware(Resources.getPath(Resources.FirmwareLocation, self._getDefaultFirmwareName()))
|
self._printer_connections[serial_port].updateFirmware(Resources.getPath(CuraApplication.ResourceTypes.Firmware, self._getDefaultFirmwareName()))
|
||||||
|
except FileNotFoundError:
|
||||||
|
self._firmware_view.close()
|
||||||
|
Logger.log("e", "Could not find firmware required for this machine")
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
## Return the singleton instance of the USBPrinterManager
|
||||||
|
@classmethod
|
||||||
|
def getInstance(cls, engine = None, script_engine = None):
|
||||||
|
# Note: Explicit use of class name to prevent issues with inheritance.
|
||||||
|
if USBPrinterManager._instance is None:
|
||||||
|
USBPrinterManager._instance = cls()
|
||||||
|
|
||||||
|
return USBPrinterManager._instance
|
||||||
|
|
||||||
def _getDefaultFirmwareName(self):
|
def _getDefaultFirmwareName(self):
|
||||||
machine_type = Application.getInstance().getActiveMachine().getTypeID()
|
machine_type = Application.getInstance().getMachineManager().getActiveMachineInstance().getMachineDefinition().getId()
|
||||||
firmware_name = ""
|
firmware_name = ""
|
||||||
baudrate = 250000
|
baudrate = 250000
|
||||||
if sys.platform.startswith("linux"):
|
if sys.platform.startswith("linux"):
|
||||||
@ -165,115 +140,41 @@ class USBPrinterManager(QObject, SignalEmitter, Extension):
|
|||||||
firmware_name += ".hex"
|
firmware_name += ".hex"
|
||||||
return firmware_name
|
return firmware_name
|
||||||
|
|
||||||
## Callback for extruder temperature change
|
def _addRemovePorts(self, serial_ports):
|
||||||
def onExtruderTemperature(self, serial_port, index, temperature):
|
# First, find and add all new or changed keys
|
||||||
self._extruder_temp = temperature
|
for serial_port in list(serial_ports):
|
||||||
self.pyqtExtruderTemperature.emit(temperature)
|
if serial_port not in self._serial_port_list:
|
||||||
|
self.addConnectionSignal.emit(serial_port) #Hack to ensure its created in main thread
|
||||||
|
continue
|
||||||
|
self._serial_port_list = list(serial_ports)
|
||||||
|
|
||||||
## Callback for bed temperature change
|
## Because the model needs to be created in the same thread as the QMLEngine, we use a signal.
|
||||||
def onBedTemperature(self, serial_port,temperature):
|
def addConnection(self, serial_port):
|
||||||
self._bed_temp = temperature
|
connection = PrinterConnection.PrinterConnection(serial_port)
|
||||||
self.pyqtBedTemperature.emit(temperature)
|
|
||||||
|
|
||||||
## Callback for error
|
|
||||||
def onError(self, error):
|
|
||||||
self._error_message = error if type(error) is str else error.decode("utf-8")
|
|
||||||
self.pyqtError.emit(self._error_message)
|
|
||||||
|
|
||||||
## Callback for progress change
|
|
||||||
def onProgress(self, progress, serial_port):
|
|
||||||
self._progress = progress
|
|
||||||
self.processingProgress.emit(progress)
|
|
||||||
|
|
||||||
## Attempt to connect with all possible connections.
|
|
||||||
def connectAllConnections(self):
|
|
||||||
for connection in self._printer_connections:
|
|
||||||
connection.connect()
|
connection.connect()
|
||||||
|
connection.connectionStateChanged.connect(self._onPrinterConnectionStateChanged)
|
||||||
|
self._printer_connections[serial_port] = connection
|
||||||
|
|
||||||
## Send gcode to printer and start printing
|
def _onPrinterConnectionStateChanged(self, serial_port):
|
||||||
def sendGCodeByPort(self, serial_port, gcode_list):
|
if self._printer_connections[serial_port].isConnected():
|
||||||
printer_connection = self.getConnectionByPort(serial_port)
|
self.getOutputDeviceManager().addOutputDevice(self._printer_connections[serial_port])
|
||||||
if printer_connection is not None:
|
|
||||||
printer_connection.printGCode(gcode_list)
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
@pyqtSlot()
|
|
||||||
def cancelPrint(self):
|
|
||||||
for printer_connection in self.getActiveConnections():
|
|
||||||
printer_connection.cancelPrint()
|
|
||||||
|
|
||||||
## Send gcode to all active printers.
|
|
||||||
# \return True if there was at least one active connection.
|
|
||||||
def sendGCodeToAllActive(self, gcode_list):
|
|
||||||
for printer_connection in self.getActiveConnections():
|
|
||||||
printer_connection.printGCode(gcode_list)
|
|
||||||
if len(self.getActiveConnections()):
|
|
||||||
return True
|
|
||||||
else:
|
else:
|
||||||
return False
|
self.getOutputDeviceManager().removeOutputDevice(serial_port)
|
||||||
|
self.printerConnectionStateChanged.emit()
|
||||||
|
|
||||||
## Send a command to a printer indentified by port
|
@pyqtProperty(QObject , notify = printerConnectionStateChanged)
|
||||||
# \param serial port String indentifieing the port
|
def connectedPrinterList(self):
|
||||||
# \param command String with the g-code command to send.
|
self._printer_connections_model = ListModel()
|
||||||
# \return True if connection was found, false otherwise
|
self._printer_connections_model.addRoleName(Qt.UserRole + 1,"name")
|
||||||
def sendCommandByPort(self, serial_port, command):
|
self._printer_connections_model.addRoleName(Qt.UserRole + 2, "printer")
|
||||||
printer_connection = self.getConnectionByPort(serial_port)
|
for connection in self._printer_connections:
|
||||||
if printer_connection is not None:
|
if self._printer_connections[connection].isConnected():
|
||||||
printer_connection.sendCommand(command)
|
self._printer_connections_model.appendItem({"name":connection, "printer": self._printer_connections[connection]})
|
||||||
return True
|
return self._printer_connections_model
|
||||||
return False
|
|
||||||
|
|
||||||
## Send a command to all active (eg; connected) printers
|
|
||||||
# \param command String with the g-code command to send.
|
|
||||||
# \return True if at least one connection was found, false otherwise
|
|
||||||
def sendCommandToAllActive(self, command):
|
|
||||||
for printer_connection in self.getActiveConnections():
|
|
||||||
printer_connection.sendCommand(command)
|
|
||||||
if len(self.getActiveConnections()):
|
|
||||||
return True
|
|
||||||
else:
|
|
||||||
return False
|
|
||||||
|
|
||||||
## Callback if the connection state of a connection is changed.
|
|
||||||
# This adds or removes the connection as a possible output device.
|
|
||||||
def serialConectionStateCallback(self, serial_port):
|
|
||||||
connection = self.getConnectionByPort(serial_port)
|
|
||||||
if connection.isConnected():
|
|
||||||
Application.getInstance().addOutputDevice(serial_port, {
|
|
||||||
"id": serial_port,
|
|
||||||
"function": self.spawnControlInterface,
|
|
||||||
"description": "Print with USB {0}".format(serial_port),
|
|
||||||
"shortDescription": "Print with USB",
|
|
||||||
"icon": "save",
|
|
||||||
"priority": 1
|
|
||||||
})
|
|
||||||
else:
|
|
||||||
Application.getInstance().removeOutputDevice(serial_port)
|
|
||||||
|
|
||||||
@pyqtSlot()
|
|
||||||
def startPrint(self):
|
|
||||||
gcode_list = getattr(Application.getInstance().getController().getScene(), "gcode_list", None)
|
|
||||||
if gcode_list:
|
|
||||||
final_list = []
|
|
||||||
for gcode in gcode_list:
|
|
||||||
final_list += gcode.split("\n")
|
|
||||||
self.sendGCodeToAllActive(gcode_list)
|
|
||||||
|
|
||||||
## Get a list of printer connection objects that are connected.
|
|
||||||
def getActiveConnections(self):
|
|
||||||
return [connection for connection in self._printer_connections if connection.isConnected()]
|
|
||||||
|
|
||||||
## Get a printer connection object by serial port
|
|
||||||
def getConnectionByPort(self, serial_port):
|
|
||||||
for printer_connection in self._printer_connections:
|
|
||||||
if serial_port == printer_connection.getSerialPort():
|
|
||||||
return printer_connection
|
|
||||||
return None
|
|
||||||
|
|
||||||
## Create a list of serial ports on the system.
|
## Create a list of serial ports on the system.
|
||||||
# \param only_list_usb If true, only usb ports are listed
|
# \param only_list_usb If true, only usb ports are listed
|
||||||
def getSerialPortList(self,only_list_usb=False):
|
def getSerialPortList(self, only_list_usb = False):
|
||||||
base_list = []
|
base_list = []
|
||||||
if platform.system() == "Windows":
|
if platform.system() == "Windows":
|
||||||
import winreg
|
import winreg
|
||||||
@ -293,8 +194,6 @@ class USBPrinterManager(QObject, SignalEmitter, Extension):
|
|||||||
base_list = filter(lambda s: "Bluetooth" not in s, base_list) # Filter because mac sometimes puts them in the list
|
base_list = filter(lambda s: "Bluetooth" not in s, base_list) # Filter because mac sometimes puts them in the list
|
||||||
else:
|
else:
|
||||||
base_list = base_list + glob.glob("/dev/ttyUSB*") + glob.glob("/dev/ttyACM*") + glob.glob("/dev/cu.*") + glob.glob("/dev/tty.usb*") + glob.glob("/dev/rfcomm*") + glob.glob("/dev/serial/by-id/*")
|
base_list = base_list + glob.glob("/dev/ttyUSB*") + glob.glob("/dev/ttyACM*") + glob.glob("/dev/cu.*") + glob.glob("/dev/tty.usb*") + glob.glob("/dev/rfcomm*") + glob.glob("/dev/serial/by-id/*")
|
||||||
return base_list
|
return list(base_list)
|
||||||
|
|
||||||
def _onApplicationShuttingDown(self):
|
_instance = None
|
||||||
for connection in self._printer_connections:
|
|
||||||
connection.close()
|
|
@ -2,7 +2,7 @@
|
|||||||
# Cura is released under the terms of the AGPLv3 or higher.
|
# Cura is released under the terms of the AGPLv3 or higher.
|
||||||
|
|
||||||
from . import USBPrinterManager
|
from . import USBPrinterManager
|
||||||
|
from PyQt5.QtQml import qmlRegisterType, qmlRegisterSingletonType
|
||||||
from UM.i18n import i18nCatalog
|
from UM.i18n import i18nCatalog
|
||||||
i18n_catalog = i18nCatalog("cura")
|
i18n_catalog = i18nCatalog("cura")
|
||||||
|
|
||||||
@ -10,12 +10,14 @@ def getMetaData():
|
|||||||
return {
|
return {
|
||||||
"type": "extension",
|
"type": "extension",
|
||||||
"plugin": {
|
"plugin": {
|
||||||
"name": "USB printing",
|
"name": i18n_catalog.i18nc("@label", "USB printing"),
|
||||||
"author": "Ultimaker",
|
"author": "Ultimaker",
|
||||||
"version": "1.0",
|
"version": "1.0",
|
||||||
"description": i18n_catalog.i18nc("USB Printing plugin description","Accepts G-Code and sends them to a printer. Plugin can also update firmware")
|
"api": 2,
|
||||||
|
"description": i18n_catalog.i18nc("@info:whatsthis","Accepts G-Code and sends them to a printer. Plugin can also update firmware.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def register(app):
|
def register(app):
|
||||||
return {"extension":USBPrinterManager.USBPrinterManager()}
|
qmlRegisterSingletonType(USBPrinterManager.USBPrinterManager, "UM", 1, 0, "USBPrinterManager", USBPrinterManager.USBPrinterManager.getInstance)
|
||||||
|
return {"extension":USBPrinterManager.USBPrinterManager.getInstance(),"output_device": USBPrinterManager.USBPrinterManager.getInstance() }
|
||||||
|
@ -1,419 +0,0 @@
|
|||||||
msgid ""
|
|
||||||
msgstr ""
|
|
||||||
"MIME-Version: 1.0\n"
|
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
|
||||||
"X-Qt-Contexts: true\n"
|
|
||||||
|
|
||||||
#. About dialog title
|
|
||||||
#: ../resources/qml/AboutDialog.qml:12
|
|
||||||
msgctxt "AboutDialog|"
|
|
||||||
msgid "About Cura"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. About dialog application description
|
|
||||||
#: ../resources/qml/AboutDialog.qml:42
|
|
||||||
msgctxt "AboutDialog|"
|
|
||||||
msgid "End-to-end solution for fused filament 3D printing."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. About dialog application author note
|
|
||||||
#: ../resources/qml/AboutDialog.qml:47
|
|
||||||
msgctxt "AboutDialog|"
|
|
||||||
msgid ""
|
|
||||||
"Cura has been developed by Ultimaker B.V. in cooperation with the community."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. Close about dialog button
|
|
||||||
#: ../resources/qml/AboutDialog.qml:58
|
|
||||||
msgctxt "AboutDialog|"
|
|
||||||
msgid "Close"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. Undo action
|
|
||||||
#: ../resources/qml/Actions.qml:37
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "&Undo"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. Redo action
|
|
||||||
#: ../resources/qml/Actions.qml:45
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "&Redo"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. Quit action
|
|
||||||
#: ../resources/qml/Actions.qml:53
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "&Quit"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. Preferences action
|
|
||||||
#: ../resources/qml/Actions.qml:61
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "&Preferences..."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. Add Printer action
|
|
||||||
#: ../resources/qml/Actions.qml:68
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "&Add Printer..."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. Configure Printers action
|
|
||||||
#: ../resources/qml/Actions.qml:74
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "&Configure Printers"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. Show Online Documentation action
|
|
||||||
#: ../resources/qml/Actions.qml:81
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "Show Online &Documentation"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. Report a Bug Action
|
|
||||||
#: ../resources/qml/Actions.qml:89
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "Report a &Bug"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. About action
|
|
||||||
#: ../resources/qml/Actions.qml:96
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "&About..."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. Delete selection action
|
|
||||||
#: ../resources/qml/Actions.qml:103
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "Delete Selection"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. Delete object action
|
|
||||||
#: ../resources/qml/Actions.qml:111
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "Delete Object"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. Center object action
|
|
||||||
#: ../resources/qml/Actions.qml:118
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "Center Object on Platform"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. Duplicate object action
|
|
||||||
#: ../resources/qml/Actions.qml:124
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "Duplicate Object"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. Split object action
|
|
||||||
#: ../resources/qml/Actions.qml:130
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "Split Object into Parts"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. Clear build platform action
|
|
||||||
#: ../resources/qml/Actions.qml:137
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "Clear Build Platform"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. Reload all objects action
|
|
||||||
#: ../resources/qml/Actions.qml:144
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "Reload All Objects"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. Reset all positions action
|
|
||||||
#: ../resources/qml/Actions.qml:150
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "Reset All Object Positions"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. Reset all positions action
|
|
||||||
#: ../resources/qml/Actions.qml:156
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "Reset All Object Transformations"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. Open file action
|
|
||||||
#: ../resources/qml/Actions.qml:162
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "&Open..."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. Save file action
|
|
||||||
#: ../resources/qml/Actions.qml:170
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "&Save..."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. Show engine log action
|
|
||||||
#: ../resources/qml/Actions.qml:178
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "Show engine &log..."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. Add Printer dialog title
|
|
||||||
#. ----------
|
|
||||||
#. Add Printer wizard page title
|
|
||||||
#: ../resources/qml/AddMachineWizard.qml:12
|
|
||||||
#: ../resources/qml/AddMachineWizard.qml:19
|
|
||||||
msgctxt "AddMachineWizard|"
|
|
||||||
msgid "Add Printer"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. Add Printer wizard page description
|
|
||||||
#: ../resources/qml/AddMachineWizard.qml:25
|
|
||||||
msgctxt "AddMachineWizard|"
|
|
||||||
msgid "Please select the type of printer:"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. Add Printer wizard field label
|
|
||||||
#: ../resources/qml/AddMachineWizard.qml:40
|
|
||||||
msgctxt "AddMachineWizard|"
|
|
||||||
msgid "Printer Name:"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. Add Printer wizarad button
|
|
||||||
#: ../resources/qml/AddMachineWizard.qml:53
|
|
||||||
msgctxt "AddMachineWizard|"
|
|
||||||
msgid "Next"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. Add Printer wizarad button
|
|
||||||
#: ../resources/qml/AddMachineWizard.qml:63
|
|
||||||
msgctxt "AddMachineWizard|"
|
|
||||||
msgid "Cancel"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. USB Printing dialog label, %1 is head temperature
|
|
||||||
#: ../plugins/USBPrinting/ControlWindow.qml:15
|
|
||||||
#, qt-format
|
|
||||||
msgctxt "ControlWindow|"
|
|
||||||
msgid "Extruder Temperature %1"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. USB Printing dialog label, %1 is bed temperature
|
|
||||||
#: ../plugins/USBPrinting/ControlWindow.qml:20
|
|
||||||
#, qt-format
|
|
||||||
msgctxt "ControlWindow|"
|
|
||||||
msgid "Bed Temperature %1"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. USB Printing dialog start print button
|
|
||||||
#: ../plugins/USBPrinting/ControlWindow.qml:33
|
|
||||||
msgctxt "ControlWindow|"
|
|
||||||
msgid "Print"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. USB Printing dialog cancel print button
|
|
||||||
#: ../plugins/USBPrinting/ControlWindow.qml:40
|
|
||||||
msgctxt "ControlWindow|"
|
|
||||||
msgid "Cancel"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. Cura application window title
|
|
||||||
#: ../resources/qml/Cura.qml:14
|
|
||||||
msgctxt "Cura|"
|
|
||||||
msgid "Cura"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. File menu
|
|
||||||
#: ../resources/qml/Cura.qml:26
|
|
||||||
msgctxt "Cura|"
|
|
||||||
msgid "&File"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. Edit menu
|
|
||||||
#: ../resources/qml/Cura.qml:38
|
|
||||||
msgctxt "Cura|"
|
|
||||||
msgid "&Edit"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. Machine menu
|
|
||||||
#: ../resources/qml/Cura.qml:50
|
|
||||||
msgctxt "Cura|"
|
|
||||||
msgid "&Machine"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. Extensions menu
|
|
||||||
#: ../resources/qml/Cura.qml:76
|
|
||||||
msgctxt "Cura|"
|
|
||||||
msgid "E&xtensions"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. Settings menu
|
|
||||||
#: ../resources/qml/Cura.qml:107
|
|
||||||
msgctxt "Cura|"
|
|
||||||
msgid "&Settings"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. Help menu
|
|
||||||
#: ../resources/qml/Cura.qml:114
|
|
||||||
msgctxt "Cura|"
|
|
||||||
msgid "&Help"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. View Mode toolbar button
|
|
||||||
#: ../resources/qml/Cura.qml:231
|
|
||||||
msgctxt "Cura|"
|
|
||||||
msgid "View Mode"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. View preferences page title
|
|
||||||
#: ../resources/qml/Cura.qml:273
|
|
||||||
msgctxt "Cura|"
|
|
||||||
msgid "View"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. File open dialog title
|
|
||||||
#: ../resources/qml/Cura.qml:370
|
|
||||||
msgctxt "Cura|"
|
|
||||||
msgid "Open File"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. File save dialog title
|
|
||||||
#: ../resources/qml/Cura.qml:386
|
|
||||||
msgctxt "Cura|"
|
|
||||||
msgid "Save File"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. Engine Log dialog title
|
|
||||||
#: ../resources/qml/EngineLog.qml:11
|
|
||||||
msgctxt "EngineLog|"
|
|
||||||
msgid "Engine Log"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. Close engine log button
|
|
||||||
#: ../resources/qml/EngineLog.qml:30
|
|
||||||
msgctxt "EngineLog|"
|
|
||||||
msgid "Close"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. Firmware update status label
|
|
||||||
#: ../plugins/USBPrinting/FirmwareUpdateWindow.qml:16
|
|
||||||
msgctxt "FirmwareUpdateWindow|"
|
|
||||||
msgid "Starting firmware update, this may take a while."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. Firmware update status label
|
|
||||||
#: ../plugins/USBPrinting/FirmwareUpdateWindow.qml:21
|
|
||||||
msgctxt "FirmwareUpdateWindow|"
|
|
||||||
msgid "Firmware update completed."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. Firmware update status label
|
|
||||||
#: ../plugins/USBPrinting/FirmwareUpdateWindow.qml:26
|
|
||||||
msgctxt "FirmwareUpdateWindow|"
|
|
||||||
msgid "Updating firmware."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. Print material amount save button label
|
|
||||||
#: ../resources/qml/SaveButton.qml:149
|
|
||||||
#, qt-format
|
|
||||||
msgctxt "SaveButton|"
|
|
||||||
msgid "%1m material"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. Save button label
|
|
||||||
#: ../resources/qml/SaveButton.qml:191
|
|
||||||
msgctxt "SaveButton|"
|
|
||||||
msgid "Please load a 3D model"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. Save button label
|
|
||||||
#: ../resources/qml/SaveButton.qml:194
|
|
||||||
msgctxt "SaveButton|"
|
|
||||||
msgid "Calculating Print-time"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. Save button label
|
|
||||||
#: ../resources/qml/SaveButton.qml:197
|
|
||||||
msgctxt "SaveButton|"
|
|
||||||
msgid "Estimated Print-time"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. Simple configuration mode option
|
|
||||||
#: ../resources/qml/Sidebar.qml:105
|
|
||||||
msgctxt "Sidebar|"
|
|
||||||
msgid "Simple"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. Advanced configuration mode option
|
|
||||||
#: ../resources/qml/Sidebar.qml:107
|
|
||||||
msgctxt "Sidebar|"
|
|
||||||
msgid "Advanced"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. Configuration mode label
|
|
||||||
#: ../resources/qml/SidebarHeader.qml:26
|
|
||||||
msgctxt "SidebarHeader|"
|
|
||||||
msgid "Mode:"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. Machine selection label
|
|
||||||
#: ../resources/qml/SidebarHeader.qml:70
|
|
||||||
msgctxt "SidebarHeader|"
|
|
||||||
msgid "Machine:"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. Sidebar header label
|
|
||||||
#: ../resources/qml/SidebarHeader.qml:117
|
|
||||||
msgctxt "SidebarHeader|"
|
|
||||||
msgid "Print Setup"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. Sidebar configuration label
|
|
||||||
#: ../resources/qml/SidebarSimple.qml:40
|
|
||||||
msgctxt "SidebarSimple|"
|
|
||||||
msgid "No Model Loaded"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. Sidebar configuration label
|
|
||||||
#: ../resources/qml/SidebarSimple.qml:45
|
|
||||||
msgctxt "SidebarSimple|"
|
|
||||||
msgid "Calculating..."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. Sidebar configuration label
|
|
||||||
#: ../resources/qml/SidebarSimple.qml:50
|
|
||||||
msgctxt "SidebarSimple|"
|
|
||||||
msgid "Estimated Print Time"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. Quality slider label
|
|
||||||
#: ../resources/qml/SidebarSimple.qml:87
|
|
||||||
msgctxt "SidebarSimple|"
|
|
||||||
msgid ""
|
|
||||||
"Minimum\n"
|
|
||||||
"Draft"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. Quality slider label
|
|
||||||
#: ../resources/qml/SidebarSimple.qml:97
|
|
||||||
msgctxt "SidebarSimple|"
|
|
||||||
msgid ""
|
|
||||||
"Maximum\n"
|
|
||||||
"Quality"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. Setting checkbox
|
|
||||||
#: ../resources/qml/SidebarSimple.qml:109
|
|
||||||
msgctxt "SidebarSimple|"
|
|
||||||
msgid "Enable Support"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. View configuration page title
|
|
||||||
#: ../resources/qml/ViewPage.qml:9
|
|
||||||
msgctxt "ViewPage|"
|
|
||||||
msgid "View"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. Display Overhang preference checkbox
|
|
||||||
#: ../resources/qml/ViewPage.qml:24
|
|
||||||
msgctxt "ViewPage|"
|
|
||||||
msgid "Display Overhang"
|
|
||||||
msgstr ""
|
|
@ -1,425 +0,0 @@
|
|||||||
msgid ""
|
|
||||||
msgstr ""
|
|
||||||
"MIME-Version: 1.0\n"
|
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
|
||||||
"X-Qt-Contexts: true\n"
|
|
||||||
"Project-Id-Version: \n"
|
|
||||||
"POT-Creation-Date: \n"
|
|
||||||
"PO-Revision-Date: \n"
|
|
||||||
"Last-Translator: \n"
|
|
||||||
"Language-Team: \n"
|
|
||||||
"X-Generator: Poedit 1.8\n"
|
|
||||||
"Language: cz\n"
|
|
||||||
|
|
||||||
#. About dialog title
|
|
||||||
#: ../resources/qml/AboutDialog.qml:12
|
|
||||||
msgctxt "AboutDialog|"
|
|
||||||
msgid "About Cura"
|
|
||||||
msgstr "Über Cura"
|
|
||||||
|
|
||||||
#. About dialog application description
|
|
||||||
#: ../resources/qml/AboutDialog.qml:42
|
|
||||||
msgctxt "AboutDialog|"
|
|
||||||
msgid "End-to-end solution for fused filament 3D printing."
|
|
||||||
msgstr "Komplettlösung für den 3D-Druck mit geschmolzenem Filament."
|
|
||||||
|
|
||||||
#. About dialog application author note
|
|
||||||
#: ../resources/qml/AboutDialog.qml:47
|
|
||||||
msgctxt "AboutDialog|"
|
|
||||||
msgid "Cura has been developed by Ultimaker B.V. in cooperation with the community."
|
|
||||||
msgstr "Cura wurde von Ultimaker B.V. in Zusammenarbeit mit der Gemeinschaft entwickelt."
|
|
||||||
|
|
||||||
#. Close about dialog button
|
|
||||||
#: ../resources/qml/AboutDialog.qml:58
|
|
||||||
msgctxt "AboutDialog|"
|
|
||||||
msgid "Close"
|
|
||||||
msgstr "Schließen"
|
|
||||||
|
|
||||||
#. Undo action
|
|
||||||
#: ../resources/qml/Actions.qml:37
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "&Undo"
|
|
||||||
msgstr "&Rückgängig machen"
|
|
||||||
|
|
||||||
#. Redo action
|
|
||||||
#: ../resources/qml/Actions.qml:45
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "&Redo"
|
|
||||||
msgstr "&Wiederholen"
|
|
||||||
|
|
||||||
#. Quit action
|
|
||||||
#: ../resources/qml/Actions.qml:53
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "&Quit"
|
|
||||||
msgstr "&Beenden"
|
|
||||||
|
|
||||||
#. Preferences action
|
|
||||||
#: ../resources/qml/Actions.qml:61
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "&Preferences..."
|
|
||||||
msgstr "&Einstellungen..."
|
|
||||||
|
|
||||||
#. Add Printer action
|
|
||||||
#: ../resources/qml/Actions.qml:68
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "&Add Printer..."
|
|
||||||
msgstr "&Drucker hinzufügen..."
|
|
||||||
|
|
||||||
#. Configure Printers action
|
|
||||||
#: ../resources/qml/Actions.qml:74
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "&Configure Printers"
|
|
||||||
msgstr "Drucker &konfigurieren"
|
|
||||||
|
|
||||||
#. Show Online Documentation action
|
|
||||||
#: ../resources/qml/Actions.qml:81
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "Show Online &Documentation"
|
|
||||||
msgstr "Online-&Dokumentation anzeigen"
|
|
||||||
|
|
||||||
#. Report a Bug Action
|
|
||||||
#: ../resources/qml/Actions.qml:89
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "Report a &Bug"
|
|
||||||
msgstr "&Fehler berichten"
|
|
||||||
|
|
||||||
#. About action
|
|
||||||
#: ../resources/qml/Actions.qml:96
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "&About..."
|
|
||||||
msgstr "&Über..."
|
|
||||||
|
|
||||||
#. Delete selection action
|
|
||||||
#: ../resources/qml/Actions.qml:103
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "Delete Selection"
|
|
||||||
msgstr "Auswahl löschen"
|
|
||||||
|
|
||||||
#. Delete object action
|
|
||||||
#: ../resources/qml/Actions.qml:111
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "Delete Object"
|
|
||||||
msgstr "Objekt löschen"
|
|
||||||
|
|
||||||
#. Center object action
|
|
||||||
#: ../resources/qml/Actions.qml:118
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "Center Object on Platform"
|
|
||||||
msgstr "Objekt auf Plattform zentrieren"
|
|
||||||
|
|
||||||
#. Duplicate object action
|
|
||||||
#: ../resources/qml/Actions.qml:124
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "Duplicate Object"
|
|
||||||
msgstr "Objekt duplizieren"
|
|
||||||
|
|
||||||
#. Split object action
|
|
||||||
#: ../resources/qml/Actions.qml:130
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "Split Object into Parts"
|
|
||||||
msgstr "Objekt teilen"
|
|
||||||
|
|
||||||
#. Clear build platform action
|
|
||||||
#: ../resources/qml/Actions.qml:137
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "Clear Build Platform"
|
|
||||||
msgstr "Druckplatte reinigen"
|
|
||||||
|
|
||||||
#. Reload all objects action
|
|
||||||
#: ../resources/qml/Actions.qml:144
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "Reload All Objects"
|
|
||||||
msgstr "Alle Objekte neu laden"
|
|
||||||
|
|
||||||
#. Reset all positions action
|
|
||||||
#: ../resources/qml/Actions.qml:150
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "Reset All Object Positions"
|
|
||||||
msgstr "Alle Objektpositionen zurücksetzen"
|
|
||||||
|
|
||||||
#. Reset all positions action
|
|
||||||
#: ../resources/qml/Actions.qml:156
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "Reset All Object Transformations"
|
|
||||||
msgstr "Alle Objektumwandlungen zurücksetzen"
|
|
||||||
|
|
||||||
#. Open file action
|
|
||||||
#: ../resources/qml/Actions.qml:162
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "&Open..."
|
|
||||||
msgstr "&Öffnen..."
|
|
||||||
|
|
||||||
#. Save file action
|
|
||||||
#: ../resources/qml/Actions.qml:170
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "&Save..."
|
|
||||||
msgstr "&Speichern..."
|
|
||||||
|
|
||||||
#. Show engine log action
|
|
||||||
#: ../resources/qml/Actions.qml:178
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "Show engine &log..."
|
|
||||||
msgstr "Engine-&Protokoll anzeigen..."
|
|
||||||
|
|
||||||
#. Add Printer dialog title
|
|
||||||
#. ----------
|
|
||||||
#. Add Printer wizard page title
|
|
||||||
#: ../resources/qml/AddMachineWizard.qml:12
|
|
||||||
#: ../resources/qml/AddMachineWizard.qml:19
|
|
||||||
msgctxt "AddMachineWizard|"
|
|
||||||
msgid "Add Printer"
|
|
||||||
msgstr "Drucker hinzufügen"
|
|
||||||
|
|
||||||
#. Add Printer wizard page description
|
|
||||||
#: ../resources/qml/AddMachineWizard.qml:25
|
|
||||||
msgctxt "AddMachineWizard|"
|
|
||||||
msgid "Please select the type of printer:"
|
|
||||||
msgstr "Wählen Sie den Druckertyp:"
|
|
||||||
|
|
||||||
#. Add Printer wizard field label
|
|
||||||
#: ../resources/qml/AddMachineWizard.qml:40
|
|
||||||
msgctxt "AddMachineWizard|"
|
|
||||||
msgid "Printer Name:"
|
|
||||||
msgstr "Druckername:"
|
|
||||||
|
|
||||||
#. Add Printer wizarad button
|
|
||||||
#: ../resources/qml/AddMachineWizard.qml:53
|
|
||||||
msgctxt "AddMachineWizard|"
|
|
||||||
msgid "Next"
|
|
||||||
msgstr "Weiter"
|
|
||||||
|
|
||||||
#. Add Printer wizarad button
|
|
||||||
#: ../resources/qml/AddMachineWizard.qml:63
|
|
||||||
msgctxt "AddMachineWizard|"
|
|
||||||
msgid "Cancel"
|
|
||||||
msgstr "Abbrechen"
|
|
||||||
|
|
||||||
#. USB Printing dialog label, %1 is head temperature
|
|
||||||
#: ../plugins/USBPrinting/ControlWindow.qml:15
|
|
||||||
#, qt-format
|
|
||||||
msgctxt "ControlWindow|"
|
|
||||||
msgid "Extruder Temperature %1"
|
|
||||||
msgstr "Extruder-Temperatur %1"
|
|
||||||
|
|
||||||
#. USB Printing dialog label, %1 is bed temperature
|
|
||||||
#: ../plugins/USBPrinting/ControlWindow.qml:20
|
|
||||||
#, qt-format
|
|
||||||
msgctxt "ControlWindow|"
|
|
||||||
msgid "Bed Temperature %1"
|
|
||||||
msgstr "Druckbett-Temperatur %1"
|
|
||||||
|
|
||||||
#. USB Printing dialog start print button
|
|
||||||
#: ../plugins/USBPrinting/ControlWindow.qml:33
|
|
||||||
msgctxt "ControlWindow|"
|
|
||||||
msgid "Print"
|
|
||||||
msgstr "Drucken"
|
|
||||||
|
|
||||||
#. USB Printing dialog cancel print button
|
|
||||||
#: ../plugins/USBPrinting/ControlWindow.qml:40
|
|
||||||
msgctxt "ControlWindow|"
|
|
||||||
msgid "Cancel"
|
|
||||||
msgstr "Abbrechen"
|
|
||||||
|
|
||||||
#. Cura application window title
|
|
||||||
#: ../resources/qml/Cura.qml:14
|
|
||||||
msgctxt "Cura|"
|
|
||||||
msgid "Cura"
|
|
||||||
msgstr "Cura"
|
|
||||||
|
|
||||||
#. File menu
|
|
||||||
#: ../resources/qml/Cura.qml:26
|
|
||||||
msgctxt "Cura|"
|
|
||||||
msgid "&File"
|
|
||||||
msgstr "&Datei"
|
|
||||||
|
|
||||||
#. Edit menu
|
|
||||||
#: ../resources/qml/Cura.qml:38
|
|
||||||
msgctxt "Cura|"
|
|
||||||
msgid "&Edit"
|
|
||||||
msgstr "&Bearbeiten"
|
|
||||||
|
|
||||||
#. Machine menu
|
|
||||||
#: ../resources/qml/Cura.qml:50
|
|
||||||
msgctxt "Cura|"
|
|
||||||
msgid "&Machine"
|
|
||||||
msgstr "&Maschine"
|
|
||||||
|
|
||||||
#. Extensions menu
|
|
||||||
#: ../resources/qml/Cura.qml:76
|
|
||||||
msgctxt "Cura|"
|
|
||||||
msgid "E&xtensions"
|
|
||||||
msgstr "Er&weiterungen"
|
|
||||||
|
|
||||||
#. Settings menu
|
|
||||||
#: ../resources/qml/Cura.qml:107
|
|
||||||
msgctxt "Cura|"
|
|
||||||
msgid "&Settings"
|
|
||||||
msgstr "&Einstellungen"
|
|
||||||
|
|
||||||
#. Help menu
|
|
||||||
#: ../resources/qml/Cura.qml:114
|
|
||||||
msgctxt "Cura|"
|
|
||||||
msgid "&Help"
|
|
||||||
msgstr "&Hilfe"
|
|
||||||
|
|
||||||
#. View Mode toolbar button
|
|
||||||
#: ../resources/qml/Cura.qml:231
|
|
||||||
msgctxt "Cura|"
|
|
||||||
msgid "View Mode"
|
|
||||||
msgstr "Ansichtsmodus"
|
|
||||||
|
|
||||||
#. View preferences page title
|
|
||||||
#: ../resources/qml/Cura.qml:273
|
|
||||||
msgctxt "Cura|"
|
|
||||||
msgid "View"
|
|
||||||
msgstr "Ansicht"
|
|
||||||
|
|
||||||
#. File open dialog title
|
|
||||||
#: ../resources/qml/Cura.qml:370
|
|
||||||
msgctxt "Cura|"
|
|
||||||
msgid "Open File"
|
|
||||||
msgstr "Datei öffnen"
|
|
||||||
|
|
||||||
#. File save dialog title
|
|
||||||
#: ../resources/qml/Cura.qml:386
|
|
||||||
msgctxt "Cura|"
|
|
||||||
msgid "Save File"
|
|
||||||
msgstr "Datei speichern"
|
|
||||||
|
|
||||||
#. Engine Log dialog title
|
|
||||||
#: ../resources/qml/EngineLog.qml:11
|
|
||||||
msgctxt "EngineLog|"
|
|
||||||
msgid "Engine Log"
|
|
||||||
msgstr "Engine-Protokoll"
|
|
||||||
|
|
||||||
#. Close engine log button
|
|
||||||
#: ../resources/qml/EngineLog.qml:30
|
|
||||||
msgctxt "EngineLog|"
|
|
||||||
msgid "Close"
|
|
||||||
msgstr "Schließen"
|
|
||||||
|
|
||||||
#. Firmware update status label
|
|
||||||
#: ../plugins/USBPrinting/FirmwareUpdateWindow.qml:16
|
|
||||||
msgctxt "FirmwareUpdateWindow|"
|
|
||||||
msgid "Starting firmware update, this may take a while."
|
|
||||||
msgstr "Das Firmware-Update wird gestartet. Dies kann eine Weile dauern."
|
|
||||||
|
|
||||||
#. Firmware update status label
|
|
||||||
#: ../plugins/USBPrinting/FirmwareUpdateWindow.qml:21
|
|
||||||
msgctxt "FirmwareUpdateWindow|"
|
|
||||||
msgid "Firmware update completed."
|
|
||||||
msgstr "Firmware-Update abgeschlossen."
|
|
||||||
|
|
||||||
#. Firmware update status label
|
|
||||||
#: ../plugins/USBPrinting/FirmwareUpdateWindow.qml:26
|
|
||||||
msgctxt "FirmwareUpdateWindow|"
|
|
||||||
msgid "Updating firmware."
|
|
||||||
msgstr "Die Firmware wird aktualisiert."
|
|
||||||
|
|
||||||
#. Print material amount save button label
|
|
||||||
#: ../resources/qml/SaveButton.qml:149
|
|
||||||
#, qt-format
|
|
||||||
msgctxt "SaveButton|"
|
|
||||||
msgid "%1m material"
|
|
||||||
msgstr "%1m Material"
|
|
||||||
|
|
||||||
#. Save button label
|
|
||||||
#: ../resources/qml/SaveButton.qml:191
|
|
||||||
msgctxt "SaveButton|"
|
|
||||||
msgid "Please load a 3D model"
|
|
||||||
msgstr "Laden Sie ein 3D-Modell"
|
|
||||||
|
|
||||||
#. Save button label
|
|
||||||
#: ../resources/qml/SaveButton.qml:194
|
|
||||||
msgctxt "SaveButton|"
|
|
||||||
msgid "Calculating Print-time"
|
|
||||||
msgstr "Die Druck-Dauer wird berechnet"
|
|
||||||
|
|
||||||
#. Save button label
|
|
||||||
#: ../resources/qml/SaveButton.qml:197
|
|
||||||
msgctxt "SaveButton|"
|
|
||||||
msgid "Estimated Print-time"
|
|
||||||
msgstr "Geschätzte Druck-Dauer"
|
|
||||||
|
|
||||||
#. Simple configuration mode option
|
|
||||||
#: ../resources/qml/Sidebar.qml:105
|
|
||||||
msgctxt "Sidebar|"
|
|
||||||
msgid "Simple"
|
|
||||||
msgstr "Einfach"
|
|
||||||
|
|
||||||
#. Advanced configuration mode option
|
|
||||||
#: ../resources/qml/Sidebar.qml:107
|
|
||||||
msgctxt "Sidebar|"
|
|
||||||
msgid "Advanced"
|
|
||||||
msgstr "Erweitert"
|
|
||||||
|
|
||||||
#. Configuration mode label
|
|
||||||
#: ../resources/qml/SidebarHeader.qml:26
|
|
||||||
msgctxt "SidebarHeader|"
|
|
||||||
msgid "Mode:"
|
|
||||||
msgstr "Modus:"
|
|
||||||
|
|
||||||
#. Machine selection label
|
|
||||||
#: ../resources/qml/SidebarHeader.qml:70
|
|
||||||
msgctxt "SidebarHeader|"
|
|
||||||
msgid "Machine:"
|
|
||||||
msgstr "Maschine:"
|
|
||||||
|
|
||||||
#. Sidebar header label
|
|
||||||
#: ../resources/qml/SidebarHeader.qml:117
|
|
||||||
msgctxt "SidebarHeader|"
|
|
||||||
msgid "Print Setup"
|
|
||||||
msgstr "Druckkonfiguration"
|
|
||||||
|
|
||||||
#. Sidebar configuration label
|
|
||||||
#: ../resources/qml/SidebarSimple.qml:40
|
|
||||||
msgctxt "SidebarSimple|"
|
|
||||||
msgid "No Model Loaded"
|
|
||||||
msgstr "Kein Modell geladen"
|
|
||||||
|
|
||||||
#. Sidebar configuration label
|
|
||||||
#: ../resources/qml/SidebarSimple.qml:45
|
|
||||||
msgctxt "SidebarSimple|"
|
|
||||||
msgid "Calculating..."
|
|
||||||
msgstr "Die Berechnung läuft..."
|
|
||||||
|
|
||||||
#. Sidebar configuration label
|
|
||||||
#: ../resources/qml/SidebarSimple.qml:50
|
|
||||||
msgctxt "SidebarSimple|"
|
|
||||||
msgid "Estimated Print Time"
|
|
||||||
msgstr "Geschätzte Druck-Dauer"
|
|
||||||
|
|
||||||
#. Quality slider label
|
|
||||||
#: ../resources/qml/SidebarSimple.qml:87
|
|
||||||
msgctxt "SidebarSimple|"
|
|
||||||
msgid ""
|
|
||||||
"Minimum\n"
|
|
||||||
"Draft"
|
|
||||||
msgstr "Minimal\nEntwurf"
|
|
||||||
|
|
||||||
#. Quality slider label
|
|
||||||
#: ../resources/qml/SidebarSimple.qml:97
|
|
||||||
msgctxt "SidebarSimple|"
|
|
||||||
msgid ""
|
|
||||||
"Maximum\n"
|
|
||||||
"Quality"
|
|
||||||
msgstr "Maximal\nQualität"
|
|
||||||
|
|
||||||
#. Setting checkbox
|
|
||||||
#: ../resources/qml/SidebarSimple.qml:109
|
|
||||||
msgctxt "SidebarSimple|"
|
|
||||||
msgid "Enable Support"
|
|
||||||
msgstr "Stützstruktur aktivieren"
|
|
||||||
|
|
||||||
#. View configuration page title
|
|
||||||
#: ../resources/qml/ViewPage.qml:9
|
|
||||||
msgctxt "ViewPage|"
|
|
||||||
msgid "View"
|
|
||||||
msgstr "Ansicht"
|
|
||||||
|
|
||||||
#. Display Overhang preference checkbox
|
|
||||||
#: ../resources/qml/ViewPage.qml:24
|
|
||||||
msgctxt "ViewPage|"
|
|
||||||
msgid "Display Overhang"
|
|
||||||
msgstr "Überhang anzeigen"
|
|
@ -1,434 +0,0 @@
|
|||||||
msgid ""
|
|
||||||
msgstr ""
|
|
||||||
"MIME-Version: 1.0\n"
|
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
|
||||||
"X-Qt-Contexts: true\n"
|
|
||||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
|
||||||
"Project-Id-Version: cura_0\n"
|
|
||||||
"POT-Creation-Date: \n"
|
|
||||||
"PO-Revision-Date: \n"
|
|
||||||
"Last-Translator: \n"
|
|
||||||
"Language-Team: Romain Di Vozzo <romaindivozzo@hotmail.com>\n"
|
|
||||||
"Language: es\n"
|
|
||||||
"X-Generator: Poedit 1.8.1\n"
|
|
||||||
|
|
||||||
#. About dialog title
|
|
||||||
#: ../resources/qml/AboutDialog.qml:12
|
|
||||||
msgctxt "AboutDialog|"
|
|
||||||
msgid "About Cura"
|
|
||||||
msgstr "Acerca de Cura"
|
|
||||||
|
|
||||||
#. About dialog application description
|
|
||||||
#: ../resources/qml/AboutDialog.qml:42
|
|
||||||
msgctxt "AboutDialog|"
|
|
||||||
msgid "End-to-end solution for fused filament 3D printing."
|
|
||||||
msgstr "Solución de extremo a extremo para impresion 3D. "
|
|
||||||
|
|
||||||
#. About dialog application author note
|
|
||||||
#: ../resources/qml/AboutDialog.qml:47
|
|
||||||
msgctxt "AboutDialog|"
|
|
||||||
msgid "Cura has been developed by Ultimaker B.V. in cooperation with the community."
|
|
||||||
msgstr "Cura ha sido desarrollado por Ultimaker B.V. en cooperación con la comunidad."
|
|
||||||
|
|
||||||
#. Close about dialog button
|
|
||||||
#: ../resources/qml/AboutDialog.qml:58
|
|
||||||
msgctxt "AboutDialog|"
|
|
||||||
msgid "Close"
|
|
||||||
msgstr "Cerrar"
|
|
||||||
|
|
||||||
#. Undo action
|
|
||||||
#: ../resources/qml/Actions.qml:37
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "&Undo"
|
|
||||||
msgstr "Deshacer"
|
|
||||||
|
|
||||||
#. Redo action
|
|
||||||
#: ../resources/qml/Actions.qml:45
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "&Redo"
|
|
||||||
msgstr "Rehacer"
|
|
||||||
|
|
||||||
#. Quit action
|
|
||||||
#: ../resources/qml/Actions.qml:53
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "&Quit"
|
|
||||||
msgstr "Salir"
|
|
||||||
|
|
||||||
#. Preferences action
|
|
||||||
#: ../resources/qml/Actions.qml:61
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "&Preferences..."
|
|
||||||
msgstr "Preferencias..."
|
|
||||||
|
|
||||||
#. Add Printer action
|
|
||||||
#: ../resources/qml/Actions.qml:68
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "&Add Printer..."
|
|
||||||
msgstr "Añadir una Impresora…"
|
|
||||||
|
|
||||||
#. Configure Printers action
|
|
||||||
#: ../resources/qml/Actions.qml:74
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "&Configure Printers"
|
|
||||||
msgstr "Configurar las Impresoras"
|
|
||||||
|
|
||||||
#. Show Online Documentation action
|
|
||||||
#: ../resources/qml/Actions.qml:81
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "Show Online &Documentation"
|
|
||||||
msgstr "Mostrar la Documentación en Línea"
|
|
||||||
|
|
||||||
#. Report a Bug Action
|
|
||||||
#: ../resources/qml/Actions.qml:89
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "Report a &Bug"
|
|
||||||
msgstr "Reportar un Error"
|
|
||||||
|
|
||||||
#. About action
|
|
||||||
#: ../resources/qml/Actions.qml:96
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "&About..."
|
|
||||||
msgstr "Acerca de..."
|
|
||||||
|
|
||||||
#. Delete selection action
|
|
||||||
#: ../resources/qml/Actions.qml:103
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "Delete Selection"
|
|
||||||
msgstr "Borrar la Selección"
|
|
||||||
|
|
||||||
#. Delete object action
|
|
||||||
#: ../resources/qml/Actions.qml:111
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "Delete Object"
|
|
||||||
msgstr "Borrar el Objeto"
|
|
||||||
|
|
||||||
#. Center object action
|
|
||||||
#: ../resources/qml/Actions.qml:118
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "Center Object on Platform"
|
|
||||||
msgstr "Centrar el Objeto en la Plataforma"
|
|
||||||
|
|
||||||
#. Duplicate object action
|
|
||||||
#: ../resources/qml/Actions.qml:124
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "Duplicate Object"
|
|
||||||
msgstr "Duplicar el Objeto"
|
|
||||||
|
|
||||||
#. Split object action
|
|
||||||
#: ../resources/qml/Actions.qml:130
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "Split Object into Parts"
|
|
||||||
msgstr "Separar el objeto en partes"
|
|
||||||
|
|
||||||
#. Clear build platform action
|
|
||||||
#: ../resources/qml/Actions.qml:137
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "Clear Build Platform"
|
|
||||||
msgstr "Vaciar la Plataforma"
|
|
||||||
|
|
||||||
#. Reload all objects action
|
|
||||||
#: ../resources/qml/Actions.qml:144
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "Reload All Objects"
|
|
||||||
msgstr "Recargar Todos los Objetos"
|
|
||||||
|
|
||||||
#. Reset all positions action
|
|
||||||
#: ../resources/qml/Actions.qml:150
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "Reset All Object Positions"
|
|
||||||
msgstr "Reiniciar la Posición de Todos los Objetos"
|
|
||||||
|
|
||||||
#. Reset all positions action
|
|
||||||
#: ../resources/qml/Actions.qml:156
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "Reset All Object Transformations"
|
|
||||||
msgstr "Reiniciar la Transformación de Todos los Objetos"
|
|
||||||
|
|
||||||
#. Open file action
|
|
||||||
#: ../resources/qml/Actions.qml:162
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "&Open..."
|
|
||||||
msgstr "Abrir..."
|
|
||||||
|
|
||||||
#. Save file action
|
|
||||||
#: ../resources/qml/Actions.qml:170
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "&Save..."
|
|
||||||
msgstr "Guardar..."
|
|
||||||
|
|
||||||
#. Show engine log action
|
|
||||||
#: ../resources/qml/Actions.qml:178
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "Show engine &log..."
|
|
||||||
msgstr "Mostrar el Registro del Motor de Cálculo "
|
|
||||||
|
|
||||||
#. Add Printer dialog title
|
|
||||||
#. ----------
|
|
||||||
#. Add Printer wizard page title
|
|
||||||
#: ../resources/qml/AddMachineWizard.qml:12
|
|
||||||
#: ../resources/qml/AddMachineWizard.qml:19
|
|
||||||
msgctxt "AddMachineWizard|"
|
|
||||||
msgid "Add Printer"
|
|
||||||
msgstr "Añadir una Impresora"
|
|
||||||
|
|
||||||
#. Add Printer wizard page description
|
|
||||||
#: ../resources/qml/AddMachineWizard.qml:25
|
|
||||||
msgctxt "AddMachineWizard|"
|
|
||||||
msgid "Please select the type of printer:"
|
|
||||||
msgstr "Seleccionar un Tipo de Impresora:"
|
|
||||||
|
|
||||||
#. Add Printer wizard field label
|
|
||||||
#: ../resources/qml/AddMachineWizard.qml:40
|
|
||||||
msgctxt "AddMachineWizard|"
|
|
||||||
msgid "Printer Name:"
|
|
||||||
msgstr "Nombre de la Impresora:"
|
|
||||||
|
|
||||||
#. Add Printer wizarad button
|
|
||||||
#: ../resources/qml/AddMachineWizard.qml:53
|
|
||||||
msgctxt "AddMachineWizard|"
|
|
||||||
msgid "Next"
|
|
||||||
msgstr "Siguiente"
|
|
||||||
|
|
||||||
#. Add Printer wizarad button
|
|
||||||
#: ../resources/qml/AddMachineWizard.qml:63
|
|
||||||
msgctxt "AddMachineWizard|"
|
|
||||||
msgid "Cancel"
|
|
||||||
msgstr "Cancelar"
|
|
||||||
|
|
||||||
# ?? -> %1
|
|
||||||
#. USB Printing dialog label, %1 is head temperature
|
|
||||||
#: ../plugins/USBPrinting/ControlWindow.qml:15
|
|
||||||
#, qt-format
|
|
||||||
msgctxt "ControlWindow|"
|
|
||||||
msgid "Extruder Temperature %1"
|
|
||||||
msgstr "Temperatura del Extrusor (%1)"
|
|
||||||
|
|
||||||
# ?? -> %1
|
|
||||||
#. USB Printing dialog label, %1 is bed temperature
|
|
||||||
#: ../plugins/USBPrinting/ControlWindow.qml:20
|
|
||||||
#, qt-format
|
|
||||||
msgctxt "ControlWindow|"
|
|
||||||
msgid "Bed Temperature %1"
|
|
||||||
msgstr "Temperatura de la Plataforma %1"
|
|
||||||
|
|
||||||
#. USB Printing dialog start print button
|
|
||||||
#: ../plugins/USBPrinting/ControlWindow.qml:33
|
|
||||||
msgctxt "ControlWindow|"
|
|
||||||
msgid "Print"
|
|
||||||
msgstr "Imprimir "
|
|
||||||
|
|
||||||
#. USB Printing dialog cancel print button
|
|
||||||
#: ../plugins/USBPrinting/ControlWindow.qml:40
|
|
||||||
msgctxt "ControlWindow|"
|
|
||||||
msgid "Cancel"
|
|
||||||
msgstr "Cancelar"
|
|
||||||
|
|
||||||
#. Cura application window title
|
|
||||||
#: ../resources/qml/Cura.qml:14
|
|
||||||
msgctxt "Cura|"
|
|
||||||
msgid "Cura"
|
|
||||||
msgstr "Cura"
|
|
||||||
|
|
||||||
#. File menu
|
|
||||||
#: ../resources/qml/Cura.qml:26
|
|
||||||
msgctxt "Cura|"
|
|
||||||
msgid "&File"
|
|
||||||
msgstr "Archivo"
|
|
||||||
|
|
||||||
#. Edit menu
|
|
||||||
#: ../resources/qml/Cura.qml:38
|
|
||||||
msgctxt "Cura|"
|
|
||||||
msgid "&Edit"
|
|
||||||
msgstr "Editar"
|
|
||||||
|
|
||||||
#. Machine menu
|
|
||||||
#: ../resources/qml/Cura.qml:50
|
|
||||||
msgctxt "Cura|"
|
|
||||||
msgid "&Machine"
|
|
||||||
msgstr "Maquina"
|
|
||||||
|
|
||||||
#. Extensions menu
|
|
||||||
#: ../resources/qml/Cura.qml:76
|
|
||||||
msgctxt "Cura|"
|
|
||||||
msgid "E&xtensions"
|
|
||||||
msgstr "Extensiones"
|
|
||||||
|
|
||||||
#. Settings menu
|
|
||||||
#: ../resources/qml/Cura.qml:107
|
|
||||||
msgctxt "Cura|"
|
|
||||||
msgid "&Settings"
|
|
||||||
msgstr "Ajustes"
|
|
||||||
|
|
||||||
#. Help menu
|
|
||||||
#: ../resources/qml/Cura.qml:114
|
|
||||||
msgctxt "Cura|"
|
|
||||||
msgid "&Help"
|
|
||||||
msgstr "Ayuda"
|
|
||||||
|
|
||||||
#. View Mode toolbar button
|
|
||||||
#: ../resources/qml/Cura.qml:231
|
|
||||||
msgctxt "Cura|"
|
|
||||||
msgid "View Mode"
|
|
||||||
msgstr "Modo de Visualización "
|
|
||||||
|
|
||||||
#. View preferences page title
|
|
||||||
#: ../resources/qml/Cura.qml:273
|
|
||||||
msgctxt "Cura|"
|
|
||||||
msgid "View"
|
|
||||||
msgstr "Visualización "
|
|
||||||
|
|
||||||
#. File open dialog title
|
|
||||||
#: ../resources/qml/Cura.qml:370
|
|
||||||
msgctxt "Cura|"
|
|
||||||
msgid "Open File"
|
|
||||||
msgstr "Abrir el Archivo"
|
|
||||||
|
|
||||||
#. File save dialog title
|
|
||||||
#: ../resources/qml/Cura.qml:386
|
|
||||||
msgctxt "Cura|"
|
|
||||||
msgid "Save File"
|
|
||||||
msgstr "Guardar el Archivo"
|
|
||||||
|
|
||||||
#. Engine Log dialog title
|
|
||||||
#: ../resources/qml/EngineLog.qml:11
|
|
||||||
msgctxt "EngineLog|"
|
|
||||||
msgid "Engine Log"
|
|
||||||
msgstr "Registro del Motor de Cálculo "
|
|
||||||
|
|
||||||
#. Close engine log button
|
|
||||||
#: ../resources/qml/EngineLog.qml:30
|
|
||||||
msgctxt "EngineLog|"
|
|
||||||
msgid "Close"
|
|
||||||
msgstr "Cerrar"
|
|
||||||
|
|
||||||
#. Firmware update status label
|
|
||||||
#: ../plugins/USBPrinting/FirmwareUpdateWindow.qml:16
|
|
||||||
msgctxt "FirmwareUpdateWindow|"
|
|
||||||
msgid "Starting firmware update, this may take a while."
|
|
||||||
msgstr "Empezando la Actualización del Firmware, este proceso puede tardar un rato."
|
|
||||||
|
|
||||||
#. Firmware update status label
|
|
||||||
#: ../plugins/USBPrinting/FirmwareUpdateWindow.qml:21
|
|
||||||
msgctxt "FirmwareUpdateWindow|"
|
|
||||||
msgid "Firmware update completed."
|
|
||||||
msgstr "Actualización de Firmware completada."
|
|
||||||
|
|
||||||
#. Firmware update status label
|
|
||||||
#: ../plugins/USBPrinting/FirmwareUpdateWindow.qml:26
|
|
||||||
msgctxt "FirmwareUpdateWindow|"
|
|
||||||
msgid "Updating firmware."
|
|
||||||
msgstr "Actualizando el Firmware."
|
|
||||||
|
|
||||||
#. Print material amount save button label
|
|
||||||
#: ../resources/qml/SaveButton.qml:149
|
|
||||||
#, qt-format
|
|
||||||
msgctxt "SaveButton|"
|
|
||||||
msgid "%1m material"
|
|
||||||
msgstr "%1m de material"
|
|
||||||
|
|
||||||
#. Save button label
|
|
||||||
#: ../resources/qml/SaveButton.qml:191
|
|
||||||
msgctxt "SaveButton|"
|
|
||||||
msgid "Please load a 3D model"
|
|
||||||
msgstr "Cargar un Archivo 3D"
|
|
||||||
|
|
||||||
#. Save button label
|
|
||||||
#: ../resources/qml/SaveButton.qml:194
|
|
||||||
msgctxt "SaveButton|"
|
|
||||||
msgid "Calculating Print-time"
|
|
||||||
msgstr "Calculando la Duración de la Impresión "
|
|
||||||
|
|
||||||
#. Save button label
|
|
||||||
#: ../resources/qml/SaveButton.qml:197
|
|
||||||
msgctxt "SaveButton|"
|
|
||||||
msgid "Estimated Print-time"
|
|
||||||
msgstr "Duración Estimada de la Impresión"
|
|
||||||
|
|
||||||
#. Simple configuration mode option
|
|
||||||
#: ../resources/qml/Sidebar.qml:105
|
|
||||||
msgctxt "Sidebar|"
|
|
||||||
msgid "Simple"
|
|
||||||
msgstr "Simple"
|
|
||||||
|
|
||||||
#. Advanced configuration mode option
|
|
||||||
#: ../resources/qml/Sidebar.qml:107
|
|
||||||
msgctxt "Sidebar|"
|
|
||||||
msgid "Advanced"
|
|
||||||
msgstr "Avanzado"
|
|
||||||
|
|
||||||
#. Configuration mode label
|
|
||||||
#: ../resources/qml/SidebarHeader.qml:26
|
|
||||||
msgctxt "SidebarHeader|"
|
|
||||||
msgid "Mode:"
|
|
||||||
msgstr "Modo:"
|
|
||||||
|
|
||||||
#. Machine selection label
|
|
||||||
#: ../resources/qml/SidebarHeader.qml:70
|
|
||||||
msgctxt "SidebarHeader|"
|
|
||||||
msgid "Machine:"
|
|
||||||
msgstr "Máquina:"
|
|
||||||
|
|
||||||
#. Sidebar header label
|
|
||||||
#: ../resources/qml/SidebarHeader.qml:117
|
|
||||||
msgctxt "SidebarHeader|"
|
|
||||||
msgid "Print Setup"
|
|
||||||
msgstr "Configurar la Impresión"
|
|
||||||
|
|
||||||
#. Sidebar configuration label
|
|
||||||
#: ../resources/qml/SidebarSimple.qml:40
|
|
||||||
msgctxt "SidebarSimple|"
|
|
||||||
msgid "No Model Loaded"
|
|
||||||
msgstr "Ningún Modelo Cargado"
|
|
||||||
|
|
||||||
#. Sidebar configuration label
|
|
||||||
#: ../resources/qml/SidebarSimple.qml:45
|
|
||||||
msgctxt "SidebarSimple|"
|
|
||||||
msgid "Calculating..."
|
|
||||||
msgstr "Calculando..."
|
|
||||||
|
|
||||||
#. Sidebar configuration label
|
|
||||||
#: ../resources/qml/SidebarSimple.qml:50
|
|
||||||
msgctxt "SidebarSimple|"
|
|
||||||
msgid "Estimated Print Time"
|
|
||||||
msgstr "Duración Estimada de la Impresión"
|
|
||||||
|
|
||||||
# a small doubt on the word "calado
|
|
||||||
# "...
|
|
||||||
#. Quality slider label
|
|
||||||
#: ../resources/qml/SidebarSimple.qml:87
|
|
||||||
msgctxt "SidebarSimple|"
|
|
||||||
msgid ""
|
|
||||||
"Minimum\n"
|
|
||||||
"Draft"
|
|
||||||
msgstr ""
|
|
||||||
"Calado\n"
|
|
||||||
"Mínimo "
|
|
||||||
|
|
||||||
#. Quality slider label
|
|
||||||
#: ../resources/qml/SidebarSimple.qml:97
|
|
||||||
msgctxt "SidebarSimple|"
|
|
||||||
msgid ""
|
|
||||||
"Maximum\n"
|
|
||||||
"Quality"
|
|
||||||
msgstr ""
|
|
||||||
"Calidad\n"
|
|
||||||
"Máxima"
|
|
||||||
|
|
||||||
#. Setting checkbox
|
|
||||||
#: ../resources/qml/SidebarSimple.qml:109
|
|
||||||
msgctxt "SidebarSimple|"
|
|
||||||
msgid "Enable Support"
|
|
||||||
msgstr "Habilitar Soporte"
|
|
||||||
|
|
||||||
#. View configuration page title
|
|
||||||
#: ../resources/qml/ViewPage.qml:9
|
|
||||||
msgctxt "ViewPage|"
|
|
||||||
msgid "View"
|
|
||||||
msgstr "Visualizar "
|
|
||||||
|
|
||||||
#. Display Overhang preference checkbox
|
|
||||||
#: ../resources/qml/ViewPage.qml:24
|
|
||||||
msgctxt "ViewPage|"
|
|
||||||
msgid "Display Overhang"
|
|
||||||
msgstr "Visualizar los Voladizos"
|
|
@ -1,426 +0,0 @@
|
|||||||
msgid ""
|
|
||||||
msgstr ""
|
|
||||||
"MIME-Version: 1.0\n"
|
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
|
||||||
"X-Qt-Contexts: true\n"
|
|
||||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
|
||||||
"Project-Id-Version: \n"
|
|
||||||
"POT-Creation-Date: \n"
|
|
||||||
"PO-Revision-Date: \n"
|
|
||||||
"Last-Translator: Tapio <info@tapimex.fi>\n"
|
|
||||||
"Language-Team: \n"
|
|
||||||
"Language: fi_FI\n"
|
|
||||||
"X-Generator: Poedit 1.8.1\n"
|
|
||||||
|
|
||||||
#. About dialog title
|
|
||||||
#: ../resources/qml/AboutDialog.qml:12
|
|
||||||
msgctxt "AboutDialog|"
|
|
||||||
msgid "About Cura"
|
|
||||||
msgstr "Tietoja Curasta"
|
|
||||||
|
|
||||||
#. About dialog application description
|
|
||||||
#: ../resources/qml/AboutDialog.qml:42
|
|
||||||
msgctxt "AboutDialog|"
|
|
||||||
msgid "End-to-end solution for fused filament 3D printing."
|
|
||||||
msgstr "Kokonaisvaltainen sulatettavan tulostuslangan 3D-tulostusratkaisu."
|
|
||||||
|
|
||||||
#. About dialog application author note
|
|
||||||
#: ../resources/qml/AboutDialog.qml:47
|
|
||||||
msgctxt "AboutDialog|"
|
|
||||||
msgid "Cura has been developed by Ultimaker B.V. in cooperation with the community."
|
|
||||||
msgstr "Cura-ohjelman on kehittänyt Ultimaker B.V. yhteistyössä yhteisön kanssa."
|
|
||||||
|
|
||||||
#. Close about dialog button
|
|
||||||
#: ../resources/qml/AboutDialog.qml:58
|
|
||||||
msgctxt "AboutDialog|"
|
|
||||||
msgid "Close"
|
|
||||||
msgstr "Sulje"
|
|
||||||
|
|
||||||
#. Undo action
|
|
||||||
#: ../resources/qml/Actions.qml:37
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "&Undo"
|
|
||||||
msgstr "&Kumoa"
|
|
||||||
|
|
||||||
#. Redo action
|
|
||||||
#: ../resources/qml/Actions.qml:45
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "&Redo"
|
|
||||||
msgstr "Tee &uudelleen"
|
|
||||||
|
|
||||||
#. Quit action
|
|
||||||
#: ../resources/qml/Actions.qml:53
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "&Quit"
|
|
||||||
msgstr "&Lopeta"
|
|
||||||
|
|
||||||
#. Preferences action
|
|
||||||
#: ../resources/qml/Actions.qml:61
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "&Preferences..."
|
|
||||||
msgstr "&Suosikkiasetukset..."
|
|
||||||
|
|
||||||
#. Add Printer action
|
|
||||||
#: ../resources/qml/Actions.qml:68
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "&Add Printer..."
|
|
||||||
msgstr "L&isää tulostin..."
|
|
||||||
|
|
||||||
#. Configure Printers action
|
|
||||||
#: ../resources/qml/Actions.qml:74
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "&Configure Printers"
|
|
||||||
msgstr "&Määritä tulostimet"
|
|
||||||
|
|
||||||
#. Show Online Documentation action
|
|
||||||
#: ../resources/qml/Actions.qml:81
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "Show Online &Documentation"
|
|
||||||
msgstr "Näytä sähköinen &dokumentaatio"
|
|
||||||
|
|
||||||
#. Report a Bug Action
|
|
||||||
#: ../resources/qml/Actions.qml:89
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "Report a &Bug"
|
|
||||||
msgstr "Ilmoita &virheestä"
|
|
||||||
|
|
||||||
#. About action
|
|
||||||
#: ../resources/qml/Actions.qml:96
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "&About..."
|
|
||||||
msgstr "Ti&etoja..."
|
|
||||||
|
|
||||||
#. Delete selection action
|
|
||||||
#: ../resources/qml/Actions.qml:103
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "Delete Selection"
|
|
||||||
msgstr "Poista valinta"
|
|
||||||
|
|
||||||
#. Delete object action
|
|
||||||
#: ../resources/qml/Actions.qml:111
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "Delete Object"
|
|
||||||
msgstr "Poista kohde"
|
|
||||||
|
|
||||||
#. Center object action
|
|
||||||
#: ../resources/qml/Actions.qml:118
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "Center Object on Platform"
|
|
||||||
msgstr "Keskitä kohde alustalle"
|
|
||||||
|
|
||||||
#. Duplicate object action
|
|
||||||
#: ../resources/qml/Actions.qml:124
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "Duplicate Object"
|
|
||||||
msgstr "Monista kohde"
|
|
||||||
|
|
||||||
#. Split object action
|
|
||||||
#: ../resources/qml/Actions.qml:130
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "Split Object into Parts"
|
|
||||||
msgstr "Jaa kohde osiin"
|
|
||||||
|
|
||||||
#. Clear build platform action
|
|
||||||
#: ../resources/qml/Actions.qml:137
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "Clear Build Platform"
|
|
||||||
msgstr "Tyhjennä alusta"
|
|
||||||
|
|
||||||
#. Reload all objects action
|
|
||||||
#: ../resources/qml/Actions.qml:144
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "Reload All Objects"
|
|
||||||
msgstr "Lataa kaikki kohteet uudelleen"
|
|
||||||
|
|
||||||
#. Reset all positions action
|
|
||||||
#: ../resources/qml/Actions.qml:150
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "Reset All Object Positions"
|
|
||||||
msgstr "Nollaa kaikki kohteiden sijainnit"
|
|
||||||
|
|
||||||
#. Reset all positions action
|
|
||||||
#: ../resources/qml/Actions.qml:156
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "Reset All Object Transformations"
|
|
||||||
msgstr "Nollaa kaikkien kohteiden muunnokset"
|
|
||||||
|
|
||||||
#. Open file action
|
|
||||||
#: ../resources/qml/Actions.qml:162
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "&Open..."
|
|
||||||
msgstr "&Avaa"
|
|
||||||
|
|
||||||
#. Save file action
|
|
||||||
#: ../resources/qml/Actions.qml:170
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "&Save..."
|
|
||||||
msgstr "&Tallenna"
|
|
||||||
|
|
||||||
#. Show engine log action
|
|
||||||
#: ../resources/qml/Actions.qml:178
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "Show engine &log..."
|
|
||||||
msgstr "Näytä moottorin l&oki"
|
|
||||||
|
|
||||||
#. Add Printer dialog title
|
|
||||||
#. ----------
|
|
||||||
#. Add Printer wizard page title
|
|
||||||
#: ../resources/qml/AddMachineWizard.qml:12
|
|
||||||
#: ../resources/qml/AddMachineWizard.qml:19
|
|
||||||
msgctxt "AddMachineWizard|"
|
|
||||||
msgid "Add Printer"
|
|
||||||
msgstr "Lisää tulostin"
|
|
||||||
|
|
||||||
#. Add Printer wizard page description
|
|
||||||
#: ../resources/qml/AddMachineWizard.qml:25
|
|
||||||
msgctxt "AddMachineWizard|"
|
|
||||||
msgid "Please select the type of printer:"
|
|
||||||
msgstr "Valitse tulostimen tyyppi:"
|
|
||||||
|
|
||||||
#. Add Printer wizard field label
|
|
||||||
#: ../resources/qml/AddMachineWizard.qml:40
|
|
||||||
msgctxt "AddMachineWizard|"
|
|
||||||
msgid "Printer Name:"
|
|
||||||
msgstr "Tulostimen nimi:"
|
|
||||||
|
|
||||||
#. Add Printer wizarad button
|
|
||||||
#: ../resources/qml/AddMachineWizard.qml:53
|
|
||||||
msgctxt "AddMachineWizard|"
|
|
||||||
msgid "Next"
|
|
||||||
msgstr "Seuraava"
|
|
||||||
|
|
||||||
#. Add Printer wizarad button
|
|
||||||
#: ../resources/qml/AddMachineWizard.qml:63
|
|
||||||
msgctxt "AddMachineWizard|"
|
|
||||||
msgid "Cancel"
|
|
||||||
msgstr "Peruuta"
|
|
||||||
|
|
||||||
#. USB Printing dialog label, %1 is head temperature
|
|
||||||
#: ../plugins/USBPrinting/ControlWindow.qml:15
|
|
||||||
#, qt-format
|
|
||||||
msgctxt "ControlWindow|"
|
|
||||||
msgid "Extruder Temperature %1"
|
|
||||||
msgstr "Suulakkeen lämpötila %1"
|
|
||||||
|
|
||||||
#. USB Printing dialog label, %1 is bed temperature
|
|
||||||
#: ../plugins/USBPrinting/ControlWindow.qml:20
|
|
||||||
#, qt-format
|
|
||||||
msgctxt "ControlWindow|"
|
|
||||||
msgid "Bed Temperature %1"
|
|
||||||
msgstr "Pöydän lämpötila %1"
|
|
||||||
|
|
||||||
#. USB Printing dialog start print button
|
|
||||||
#: ../plugins/USBPrinting/ControlWindow.qml:33
|
|
||||||
msgctxt "ControlWindow|"
|
|
||||||
msgid "Print"
|
|
||||||
msgstr "Tulosta"
|
|
||||||
|
|
||||||
#. USB Printing dialog cancel print button
|
|
||||||
#: ../plugins/USBPrinting/ControlWindow.qml:40
|
|
||||||
msgctxt "ControlWindow|"
|
|
||||||
msgid "Cancel"
|
|
||||||
msgstr "Peruuta"
|
|
||||||
|
|
||||||
#. Cura application window title
|
|
||||||
#: ../resources/qml/Cura.qml:14
|
|
||||||
msgctxt "Cura|"
|
|
||||||
msgid "Cura"
|
|
||||||
msgstr "Cura"
|
|
||||||
|
|
||||||
#. File menu
|
|
||||||
#: ../resources/qml/Cura.qml:26
|
|
||||||
msgctxt "Cura|"
|
|
||||||
msgid "&File"
|
|
||||||
msgstr "&Tiedosto"
|
|
||||||
|
|
||||||
#. Edit menu
|
|
||||||
#: ../resources/qml/Cura.qml:38
|
|
||||||
msgctxt "Cura|"
|
|
||||||
msgid "&Edit"
|
|
||||||
msgstr "&Muokkaa"
|
|
||||||
|
|
||||||
#. Machine menu
|
|
||||||
#: ../resources/qml/Cura.qml:50
|
|
||||||
msgctxt "Cura|"
|
|
||||||
msgid "&Machine"
|
|
||||||
msgstr "&Laite"
|
|
||||||
|
|
||||||
#. Extensions menu
|
|
||||||
#: ../resources/qml/Cura.qml:76
|
|
||||||
msgctxt "Cura|"
|
|
||||||
msgid "E&xtensions"
|
|
||||||
msgstr "Laa&jennukset"
|
|
||||||
|
|
||||||
#. Settings menu
|
|
||||||
#: ../resources/qml/Cura.qml:107
|
|
||||||
msgctxt "Cura|"
|
|
||||||
msgid "&Settings"
|
|
||||||
msgstr "&Asetukset"
|
|
||||||
|
|
||||||
#. Help menu
|
|
||||||
#: ../resources/qml/Cura.qml:114
|
|
||||||
msgctxt "Cura|"
|
|
||||||
msgid "&Help"
|
|
||||||
msgstr "&Ohje"
|
|
||||||
|
|
||||||
#. View Mode toolbar button
|
|
||||||
#: ../resources/qml/Cura.qml:231
|
|
||||||
msgctxt "Cura|"
|
|
||||||
msgid "View Mode"
|
|
||||||
msgstr "Näyttötapa"
|
|
||||||
|
|
||||||
#. View preferences page title
|
|
||||||
#: ../resources/qml/Cura.qml:273
|
|
||||||
msgctxt "Cura|"
|
|
||||||
msgid "View"
|
|
||||||
msgstr "Näytä"
|
|
||||||
|
|
||||||
#. File open dialog title
|
|
||||||
#: ../resources/qml/Cura.qml:370
|
|
||||||
msgctxt "Cura|"
|
|
||||||
msgid "Open File"
|
|
||||||
msgstr "Avaa tiedosto"
|
|
||||||
|
|
||||||
#. File save dialog title
|
|
||||||
#: ../resources/qml/Cura.qml:386
|
|
||||||
msgctxt "Cura|"
|
|
||||||
msgid "Save File"
|
|
||||||
msgstr "Tallenna tiedosto"
|
|
||||||
|
|
||||||
#. Engine Log dialog title
|
|
||||||
#: ../resources/qml/EngineLog.qml:11
|
|
||||||
msgctxt "EngineLog|"
|
|
||||||
msgid "Engine Log"
|
|
||||||
msgstr "Moottorin loki"
|
|
||||||
|
|
||||||
#. Close engine log button
|
|
||||||
#: ../resources/qml/EngineLog.qml:30
|
|
||||||
msgctxt "EngineLog|"
|
|
||||||
msgid "Close"
|
|
||||||
msgstr "Sulje"
|
|
||||||
|
|
||||||
#. Firmware update status label
|
|
||||||
#: ../plugins/USBPrinting/FirmwareUpdateWindow.qml:16
|
|
||||||
msgctxt "FirmwareUpdateWindow|"
|
|
||||||
msgid "Starting firmware update, this may take a while."
|
|
||||||
msgstr "Käynnistetään laiteohjelmiston päivitystä, mikä voi kestää hetken."
|
|
||||||
|
|
||||||
#. Firmware update status label
|
|
||||||
#: ../plugins/USBPrinting/FirmwareUpdateWindow.qml:21
|
|
||||||
msgctxt "FirmwareUpdateWindow|"
|
|
||||||
msgid "Firmware update completed."
|
|
||||||
msgstr "Laiteohjelmiston päivitys suoritettu."
|
|
||||||
|
|
||||||
#. Firmware update status label
|
|
||||||
#: ../plugins/USBPrinting/FirmwareUpdateWindow.qml:26
|
|
||||||
msgctxt "FirmwareUpdateWindow|"
|
|
||||||
msgid "Updating firmware."
|
|
||||||
msgstr "Päivitetään laiteohjelmistoa."
|
|
||||||
|
|
||||||
#. Print material amount save button label
|
|
||||||
#: ../resources/qml/SaveButton.qml:149
|
|
||||||
#, qt-format
|
|
||||||
msgctxt "SaveButton|"
|
|
||||||
msgid "%1m material"
|
|
||||||
msgstr "%1m materiaali"
|
|
||||||
|
|
||||||
#. Save button label
|
|
||||||
#: ../resources/qml/SaveButton.qml:191
|
|
||||||
msgctxt "SaveButton|"
|
|
||||||
msgid "Please load a 3D model"
|
|
||||||
msgstr "Lataa 3D-malli"
|
|
||||||
|
|
||||||
#. Save button label
|
|
||||||
#: ../resources/qml/SaveButton.qml:194
|
|
||||||
msgctxt "SaveButton|"
|
|
||||||
msgid "Calculating Print-time"
|
|
||||||
msgstr "Lasketaan tulostusaikaa"
|
|
||||||
|
|
||||||
#. Save button label
|
|
||||||
#: ../resources/qml/SaveButton.qml:197
|
|
||||||
msgctxt "SaveButton|"
|
|
||||||
msgid "Estimated Print-time"
|
|
||||||
msgstr "Arvioitu tulostusaika"
|
|
||||||
|
|
||||||
#. Simple configuration mode option
|
|
||||||
#: ../resources/qml/Sidebar.qml:105
|
|
||||||
msgctxt "Sidebar|"
|
|
||||||
msgid "Simple"
|
|
||||||
msgstr "Perusasetukset"
|
|
||||||
|
|
||||||
#. Advanced configuration mode option
|
|
||||||
#: ../resources/qml/Sidebar.qml:107
|
|
||||||
msgctxt "Sidebar|"
|
|
||||||
msgid "Advanced"
|
|
||||||
msgstr "Lisäasetukset"
|
|
||||||
|
|
||||||
#. Configuration mode label
|
|
||||||
#: ../resources/qml/SidebarHeader.qml:26
|
|
||||||
msgctxt "SidebarHeader|"
|
|
||||||
msgid "Mode:"
|
|
||||||
msgstr "Tila:"
|
|
||||||
|
|
||||||
#. Machine selection label
|
|
||||||
#: ../resources/qml/SidebarHeader.qml:70
|
|
||||||
msgctxt "SidebarHeader|"
|
|
||||||
msgid "Machine:"
|
|
||||||
msgstr "Laite:"
|
|
||||||
|
|
||||||
#. Sidebar header label
|
|
||||||
#: ../resources/qml/SidebarHeader.qml:117
|
|
||||||
msgctxt "SidebarHeader|"
|
|
||||||
msgid "Print Setup"
|
|
||||||
msgstr "Tulostimen asennus"
|
|
||||||
|
|
||||||
#. Sidebar configuration label
|
|
||||||
#: ../resources/qml/SidebarSimple.qml:40
|
|
||||||
msgctxt "SidebarSimple|"
|
|
||||||
msgid "No Model Loaded"
|
|
||||||
msgstr "Ei ladattua mallia"
|
|
||||||
|
|
||||||
#. Sidebar configuration label
|
|
||||||
#: ../resources/qml/SidebarSimple.qml:45
|
|
||||||
msgctxt "SidebarSimple|"
|
|
||||||
msgid "Calculating..."
|
|
||||||
msgstr "Lasketaan..."
|
|
||||||
|
|
||||||
#. Sidebar configuration label
|
|
||||||
#: ../resources/qml/SidebarSimple.qml:50
|
|
||||||
msgctxt "SidebarSimple|"
|
|
||||||
msgid "Estimated Print Time"
|
|
||||||
msgstr "Arvioitu tulostusaika"
|
|
||||||
|
|
||||||
#. Quality slider label
|
|
||||||
#: ../resources/qml/SidebarSimple.qml:87
|
|
||||||
msgctxt "SidebarSimple|"
|
|
||||||
msgid ""
|
|
||||||
"Minimum\n"
|
|
||||||
"Draft"
|
|
||||||
msgstr "Minimivedos"
|
|
||||||
|
|
||||||
#. Quality slider label
|
|
||||||
#: ../resources/qml/SidebarSimple.qml:97
|
|
||||||
msgctxt "SidebarSimple|"
|
|
||||||
msgid ""
|
|
||||||
"Maximum\n"
|
|
||||||
"Quality"
|
|
||||||
msgstr "Maksimilaatu"
|
|
||||||
|
|
||||||
#. Setting checkbox
|
|
||||||
#: ../resources/qml/SidebarSimple.qml:109
|
|
||||||
msgctxt "SidebarSimple|"
|
|
||||||
msgid "Enable Support"
|
|
||||||
msgstr "Ota tuki käyttöön"
|
|
||||||
|
|
||||||
#. View configuration page title
|
|
||||||
#: ../resources/qml/ViewPage.qml:9
|
|
||||||
msgctxt "ViewPage|"
|
|
||||||
msgid "View"
|
|
||||||
msgstr "Näytä"
|
|
||||||
|
|
||||||
#. Display Overhang preference checkbox
|
|
||||||
#: ../resources/qml/ViewPage.qml:24
|
|
||||||
msgctxt "ViewPage|"
|
|
||||||
msgid "Display Overhang"
|
|
||||||
msgstr "Näytä uloke"
|
|
@ -1,498 +0,0 @@
|
|||||||
# ahiemstra <a.hiemstra@ultimaker.com>, 2015.
|
|
||||||
msgid ""
|
|
||||||
msgstr ""
|
|
||||||
"Project-Id-Version: \n"
|
|
||||||
"POT-Creation-Date: \n"
|
|
||||||
"PO-Revision-Date: 2015-06-30 10:35+0100\n"
|
|
||||||
"Last-Translator: ahiemstra <a.hiemstra@ultimaker.com>\n"
|
|
||||||
"Language-Team: English <kde-i18n-doc@kde.org>\n"
|
|
||||||
"Language: en_GB\n"
|
|
||||||
"MIME-Version: 1.0\n"
|
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
|
||||||
"X-Qt-Contexts: true\n"
|
|
||||||
"X-Generator: Lokalize 2.0\n"
|
|
||||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
|
||||||
|
|
||||||
#. About dialog title
|
|
||||||
#: ../resources/qml/AboutDialog.qml:12
|
|
||||||
msgctxt "AboutDialog|"
|
|
||||||
msgid "About Cura"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. About dialog application description
|
|
||||||
#: ../resources/qml/AboutDialog.qml:42
|
|
||||||
msgctxt "AboutDialog|"
|
|
||||||
msgid "End-to-end solution for fused filament 3D printing."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. About dialog application author note
|
|
||||||
#: ../resources/qml/AboutDialog.qml:47
|
|
||||||
msgctxt "AboutDialog|"
|
|
||||||
msgid ""
|
|
||||||
"Cura has been developed by Ultimaker B.V. in cooperation with the community."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. Close about dialog button
|
|
||||||
#: ../resources/qml/AboutDialog.qml:58
|
|
||||||
msgctxt "AboutDialog|"
|
|
||||||
msgid "Close"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. Undo action
|
|
||||||
#: ../resources/qml/Actions.qml:37
|
|
||||||
#, fuzzy
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "&Undo"
|
|
||||||
msgstr "Annuler"
|
|
||||||
|
|
||||||
#. Redo action
|
|
||||||
#: ../resources/qml/Actions.qml:45
|
|
||||||
#, fuzzy
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "&Redo"
|
|
||||||
msgstr "Rétablir"
|
|
||||||
|
|
||||||
#. Quit action
|
|
||||||
#: ../resources/qml/Actions.qml:53
|
|
||||||
#, fuzzy
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "&Quit"
|
|
||||||
msgstr "Quitter"
|
|
||||||
|
|
||||||
#. Preferences action
|
|
||||||
#: ../resources/qml/Actions.qml:61
|
|
||||||
#, fuzzy
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "&Preferences..."
|
|
||||||
msgstr "Préférences"
|
|
||||||
|
|
||||||
#. Add Printer action
|
|
||||||
#: ../resources/qml/Actions.qml:68
|
|
||||||
#, fuzzy
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "&Add Printer..."
|
|
||||||
msgstr "Ajouter une imprimante..."
|
|
||||||
|
|
||||||
#. Configure Printers action
|
|
||||||
#: ../resources/qml/Actions.qml:74
|
|
||||||
#, fuzzy
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "&Configure Printers"
|
|
||||||
msgstr "Configurer les imprimantes"
|
|
||||||
|
|
||||||
#. Show Online Documentation action
|
|
||||||
#: ../resources/qml/Actions.qml:81
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "Show Online &Documentation"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. Report a Bug Action
|
|
||||||
#: ../resources/qml/Actions.qml:89
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "Report a &Bug"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. About action
|
|
||||||
#: ../resources/qml/Actions.qml:96
|
|
||||||
#, fuzzy
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "&About..."
|
|
||||||
msgstr "À propos de..."
|
|
||||||
|
|
||||||
#. Delete selection action
|
|
||||||
#: ../resources/qml/Actions.qml:103
|
|
||||||
#, fuzzy
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "Delete Selection"
|
|
||||||
msgstr "Supprimer la sélection"
|
|
||||||
|
|
||||||
#. Delete object action
|
|
||||||
#: ../resources/qml/Actions.qml:111
|
|
||||||
#, fuzzy
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "Delete Object"
|
|
||||||
msgstr "Supprimer l’objet"
|
|
||||||
|
|
||||||
#. Center object action
|
|
||||||
#: ../resources/qml/Actions.qml:118
|
|
||||||
#, fuzzy
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "Center Object on Platform"
|
|
||||||
msgstr "Centrer l’objet sur le plateau"
|
|
||||||
|
|
||||||
#. Duplicate object action
|
|
||||||
#: ../resources/qml/Actions.qml:124
|
|
||||||
#, fuzzy
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "Duplicate Object"
|
|
||||||
msgstr "Dupliquer l’objet"
|
|
||||||
|
|
||||||
#. Split object action
|
|
||||||
#: ../resources/qml/Actions.qml:130
|
|
||||||
#, fuzzy
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "Split Object into Parts"
|
|
||||||
msgstr "Diviser l’objet en plusieurs parties"
|
|
||||||
|
|
||||||
#. Clear build platform action
|
|
||||||
#: ../resources/qml/Actions.qml:137
|
|
||||||
#, fuzzy
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "Clear Build Platform"
|
|
||||||
msgstr "Effacer les éléments du plateau d’impression"
|
|
||||||
|
|
||||||
#. Reload all objects action
|
|
||||||
#: ../resources/qml/Actions.qml:144
|
|
||||||
#, fuzzy
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "Reload All Objects"
|
|
||||||
msgstr "Recharger tous les objets"
|
|
||||||
|
|
||||||
#. Reset all positions action
|
|
||||||
#: ../resources/qml/Actions.qml:150
|
|
||||||
#, fuzzy
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "Reset All Object Positions"
|
|
||||||
msgstr "Réinitialiser toutes les positions de l’objet"
|
|
||||||
|
|
||||||
#. Reset all positions action
|
|
||||||
#: ../resources/qml/Actions.qml:156
|
|
||||||
#, fuzzy
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "Reset All Object Transformations"
|
|
||||||
msgstr "Réinitialiser toutes les transformations de l’objet"
|
|
||||||
|
|
||||||
#. Open file action
|
|
||||||
#: ../resources/qml/Actions.qml:162
|
|
||||||
#, fuzzy
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "&Open..."
|
|
||||||
msgstr "Ouvrir..."
|
|
||||||
|
|
||||||
#. Save file action
|
|
||||||
#: ../resources/qml/Actions.qml:170
|
|
||||||
#, fuzzy
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "&Save..."
|
|
||||||
msgstr "Enregistrer..."
|
|
||||||
|
|
||||||
#. Show engine log action
|
|
||||||
#: ../resources/qml/Actions.qml:178
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "Show engine &log..."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. Add Printer dialog title
|
|
||||||
#. ----------
|
|
||||||
#. Add Printer wizard page title
|
|
||||||
#: ../resources/qml/AddMachineWizard.qml:12
|
|
||||||
#: ../resources/qml/AddMachineWizard.qml:19
|
|
||||||
msgctxt "AddMachineWizard|"
|
|
||||||
msgid "Add Printer"
|
|
||||||
msgstr "Ajouter une imprimante"
|
|
||||||
|
|
||||||
#. Add Printer wizard page description
|
|
||||||
#: ../resources/qml/AddMachineWizard.qml:25
|
|
||||||
msgctxt "AddMachineWizard|"
|
|
||||||
msgid "Please select the type of printer:"
|
|
||||||
msgstr "Veuillez sélectionner le type d’imprimante :"
|
|
||||||
|
|
||||||
#. Add Printer wizard field label
|
|
||||||
#: ../resources/qml/AddMachineWizard.qml:40
|
|
||||||
msgctxt "AddMachineWizard|"
|
|
||||||
msgid "Printer Name:"
|
|
||||||
msgstr "Nom de l’imprimante :"
|
|
||||||
|
|
||||||
#. Add Printer wizarad button
|
|
||||||
#: ../resources/qml/AddMachineWizard.qml:53
|
|
||||||
msgctxt "AddMachineWizard|"
|
|
||||||
msgid "Next"
|
|
||||||
msgstr "Suivant"
|
|
||||||
|
|
||||||
#. Add Printer wizarad button
|
|
||||||
#: ../resources/qml/AddMachineWizard.qml:63
|
|
||||||
msgctxt "AddMachineWizard|"
|
|
||||||
msgid "Cancel"
|
|
||||||
msgstr "Annuler"
|
|
||||||
|
|
||||||
#. USB Printing dialog label, %1 is head temperature
|
|
||||||
#: ../plugins/USBPrinting/ControlWindow.qml:15
|
|
||||||
#, qt-format
|
|
||||||
msgctxt "ControlWindow|"
|
|
||||||
msgid "Extruder Temperature %1"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. USB Printing dialog label, %1 is bed temperature
|
|
||||||
#: ../plugins/USBPrinting/ControlWindow.qml:20
|
|
||||||
#, qt-format
|
|
||||||
msgctxt "ControlWindow|"
|
|
||||||
msgid "Bed Temperature %1"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. USB Printing dialog start print button
|
|
||||||
#: ../plugins/USBPrinting/ControlWindow.qml:33
|
|
||||||
#, fuzzy
|
|
||||||
msgctxt "ControlWindow|"
|
|
||||||
msgid "Print"
|
|
||||||
msgstr "Ajouter une imprimante"
|
|
||||||
|
|
||||||
#. USB Printing dialog cancel print button
|
|
||||||
#: ../plugins/USBPrinting/ControlWindow.qml:40
|
|
||||||
#, fuzzy
|
|
||||||
msgctxt "ControlWindow|"
|
|
||||||
msgid "Cancel"
|
|
||||||
msgstr "Annuler"
|
|
||||||
|
|
||||||
#. Cura application window title
|
|
||||||
#: ../resources/qml/Cura.qml:14
|
|
||||||
#, fuzzy
|
|
||||||
msgctxt "Cura|"
|
|
||||||
msgid "Cura"
|
|
||||||
msgstr "Cura"
|
|
||||||
|
|
||||||
#. File menu
|
|
||||||
#: ../resources/qml/Cura.qml:26
|
|
||||||
#, fuzzy
|
|
||||||
msgctxt "Cura|"
|
|
||||||
msgid "&File"
|
|
||||||
msgstr "&Fichier"
|
|
||||||
|
|
||||||
#. Edit menu
|
|
||||||
#: ../resources/qml/Cura.qml:38
|
|
||||||
#, fuzzy
|
|
||||||
msgctxt "Cura|"
|
|
||||||
msgid "&Edit"
|
|
||||||
msgstr "M&odifier"
|
|
||||||
|
|
||||||
#. Machine menu
|
|
||||||
#: ../resources/qml/Cura.qml:50
|
|
||||||
#, fuzzy
|
|
||||||
msgctxt "Cura|"
|
|
||||||
msgid "&Machine"
|
|
||||||
msgstr "&Machine"
|
|
||||||
|
|
||||||
#. Extensions menu
|
|
||||||
#: ../resources/qml/Cura.qml:76
|
|
||||||
#, fuzzy
|
|
||||||
msgctxt "Cura|"
|
|
||||||
msgid "E&xtensions"
|
|
||||||
msgstr "&Extensions"
|
|
||||||
|
|
||||||
#. Settings menu
|
|
||||||
#: ../resources/qml/Cura.qml:107
|
|
||||||
#, fuzzy
|
|
||||||
msgctxt "Cura|"
|
|
||||||
msgid "&Settings"
|
|
||||||
msgstr "&Paramètres"
|
|
||||||
|
|
||||||
#. Help menu
|
|
||||||
#: ../resources/qml/Cura.qml:114
|
|
||||||
#, fuzzy
|
|
||||||
msgctxt "Cura|"
|
|
||||||
msgid "&Help"
|
|
||||||
msgstr "&Aide"
|
|
||||||
|
|
||||||
#. View Mode toolbar button
|
|
||||||
#: ../resources/qml/Cura.qml:231
|
|
||||||
#, fuzzy
|
|
||||||
msgctxt "Cura|"
|
|
||||||
msgid "View Mode"
|
|
||||||
msgstr "Mode d’affichage"
|
|
||||||
|
|
||||||
#. View preferences page title
|
|
||||||
#: ../resources/qml/Cura.qml:273
|
|
||||||
#, fuzzy
|
|
||||||
msgctxt "Cura|"
|
|
||||||
msgid "View"
|
|
||||||
msgstr "Afficher"
|
|
||||||
|
|
||||||
#. File open dialog title
|
|
||||||
#: ../resources/qml/Cura.qml:370
|
|
||||||
#, fuzzy
|
|
||||||
msgctxt "Cura|"
|
|
||||||
msgid "Open File"
|
|
||||||
msgstr "Ouvrir un fichier"
|
|
||||||
|
|
||||||
#. File save dialog title
|
|
||||||
#: ../resources/qml/Cura.qml:386
|
|
||||||
#, fuzzy
|
|
||||||
msgctxt "Cura|"
|
|
||||||
msgid "Save File"
|
|
||||||
msgstr "Enregistrer un fichier"
|
|
||||||
|
|
||||||
#. Engine Log dialog title
|
|
||||||
#: ../resources/qml/EngineLog.qml:11
|
|
||||||
msgctxt "EngineLog|"
|
|
||||||
msgid "Engine Log"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. Close engine log button
|
|
||||||
#: ../resources/qml/EngineLog.qml:30
|
|
||||||
msgctxt "EngineLog|"
|
|
||||||
msgid "Close"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. Firmware update status label
|
|
||||||
#: ../plugins/USBPrinting/FirmwareUpdateWindow.qml:16
|
|
||||||
msgctxt "FirmwareUpdateWindow|"
|
|
||||||
msgid "Starting firmware update, this may take a while."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. Firmware update status label
|
|
||||||
#: ../plugins/USBPrinting/FirmwareUpdateWindow.qml:21
|
|
||||||
msgctxt "FirmwareUpdateWindow|"
|
|
||||||
msgid "Firmware update completed."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. Firmware update status label
|
|
||||||
#: ../plugins/USBPrinting/FirmwareUpdateWindow.qml:26
|
|
||||||
msgctxt "FirmwareUpdateWindow|"
|
|
||||||
msgid "Updating firmware."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. Print material amount save button label
|
|
||||||
#: ../resources/qml/SaveButton.qml:149
|
|
||||||
#, qt-format
|
|
||||||
msgctxt "SaveButton|"
|
|
||||||
msgid "%1m material"
|
|
||||||
msgstr "%1m de matériel"
|
|
||||||
|
|
||||||
#. Save button label
|
|
||||||
#: ../resources/qml/SaveButton.qml:191
|
|
||||||
msgctxt "SaveButton|"
|
|
||||||
msgid "Please load a 3D model"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. Save button label
|
|
||||||
#: ../resources/qml/SaveButton.qml:194
|
|
||||||
msgctxt "SaveButton|"
|
|
||||||
msgid "Calculating Print-time"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. Save button label
|
|
||||||
#: ../resources/qml/SaveButton.qml:197
|
|
||||||
msgctxt "SaveButton|"
|
|
||||||
msgid "Estimated Print-time"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. Simple configuration mode option
|
|
||||||
#: ../resources/qml/Sidebar.qml:105
|
|
||||||
msgctxt "Sidebar|"
|
|
||||||
msgid "Simple"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. Advanced configuration mode option
|
|
||||||
#: ../resources/qml/Sidebar.qml:107
|
|
||||||
msgctxt "Sidebar|"
|
|
||||||
msgid "Advanced"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. Configuration mode label
|
|
||||||
#: ../resources/qml/SidebarHeader.qml:26
|
|
||||||
msgctxt "SidebarHeader|"
|
|
||||||
msgid "Mode:"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. Machine selection label
|
|
||||||
#: ../resources/qml/SidebarHeader.qml:70
|
|
||||||
#, fuzzy
|
|
||||||
msgctxt "SidebarHeader|"
|
|
||||||
msgid "Machine:"
|
|
||||||
msgstr "Machine"
|
|
||||||
|
|
||||||
#. Sidebar header label
|
|
||||||
#: ../resources/qml/SidebarHeader.qml:117
|
|
||||||
#, fuzzy
|
|
||||||
msgctxt "SidebarHeader|"
|
|
||||||
msgid "Print Setup"
|
|
||||||
msgstr "Paramètres d’impression"
|
|
||||||
|
|
||||||
#. Sidebar configuration label
|
|
||||||
#: ../resources/qml/SidebarSimple.qml:40
|
|
||||||
msgctxt "SidebarSimple|"
|
|
||||||
msgid "No Model Loaded"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. Sidebar configuration label
|
|
||||||
#: ../resources/qml/SidebarSimple.qml:45
|
|
||||||
msgctxt "SidebarSimple|"
|
|
||||||
msgid "Calculating..."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. Sidebar configuration label
|
|
||||||
#: ../resources/qml/SidebarSimple.qml:50
|
|
||||||
msgctxt "SidebarSimple|"
|
|
||||||
msgid "Estimated Print Time"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. Quality slider label
|
|
||||||
#: ../resources/qml/SidebarSimple.qml:87
|
|
||||||
msgctxt "SidebarSimple|"
|
|
||||||
msgid ""
|
|
||||||
"Minimum\n"
|
|
||||||
"Draft"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. Quality slider label
|
|
||||||
#: ../resources/qml/SidebarSimple.qml:97
|
|
||||||
msgctxt "SidebarSimple|"
|
|
||||||
msgid ""
|
|
||||||
"Maximum\n"
|
|
||||||
"Quality"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. Setting checkbox
|
|
||||||
#: ../resources/qml/SidebarSimple.qml:109
|
|
||||||
msgctxt "SidebarSimple|"
|
|
||||||
msgid "Enable Support"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. View configuration page title
|
|
||||||
#: ../resources/qml/ViewPage.qml:9
|
|
||||||
msgctxt "ViewPage|"
|
|
||||||
msgid "View"
|
|
||||||
msgstr "Afficher"
|
|
||||||
|
|
||||||
#. Display Overhang preference checkbox
|
|
||||||
#: ../resources/qml/ViewPage.qml:24
|
|
||||||
#, fuzzy
|
|
||||||
msgctxt "ViewPage|"
|
|
||||||
msgid "Display Overhang"
|
|
||||||
msgstr "Dépassement de l’affichage"
|
|
||||||
|
|
||||||
#~ msgctxt "OutputGCodeButton|"
|
|
||||||
#~ msgid "Save"
|
|
||||||
#~ msgstr "Enregistrer"
|
|
||||||
|
|
||||||
#~ msgctxt "OutputGCodeButton|"
|
|
||||||
#~ msgid "Write to SD"
|
|
||||||
#~ msgstr "Enregistrer sur la carte SD"
|
|
||||||
|
|
||||||
#~ msgctxt "OutputGCodeButton|"
|
|
||||||
#~ msgid "Send over USB"
|
|
||||||
#~ msgstr "Transférer vers le périphérique USB"
|
|
||||||
|
|
||||||
#~ msgctxt "Printer|"
|
|
||||||
#~ msgid "No extensions loaded"
|
|
||||||
#~ msgstr "Aucune extension téléchargée"
|
|
||||||
|
|
||||||
#~ msgctxt "Printer|"
|
|
||||||
#~ msgid "Open File"
|
|
||||||
#~ msgstr "Ouvrir un fichier"
|
|
||||||
|
|
||||||
#~ msgctxt "PrinterActions|"
|
|
||||||
#~ msgid "Show Manual"
|
|
||||||
#~ msgstr "Afficher les instructions"
|
|
||||||
|
|
||||||
#~ msgctxt "SettingsPane|"
|
|
||||||
#~ msgid "Time"
|
|
||||||
#~ msgstr "Heure"
|
|
||||||
|
|
||||||
#~ msgctxt "SettingsPane|"
|
|
||||||
#~ msgid "Low Quality"
|
|
||||||
#~ msgstr "Basse qualité"
|
|
||||||
|
|
||||||
#~ msgctxt "SettingsPane|"
|
|
||||||
#~ msgid "High Quality"
|
|
||||||
#~ msgstr "Haute qualité"
|
|
@ -1,430 +0,0 @@
|
|||||||
msgid ""
|
|
||||||
msgstr ""
|
|
||||||
"MIME-Version: 1.0\n"
|
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
|
||||||
"X-Qt-Contexts: true\n"
|
|
||||||
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
|
|
||||||
"Project-Id-Version: Cura\n"
|
|
||||||
"POT-Creation-Date: \n"
|
|
||||||
"PO-Revision-Date: \n"
|
|
||||||
"Last-Translator: \n"
|
|
||||||
"Language-Team: \n"
|
|
||||||
"Language: ru\n"
|
|
||||||
"X-Generator: Poedit 1.8.1\n"
|
|
||||||
|
|
||||||
#. About dialog title
|
|
||||||
#: ../resources/qml/AboutDialog.qml:12
|
|
||||||
msgctxt "AboutDialog|"
|
|
||||||
msgid "About Cura"
|
|
||||||
msgstr "О Кура"
|
|
||||||
|
|
||||||
#. About dialog application description
|
|
||||||
#: ../resources/qml/AboutDialog.qml:42
|
|
||||||
msgctxt "AboutDialog|"
|
|
||||||
msgid "End-to-end solution for fused filament 3D printing."
|
|
||||||
msgstr "Комплексное решение для 3D печати по технологии послойного накладывание пластика."
|
|
||||||
|
|
||||||
#. About dialog application author note
|
|
||||||
#: ../resources/qml/AboutDialog.qml:47
|
|
||||||
msgctxt "AboutDialog|"
|
|
||||||
msgid "Cura has been developed by Ultimaker B.V. in cooperation with the community."
|
|
||||||
msgstr "Кура была разработана компании Ultimaker BV в сотрудничестве с сообществом."
|
|
||||||
|
|
||||||
#. Close about dialog button
|
|
||||||
#: ../resources/qml/AboutDialog.qml:58
|
|
||||||
msgctxt "AboutDialog|"
|
|
||||||
msgid "Close"
|
|
||||||
msgstr "Закрыть окно"
|
|
||||||
|
|
||||||
#. Undo action
|
|
||||||
#: ../resources/qml/Actions.qml:37
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "&Undo"
|
|
||||||
msgstr "&Отмена"
|
|
||||||
|
|
||||||
#. Redo action
|
|
||||||
#: ../resources/qml/Actions.qml:45
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "&Redo"
|
|
||||||
msgstr "&Повтор"
|
|
||||||
|
|
||||||
#. Quit action
|
|
||||||
#: ../resources/qml/Actions.qml:53
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "&Quit"
|
|
||||||
msgstr "&Выход"
|
|
||||||
|
|
||||||
#. Preferences action
|
|
||||||
#: ../resources/qml/Actions.qml:61
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "&Preferences..."
|
|
||||||
msgstr "&Настройки программы..."
|
|
||||||
|
|
||||||
#. Add Printer action
|
|
||||||
#: ../resources/qml/Actions.qml:68
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "&Add Printer..."
|
|
||||||
msgstr "&Добавит новый принтер"
|
|
||||||
|
|
||||||
#. Configure Printers action
|
|
||||||
#: ../resources/qml/Actions.qml:74
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "&Configure Printers"
|
|
||||||
msgstr "&Настройки принтера"
|
|
||||||
|
|
||||||
#. Show Online Documentation action
|
|
||||||
#: ../resources/qml/Actions.qml:81
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "Show Online &Documentation"
|
|
||||||
msgstr "Показать онлайн &справку"
|
|
||||||
|
|
||||||
#. Report a Bug Action
|
|
||||||
#: ../resources/qml/Actions.qml:89
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "Report a &Bug"
|
|
||||||
msgstr "Сообщить о &проблеме"
|
|
||||||
|
|
||||||
#. About action
|
|
||||||
#: ../resources/qml/Actions.qml:96
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "&About..."
|
|
||||||
msgstr "&О Кура"
|
|
||||||
|
|
||||||
#. Delete selection action
|
|
||||||
#: ../resources/qml/Actions.qml:103
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "Delete Selection"
|
|
||||||
msgstr "Удалить выбранное"
|
|
||||||
|
|
||||||
#. Delete object action
|
|
||||||
#: ../resources/qml/Actions.qml:111
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "Delete Object"
|
|
||||||
msgstr "Удалить объект"
|
|
||||||
|
|
||||||
#. Center object action
|
|
||||||
#: ../resources/qml/Actions.qml:118
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "Center Object on Platform"
|
|
||||||
msgstr "Расположить объект по центру"
|
|
||||||
|
|
||||||
#. Duplicate object action
|
|
||||||
#: ../resources/qml/Actions.qml:124
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "Duplicate Object"
|
|
||||||
msgstr "Умножить объект"
|
|
||||||
|
|
||||||
#. Split object action
|
|
||||||
#: ../resources/qml/Actions.qml:130
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "Split Object into Parts"
|
|
||||||
msgstr "Разбить объект на частей"
|
|
||||||
|
|
||||||
#. Clear build platform action
|
|
||||||
#: ../resources/qml/Actions.qml:137
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "Clear Build Platform"
|
|
||||||
msgstr "Очистить печатающую платформу"
|
|
||||||
|
|
||||||
#. Reload all objects action
|
|
||||||
#: ../resources/qml/Actions.qml:144
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "Reload All Objects"
|
|
||||||
msgstr "Перезагрузить все объекты"
|
|
||||||
|
|
||||||
#. Reset all positions action
|
|
||||||
#: ../resources/qml/Actions.qml:150
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "Reset All Object Positions"
|
|
||||||
msgstr "Сбросить все позиции объектов"
|
|
||||||
|
|
||||||
#. Reset all positions action
|
|
||||||
#: ../resources/qml/Actions.qml:156
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "Reset All Object Transformations"
|
|
||||||
msgstr "Сбросить все преобразования объектов"
|
|
||||||
|
|
||||||
#. Open file action
|
|
||||||
#: ../resources/qml/Actions.qml:162
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "&Open..."
|
|
||||||
msgstr "&Открыть..."
|
|
||||||
|
|
||||||
#. Save file action
|
|
||||||
#: ../resources/qml/Actions.qml:170
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "&Save..."
|
|
||||||
msgstr "&Сохранить..."
|
|
||||||
|
|
||||||
#. Show engine log action
|
|
||||||
#: ../resources/qml/Actions.qml:178
|
|
||||||
msgctxt "Actions|"
|
|
||||||
msgid "Show engine &log..."
|
|
||||||
msgstr "Показать журнал &слайсера"
|
|
||||||
|
|
||||||
#. Add Printer dialog title
|
|
||||||
#. ----------
|
|
||||||
#. Add Printer wizard page title
|
|
||||||
#: ../resources/qml/AddMachineWizard.qml:12
|
|
||||||
#: ../resources/qml/AddMachineWizard.qml:19
|
|
||||||
msgctxt "AddMachineWizard|"
|
|
||||||
msgid "Add Printer"
|
|
||||||
msgstr "Добавить новый принтер"
|
|
||||||
|
|
||||||
#. Add Printer wizard page description
|
|
||||||
#: ../resources/qml/AddMachineWizard.qml:25
|
|
||||||
msgctxt "AddMachineWizard|"
|
|
||||||
msgid "Please select the type of printer:"
|
|
||||||
msgstr "Выберите тип принтера:"
|
|
||||||
|
|
||||||
#. Add Printer wizard field label
|
|
||||||
#: ../resources/qml/AddMachineWizard.qml:40
|
|
||||||
msgctxt "AddMachineWizard|"
|
|
||||||
msgid "Printer Name:"
|
|
||||||
msgstr "Название принтера:"
|
|
||||||
|
|
||||||
#. Add Printer wizarad button
|
|
||||||
#: ../resources/qml/AddMachineWizard.qml:53
|
|
||||||
msgctxt "AddMachineWizard|"
|
|
||||||
msgid "Next"
|
|
||||||
msgstr "Дальше"
|
|
||||||
|
|
||||||
#. Add Printer wizarad button
|
|
||||||
#: ../resources/qml/AddMachineWizard.qml:63
|
|
||||||
msgctxt "AddMachineWizard|"
|
|
||||||
msgid "Cancel"
|
|
||||||
msgstr "Отменить"
|
|
||||||
|
|
||||||
#. USB Printing dialog label, %1 is head temperature
|
|
||||||
#: ../plugins/USBPrinting/ControlWindow.qml:15
|
|
||||||
#, qt-format
|
|
||||||
msgctxt "ControlWindow|"
|
|
||||||
msgid "Extruder Temperature %1"
|
|
||||||
msgstr "Температура экструдера %1"
|
|
||||||
|
|
||||||
#. USB Printing dialog label, %1 is bed temperature
|
|
||||||
#: ../plugins/USBPrinting/ControlWindow.qml:20
|
|
||||||
#, qt-format
|
|
||||||
msgctxt "ControlWindow|"
|
|
||||||
msgid "Bed Temperature %1"
|
|
||||||
msgstr "Температура платформы %1"
|
|
||||||
|
|
||||||
#. USB Printing dialog start print button
|
|
||||||
#: ../plugins/USBPrinting/ControlWindow.qml:33
|
|
||||||
msgctxt "ControlWindow|"
|
|
||||||
msgid "Print"
|
|
||||||
msgstr "Печать"
|
|
||||||
|
|
||||||
#. USB Printing dialog cancel print button
|
|
||||||
#: ../plugins/USBPrinting/ControlWindow.qml:40
|
|
||||||
msgctxt "ControlWindow|"
|
|
||||||
msgid "Cancel"
|
|
||||||
msgstr "Отменить"
|
|
||||||
|
|
||||||
#. Cura application window title
|
|
||||||
#: ../resources/qml/Cura.qml:14
|
|
||||||
msgctxt "Cura|"
|
|
||||||
msgid "Cura"
|
|
||||||
msgstr "Кура"
|
|
||||||
|
|
||||||
#. File menu
|
|
||||||
#: ../resources/qml/Cura.qml:26
|
|
||||||
msgctxt "Cura|"
|
|
||||||
msgid "&File"
|
|
||||||
msgstr "&Файл"
|
|
||||||
|
|
||||||
#. Edit menu
|
|
||||||
#: ../resources/qml/Cura.qml:38
|
|
||||||
msgctxt "Cura|"
|
|
||||||
msgid "&Edit"
|
|
||||||
msgstr "&Изменить"
|
|
||||||
|
|
||||||
#. Machine menu
|
|
||||||
#: ../resources/qml/Cura.qml:50
|
|
||||||
msgctxt "Cura|"
|
|
||||||
msgid "&Machine"
|
|
||||||
msgstr "&Принтер"
|
|
||||||
|
|
||||||
#. Extensions menu
|
|
||||||
#: ../resources/qml/Cura.qml:76
|
|
||||||
msgctxt "Cura|"
|
|
||||||
msgid "E&xtensions"
|
|
||||||
msgstr "&Расширения"
|
|
||||||
|
|
||||||
#. Settings menu
|
|
||||||
#: ../resources/qml/Cura.qml:107
|
|
||||||
msgctxt "Cura|"
|
|
||||||
msgid "&Settings"
|
|
||||||
msgstr "&Настройки"
|
|
||||||
|
|
||||||
#. Help menu
|
|
||||||
#: ../resources/qml/Cura.qml:114
|
|
||||||
msgctxt "Cura|"
|
|
||||||
msgid "&Help"
|
|
||||||
msgstr "&Помощь"
|
|
||||||
|
|
||||||
#. View Mode toolbar button
|
|
||||||
#: ../resources/qml/Cura.qml:231
|
|
||||||
msgctxt "Cura|"
|
|
||||||
msgid "View Mode"
|
|
||||||
msgstr "Режим просмотра"
|
|
||||||
|
|
||||||
#. View preferences page title
|
|
||||||
#: ../resources/qml/Cura.qml:273
|
|
||||||
msgctxt "Cura|"
|
|
||||||
msgid "View"
|
|
||||||
msgstr "Просмотр"
|
|
||||||
|
|
||||||
#. File open dialog title
|
|
||||||
#: ../resources/qml/Cura.qml:370
|
|
||||||
msgctxt "Cura|"
|
|
||||||
msgid "Open File"
|
|
||||||
msgstr "Открыть файл"
|
|
||||||
|
|
||||||
#. File save dialog title
|
|
||||||
#: ../resources/qml/Cura.qml:386
|
|
||||||
msgctxt "Cura|"
|
|
||||||
msgid "Save File"
|
|
||||||
msgstr "Сохранить файл"
|
|
||||||
|
|
||||||
#. Engine Log dialog title
|
|
||||||
#: ../resources/qml/EngineLog.qml:11
|
|
||||||
msgctxt "EngineLog|"
|
|
||||||
msgid "Engine Log"
|
|
||||||
msgstr "Журнал слайсера"
|
|
||||||
|
|
||||||
#. Close engine log button
|
|
||||||
#: ../resources/qml/EngineLog.qml:30
|
|
||||||
msgctxt "EngineLog|"
|
|
||||||
msgid "Close"
|
|
||||||
msgstr "Закрыть"
|
|
||||||
|
|
||||||
#. Firmware update status label
|
|
||||||
#: ../plugins/USBPrinting/FirmwareUpdateWindow.qml:16
|
|
||||||
msgctxt "FirmwareUpdateWindow|"
|
|
||||||
msgid "Starting firmware update, this may take a while."
|
|
||||||
msgstr "Начинается обновление прошивки, это может занять некоторое время."
|
|
||||||
|
|
||||||
#. Firmware update status label
|
|
||||||
#: ../plugins/USBPrinting/FirmwareUpdateWindow.qml:21
|
|
||||||
msgctxt "FirmwareUpdateWindow|"
|
|
||||||
msgid "Firmware update completed."
|
|
||||||
msgstr "Обновление прошивки завершено."
|
|
||||||
|
|
||||||
#. Firmware update status label
|
|
||||||
#: ../plugins/USBPrinting/FirmwareUpdateWindow.qml:26
|
|
||||||
msgctxt "FirmwareUpdateWindow|"
|
|
||||||
msgid "Updating firmware."
|
|
||||||
msgstr "Обновление прошивки."
|
|
||||||
|
|
||||||
#. Print material amount save button label
|
|
||||||
#: ../resources/qml/SaveButton.qml:149
|
|
||||||
#, qt-format
|
|
||||||
msgctxt "SaveButton|"
|
|
||||||
msgid "%1m material"
|
|
||||||
msgstr "%1m материал"
|
|
||||||
|
|
||||||
#. Save button label
|
|
||||||
#: ../resources/qml/SaveButton.qml:191
|
|
||||||
msgctxt "SaveButton|"
|
|
||||||
msgid "Please load a 3D model"
|
|
||||||
msgstr "Пожалуйста, загрузите 3D модель"
|
|
||||||
|
|
||||||
#. Save button label
|
|
||||||
#: ../resources/qml/SaveButton.qml:194
|
|
||||||
msgctxt "SaveButton|"
|
|
||||||
msgid "Calculating Print-time"
|
|
||||||
msgstr "Вычисляется время печати"
|
|
||||||
|
|
||||||
#. Save button label
|
|
||||||
#: ../resources/qml/SaveButton.qml:197
|
|
||||||
msgctxt "SaveButton|"
|
|
||||||
msgid "Estimated Print-time"
|
|
||||||
msgstr "Расчетное время печати"
|
|
||||||
|
|
||||||
#. Simple configuration mode option
|
|
||||||
#: ../resources/qml/Sidebar.qml:105
|
|
||||||
msgctxt "Sidebar|"
|
|
||||||
msgid "Simple"
|
|
||||||
msgstr "Простой"
|
|
||||||
|
|
||||||
#. Advanced configuration mode option
|
|
||||||
#: ../resources/qml/Sidebar.qml:107
|
|
||||||
msgctxt "Sidebar|"
|
|
||||||
msgid "Advanced"
|
|
||||||
msgstr "Продвинутый"
|
|
||||||
|
|
||||||
#. Configuration mode label
|
|
||||||
#: ../resources/qml/SidebarHeader.qml:26
|
|
||||||
msgctxt "SidebarHeader|"
|
|
||||||
msgid "Mode:"
|
|
||||||
msgstr "Режим:"
|
|
||||||
|
|
||||||
#. Machine selection label
|
|
||||||
#: ../resources/qml/SidebarHeader.qml:70
|
|
||||||
msgctxt "SidebarHeader|"
|
|
||||||
msgid "Machine:"
|
|
||||||
msgstr "Принтер:"
|
|
||||||
|
|
||||||
#. Sidebar header label
|
|
||||||
#: ../resources/qml/SidebarHeader.qml:117
|
|
||||||
msgctxt "SidebarHeader|"
|
|
||||||
msgid "Print Setup"
|
|
||||||
msgstr "Настройка Печати"
|
|
||||||
|
|
||||||
#. Sidebar configuration label
|
|
||||||
#: ../resources/qml/SidebarSimple.qml:40
|
|
||||||
msgctxt "SidebarSimple|"
|
|
||||||
msgid "No Model Loaded"
|
|
||||||
msgstr "Модель не загружена"
|
|
||||||
|
|
||||||
#. Sidebar configuration label
|
|
||||||
#: ../resources/qml/SidebarSimple.qml:45
|
|
||||||
msgctxt "SidebarSimple|"
|
|
||||||
msgid "Calculating..."
|
|
||||||
msgstr "Высчитывается..."
|
|
||||||
|
|
||||||
#. Sidebar configuration label
|
|
||||||
#: ../resources/qml/SidebarSimple.qml:50
|
|
||||||
msgctxt "SidebarSimple|"
|
|
||||||
msgid "Estimated Print Time"
|
|
||||||
msgstr "Расчетное время печати"
|
|
||||||
|
|
||||||
#. Quality slider label
|
|
||||||
#: ../resources/qml/SidebarSimple.qml:87
|
|
||||||
msgctxt "SidebarSimple|"
|
|
||||||
msgid ""
|
|
||||||
"Minimum\n"
|
|
||||||
"Draft"
|
|
||||||
msgstr ""
|
|
||||||
"Минимальная \n"
|
|
||||||
"тяга"
|
|
||||||
|
|
||||||
#. Quality slider label
|
|
||||||
#: ../resources/qml/SidebarSimple.qml:97
|
|
||||||
msgctxt "SidebarSimple|"
|
|
||||||
msgid ""
|
|
||||||
"Maximum\n"
|
|
||||||
"Quality"
|
|
||||||
msgstr ""
|
|
||||||
"Максимальное\n"
|
|
||||||
"Качество"
|
|
||||||
|
|
||||||
#. Setting checkbox
|
|
||||||
#: ../resources/qml/SidebarSimple.qml:109
|
|
||||||
msgctxt "SidebarSimple|"
|
|
||||||
msgid "Enable Support"
|
|
||||||
msgstr "Включить Поддержку"
|
|
||||||
|
|
||||||
#. View configuration page title
|
|
||||||
#: ../resources/qml/ViewPage.qml:9
|
|
||||||
msgctxt "ViewPage|"
|
|
||||||
msgid "View"
|
|
||||||
msgstr "Просмотр"
|
|
||||||
|
|
||||||
#. Display Overhang preference checkbox
|
|
||||||
#: ../resources/qml/ViewPage.qml:24
|
|
||||||
msgctxt "ViewPage|"
|
|
||||||
msgid "Display Overhang"
|
|
||||||
msgstr "Показать где есть нависающие части"
|
|
BIN
resources/images/MakerStarterbackplate.png
Normal file
After Width: | Height: | Size: 13 KiB |
BIN
resources/images/Ultimaker2Extendedbackplate.png
Normal file
After Width: | Height: | Size: 13 KiB |
BIN
resources/images/Ultimaker2Gobackplate.png
Normal file
After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 7.1 KiB After Width: | Height: | Size: 9.9 KiB |
60
resources/machines/RigidBot.json
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
{
|
||||||
|
"id": "rigidbotbig",
|
||||||
|
"version": 1,
|
||||||
|
"name": "RigidBot",
|
||||||
|
"manufacturer": "Invent-A-Part",
|
||||||
|
"author": "RBC",
|
||||||
|
"platform": "rigidbot_platform.stl",
|
||||||
|
|
||||||
|
"inherits": "fdmprinter.json",
|
||||||
|
|
||||||
|
"machine_settings": {
|
||||||
|
|
||||||
|
"machine_width": { "default": 254 },
|
||||||
|
"machine_depth": { "default": 254 },
|
||||||
|
"machine_height": { "default": 254 },
|
||||||
|
"machine_heated_bed": { "default": true },
|
||||||
|
|
||||||
|
"machine_nozzle_size": { "default": 0.4,
|
||||||
|
"visible": true
|
||||||
|
},
|
||||||
|
"machine_head_shape_min_x": { "default": 0 },
|
||||||
|
"machine_head_shape_min_y": { "default": 0 },
|
||||||
|
"machine_head_shape_max_x": { "default": 0 },
|
||||||
|
"machine_head_shape_max_y": { "default": 0 },
|
||||||
|
"machine_nozzle_gantry_distance": { "default": 0 },
|
||||||
|
"machine_gcode_flavor": { "default": "RepRap (Marlin/Sprinter)" },
|
||||||
|
|
||||||
|
"machine_start_gcode": {
|
||||||
|
"default": ";Sliced at: {day} {date} {time}\n;Basic settings: Layer height: {layer_height} Walls: {wall_thickness} Fill: {infill_density}\n;Print time: {print_time}\n;Filament used: {filament_amount}m {filament_weight}g\n;Filament cost: {filament_cost}\n;M190 S{print_bed_temperature} ;Uncomment to add your own bed temperature line\n;M109 S{print_temperature} ;Uncomment to add your own temperature line\nG21 ;metric values\nG90 ;absolute positioning\nM82 ;set extruder to absolute mode\nM107 ;start with the fan off\nG28 X0 Y0 ;move X/Y to min endstops\nG28 Z0 ;move Z to min endstops\nM205 X8 ;X/Y Jerk settings\nG1 Z15.0 F{travel_speed} ;move the platform down 15mm\nG92 E0 ;zero the extruded length\nG1 F200 E7 ;extrude 3mm of feed stock\nG92 E0 ;zero the extruded length again\nG1 F{travel_speed}\n;Put printing message on LCD screen\nM117 Rigibot Printing..."
|
||||||
|
},
|
||||||
|
"machine_end_gcode": {
|
||||||
|
"default": ";End GCode\nM104 S0 ;extruder heater off\nM140 S0 ;heated bed heater off (if you have it)\nG91 ;relative positioning\nG1 E-1 F300 ;retract the filament a bit before lifting the nozzle, to release some of the pressure\nG1 Z+10 E-1 X-20 Y-20 F{travel_speed} ;move Z up a bit and retract filament even more\nG28 X0 Y0 ;move X/Y to min endstops, so the head is out of the way\nG1 Y230 F3000 ;move Y so the head is out of the way and Plate is moved forward\nM84 ;steppers off\nG90 ;absolute positioning\n;{profile_string}"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
"overrides": {
|
||||||
|
"layer_height": { "default": 0.2 },
|
||||||
|
"shell_thickness": { "default": 0.8 },
|
||||||
|
"wall_thickness": { "default": 0.8 },
|
||||||
|
"top_bottom_thickness": { "default": 0.3, "visible": true },
|
||||||
|
"material_print_temperature": { "default": 195, "visible": true },
|
||||||
|
"material_bed_temperature": { "default": 60, "visible": true },
|
||||||
|
"material_diameter": { "default": 1.75, "visible": true },
|
||||||
|
"retraction_enable": { "default": true, "always_visible": true },
|
||||||
|
"retraction_speed": { "default": 50.0, "visible": false },
|
||||||
|
"retraction_amount": { "default": 0.8, "visible": false },
|
||||||
|
"retraction_hop": { "default": 0.075, "visible": false },
|
||||||
|
"speed_print": { "default": 60.0, "visible": true },
|
||||||
|
"speed_infill": { "default": 100.0, "visible": true },
|
||||||
|
"speed_topbottom": { "default": 15.0, "visible": true },
|
||||||
|
"speed_travel": { "default": 150.0, "visible": true },
|
||||||
|
"speed_layer_0": { "min_value": 0.1, "default": 15.0, "visible": true },
|
||||||
|
"infill_overlap": { "default": 10.0 },
|
||||||
|
"cool_fan_enabled": { "default": false, "visible": true },
|
||||||
|
"cool_fan_speed": { "default": 0.0, "visible": true },
|
||||||
|
"skirt_line_count": { "default": 3, "active_if": { "setting": "adhesion_type", "value": "None" } },
|
||||||
|
"skirt_gap": { "default": 4.0, "active_if": { "setting": "adhesion_type", "value": "None" } },
|
||||||
|
"skirt_minimal_length": { "default": 200.0, "active_if": { "setting": "adhesion_type", "value": "None" } }
|
||||||
|
}
|
||||||
|
}
|
58
resources/machines/RigidBotBig.json
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
{
|
||||||
|
"id": "rigidbotbig",
|
||||||
|
"version": 1,
|
||||||
|
"name": "RigidBotBig",
|
||||||
|
"manufacturer": "Invent-A-Part",
|
||||||
|
"author": "RBC",
|
||||||
|
"platform": "rigidbotbig_platform.stl",
|
||||||
|
|
||||||
|
"inherits": "fdmprinter.json",
|
||||||
|
|
||||||
|
"machine_settings": {
|
||||||
|
|
||||||
|
"machine_width": { "default": 400 },
|
||||||
|
"machine_depth": { "default": 300 },
|
||||||
|
"machine_height": { "default": 254 },
|
||||||
|
"machine_heated_bed": { "default": true },
|
||||||
|
|
||||||
|
"machine_nozzle_size": { "default": 0.4},
|
||||||
|
"machine_head_shape_min_x": { "default": 0 },
|
||||||
|
"machine_head_shape_min_y": { "default": 0 },
|
||||||
|
"machine_head_shape_max_x": { "default": 0 },
|
||||||
|
"machine_head_shape_max_y": { "default": 0 },
|
||||||
|
"machine_nozzle_gantry_distance": { "default": 0 },
|
||||||
|
"machine_gcode_flavor": { "default": "RepRap (Marlin/Sprinter)" },
|
||||||
|
|
||||||
|
"machine_start_gcode": {
|
||||||
|
"default": ";Sliced at: {day} {date} {time}\n;Basic settings: Layer height: {layer_height} Walls: {wall_thickness} Fill: {infill_density}\n;Print time: {print_time}\n;Filament used: {filament_amount}m {filament_weight}g\n;Filament cost: {filament_cost}\n;M190 S{print_bed_temperature} ;Uncomment to add your own bed temperature line\n;M109 S{print_temperature} ;Uncomment to add your own temperature line\nG21 ;metric values\nG90 ;absolute positioning\nM82 ;set extruder to absolute mode\nM107 ;start with the fan off\nG28 X0 Y0 ;move X/Y to min endstops\nG28 Z0 ;move Z to min endstops\nM205 X8 ;X/Y Jerk settings\nG1 Z15.0 F{travel_speed} ;move the platform down 15mm\nG92 E0 ;zero the extruded length\nG1 F200 E7 ;extrude 3mm of feed stock\nG92 E0 ;zero the extruded length again\nG1 F{travel_speed}\n;Put printing message on LCD screen\nM117 Rigibot Printing..."
|
||||||
|
},
|
||||||
|
"machine_end_gcode": {
|
||||||
|
"default": ";End GCode\nM104 S0 ;extruder heater off\nM140 S0 ;heated bed heater off (if you have it)\nG91 ;relative positioning\nG1 E-1 F300 ;retract the filament a bit before lifting the nozzle, to release some of the pressure\nG1 Z+10 E-1 X-20 Y-20 F{travel_speed} ;move Z up a bit and retract filament even more\nG28 X0 Y0 ;move X/Y to min endstops, so the head is out of the way\nG1 Y230 F3000 ;move Y so the head is out of the way and Plate is moved forward\nM84 ;steppers off\nG90 ;absolute positioning\n;{profile_string}"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
"overrides": {
|
||||||
|
"layer_height": { "default": 0.2 },
|
||||||
|
"shell_thickness": { "default": 0.8},
|
||||||
|
"wall_thickness": { "default": 0.8 },
|
||||||
|
"top_bottom_thickness": { "default": 0.3, "visible": true },
|
||||||
|
"material_print_temperature": { "default": 195, "visible": true },
|
||||||
|
"material_bed_temperature": { "default": 60, "visible": true },
|
||||||
|
"material_diameter": { "default": 1.75, "visible": true },
|
||||||
|
"retraction_enable": { "default": true, "always_visible": true},
|
||||||
|
"retraction_speed": { "default": 50.0, "visible": false },
|
||||||
|
"retraction_amount": { "default": 0.8, "visible": false },
|
||||||
|
"retraction_hop": { "default": 0.075, "visible": false },
|
||||||
|
"speed_print": { "default": 60.0, "visible": true},
|
||||||
|
"speed_infill": { "default": 100.0, "visible": true },
|
||||||
|
"speed_topbottom": { "default": 15.0, "visible": true },
|
||||||
|
"speed_travel": { "default": 150.0, "visible": true },
|
||||||
|
"speed_layer_0": { "min_value": 0.1, "default": 15.0, "visible": true },
|
||||||
|
"infill_overlap": { "default": 10.0 },
|
||||||
|
"cool_fan_enabled": { "default": false, "visible": true},
|
||||||
|
"cool_fan_speed": { "default": 0.0, "visible": true },
|
||||||
|
"skirt_line_count": { "default": 3, "active_if": { "setting": "adhesion_type", "value": "None" } },
|
||||||
|
"skirt_gap": { "default": 4.0, "active_if": { "setting": "adhesion_type", "value": "None" } },
|
||||||
|
"skirt_minimal_length": { "default": 200.0, "active_if": { "setting": "adhesion_type", "value": "None" } }
|
||||||
|
}
|
||||||
|
}
|
60
resources/machines/bq_hephestos.json
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
{
|
||||||
|
"id": "bq_hephestos",
|
||||||
|
"version": 1,
|
||||||
|
"name": "BQ Prusa i3 Hephestos",
|
||||||
|
"manufacturer": "BQ",
|
||||||
|
"author": "BQ",
|
||||||
|
"platform": "hephestos_platform.stl",
|
||||||
|
"inherits": "fdmprinter.json",
|
||||||
|
|
||||||
|
"machine_settings": {
|
||||||
|
"machine_start_gcode": {
|
||||||
|
"default": "; -- START GCODE --\nG21 ;set units to millimetres\nG90 ;set to absolute positioning\nM106 S0 ;set fan speed to zero (turned off)\nG28 X0 Y0 ;move to the X/Y origin (Home)\nG28 Z0 ;move to the Z origin (Home)\nG1 Z15.0 F1200 ;move Z to position 15.0 mm\nG92 E0 ;zero the extruded length\nG1 E20 F200 ;extrude 20mm of feed stock\nG92 E0 ;zero the extruded length again\nG1 F7200 ;set feedrate to 120 mm/sec\n; -- end of START GCODE --"
|
||||||
|
},
|
||||||
|
"machine_end_gcode": {
|
||||||
|
"default": "; -- END GCODE --\nM104 S0 ;set extruder temperature to zero (turned off)\nG91 ;set to relative positioning\nG1 E-20 F300 ;retract the filament a bit to release some of the pressure\nG1 Z10 ;move extruder up 10 mm\nG90 ;set to absolute positioning\nG1 X0 Y180 F1200 ;expose the platform\nM84 ;turn off steppers\n; -- end of END GCODE --"
|
||||||
|
},
|
||||||
|
"machine_width": {
|
||||||
|
"default": 215
|
||||||
|
},
|
||||||
|
"machine_depth": {
|
||||||
|
"default": 210
|
||||||
|
},
|
||||||
|
"machine_height": {
|
||||||
|
"default": 180
|
||||||
|
},
|
||||||
|
"machine_heated_bed": {
|
||||||
|
"default": false
|
||||||
|
},
|
||||||
|
"machine_center_is_zero": {
|
||||||
|
"default": false
|
||||||
|
},
|
||||||
|
"machine_gcode_flavor": {
|
||||||
|
"default": "RepRap"
|
||||||
|
},
|
||||||
|
"machine_platform_offset": {
|
||||||
|
"default": [0, 100, 0]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"overrides": {
|
||||||
|
"layer_height": { "default": 0.2 },
|
||||||
|
"layer_height_0": { "default": 0.2, "visible": false },
|
||||||
|
"shell_thickness": { "default": 1.0 },
|
||||||
|
"wall_thickness": { "default": 1.0, "visible": false },
|
||||||
|
"top_bottom_thickness": { "default": 1.0, "visible": false},
|
||||||
|
"bottom_thickness": { "default": 1.0, "visible": false },
|
||||||
|
"material_print_temperature": { "default": 220, "visible": true },
|
||||||
|
"material_bed_temperature": { "default": 0, "visible": false },
|
||||||
|
"material_diameter": { "default": 1.75, "visible": true },
|
||||||
|
"speed_print": { "default": 40.0},
|
||||||
|
"speed_infill": { "default": 40.0, "visible": true },
|
||||||
|
"speed_wall": { "default": 35.0, "visible": true},
|
||||||
|
"speed_topbottom": { "default": 35.0, "visible": true },
|
||||||
|
"speed_travel": { "default": 120.0 },
|
||||||
|
"speed_layer_0": { "default": 20.0, "visible": false },
|
||||||
|
"retraction_speed": { "default": 30.0, "visible": false},
|
||||||
|
"retraction_amount": { "default": 2.0, "visible": false },
|
||||||
|
"retraction_hop": { "default": 0.075, "visible": false },
|
||||||
|
"support_enable": { "default": true }
|
||||||
|
}
|
||||||
|
}
|
60
resources/machines/bq_hephestos_xl.json
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
{
|
||||||
|
"id": "bq_hephestos_xl",
|
||||||
|
"version": 1,
|
||||||
|
"name": "BQ Prusa i3 Hephestos XL",
|
||||||
|
"manufacturer": "BQ",
|
||||||
|
"author": "BQ",
|
||||||
|
"platform": "hephestos_platform.stl",
|
||||||
|
"inherits": "fdmprinter.json",
|
||||||
|
|
||||||
|
"machine_settings": {
|
||||||
|
"machine_start_gcode": {
|
||||||
|
"default": "; -- START GCODE --\nG21 ;set units to millimetres\nG90 ;set to absolute positioning\nM106 S0 ;set fan speed to zero (turned off)\nG28 X0 Y0 ;move to the X/Y origin (Home)\nG28 Z0 ;move to the Z origin (Home)\nG1 Z15.0 F1200 ;move Z to position 15.0 mm\nG92 E0 ;zero the extruded length\nG1 E20 F200 ;extrude 20mm of feed stock\nG92 E0 ;zero the extruded length again\nG1 F7200 ;set feedrate to 120 mm/sec\n; -- end of START GCODE --"
|
||||||
|
},
|
||||||
|
"machine_end_gcode": {
|
||||||
|
"default": "; -- END GCODE --\nM104 S0 ;set extruder temperature to zero (turned off)\nG91 ;set to relative positioning\nG1 E-20 F300 ;retract the filament a bit to release some of the pressure\nG1 Z10 ;move extruder up 10 mm\nG90 ;set to absolute positioning\nG1 X0 Y180 F1200 ;expose the platform\nM84 ;turn off steppers\n; -- end of END GCODE --"
|
||||||
|
},
|
||||||
|
"machine_width": {
|
||||||
|
"default": 200
|
||||||
|
},
|
||||||
|
"machine_depth": {
|
||||||
|
"default": 300
|
||||||
|
},
|
||||||
|
"machine_height": {
|
||||||
|
"default": 180
|
||||||
|
},
|
||||||
|
"machine_heated_bed": {
|
||||||
|
"default": false
|
||||||
|
},
|
||||||
|
"machine_center_is_zero": {
|
||||||
|
"default": false
|
||||||
|
},
|
||||||
|
"machine_gcode_flavor": {
|
||||||
|
"default": "RepRap"
|
||||||
|
},
|
||||||
|
"machine_platform_offset": {
|
||||||
|
"default": [0, 100, 0]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"overrides": {
|
||||||
|
"layer_height": { "default": 0.2 },
|
||||||
|
"layer_height_0": { "default": 0.2, "visible": false },
|
||||||
|
"shell_thickness": { "default": 1.0 },
|
||||||
|
"wall_thickness": { "default": 1.0, "visible": false },
|
||||||
|
"top_bottom_thickness": { "default": 1.0, "visible": false},
|
||||||
|
"bottom_thickness": { "default": 1.0, "visible": false },
|
||||||
|
"material_print_temperature": { "default": 220, "visible": true },
|
||||||
|
"material_bed_temperature": { "default": 0, "visible": false },
|
||||||
|
"material_diameter": { "default": 1.75, "visible": true },
|
||||||
|
"speed_print": { "default": 40.0},
|
||||||
|
"speed_infill": { "default": 40.0, "visible": true },
|
||||||
|
"speed_wall": { "default": 35.0, "visible": true},
|
||||||
|
"speed_topbottom": { "default": 35.0, "visible": true },
|
||||||
|
"speed_travel": { "default": 120.0 },
|
||||||
|
"speed_layer_0": { "default": 20.0, "visible": false },
|
||||||
|
"retraction_speed": { "default": 30.0, "visible": false},
|
||||||
|
"retraction_amount": { "default": 2.0, "visible": false },
|
||||||
|
"retraction_hop": { "default": 0.075, "visible": false },
|
||||||
|
"support_enable": { "default": true }
|
||||||
|
}
|
||||||
|
}
|
60
resources/machines/bq_witbox.json
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
{
|
||||||
|
"id": "bq_witbox",
|
||||||
|
"version": 1,
|
||||||
|
"name": "BQ Witbox",
|
||||||
|
"manufacturer": "BQ",
|
||||||
|
"author": "BQ",
|
||||||
|
"platform": "witbox_platform.stl",
|
||||||
|
"inherits": "fdmprinter.json",
|
||||||
|
|
||||||
|
"machine_settings": {
|
||||||
|
"machine_start_gcode": {
|
||||||
|
"default": "; -- START GCODE --\nG21 ;set units to millimetres\nG90 ;set to absolute positioning\nM106 S0 ;set fan speed to zero (turned off)\nG28 X0 Y0 ;move to the X/Y origin (Home)\nG28 Z0 ;move to the Z origin (Home)\nG1 Z15.0 F1200 ;move Z to position 15.0 mm\nG92 E0 ;zero the extruded length\nG1 E20 F200 ;extrude 20mm of feed stock\nG92 E0 ;zero the extruded length again\nG1 F7200 ;set feedrate to 120 mm/sec\n; -- end of START GCODE --"
|
||||||
|
},
|
||||||
|
"machine_end_gcode": {
|
||||||
|
"default": "; -- END GCODE --\nM104 S0 ;set extruder temperature to zero (turned off)\nG91 ;set to relative positioning\nG1 E-20 F300 ;retract the filament a bit to release some of the pressure\nG90 ;set to absolute positioning\nG1 Z200 ;move the platform to the bottom\nG28 X0 Y0 ;move to the X/Y origin (Home)\nM84 ;turn off steppers\n; -- end of END GCODE --"
|
||||||
|
},
|
||||||
|
"machine_width": {
|
||||||
|
"default": 297
|
||||||
|
},
|
||||||
|
"machine_depth": {
|
||||||
|
"default": 210
|
||||||
|
},
|
||||||
|
"machine_height": {
|
||||||
|
"default": 200
|
||||||
|
},
|
||||||
|
"machine_heated_bed": {
|
||||||
|
"default": false
|
||||||
|
},
|
||||||
|
"machine_center_is_zero": {
|
||||||
|
"default": false
|
||||||
|
},
|
||||||
|
"machine_gcode_flavor": {
|
||||||
|
"default": "RepRap"
|
||||||
|
},
|
||||||
|
"machine_platform_offset": {
|
||||||
|
"default": [0, -145, -38]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"overrides": {
|
||||||
|
"layer_height": { "default": 0.2 },
|
||||||
|
"layer_height_0": { "default": 0.2, "visible": false },
|
||||||
|
"shell_thickness": { "default": 1.0 },
|
||||||
|
"wall_thickness": { "default": 1.0, "visible": false },
|
||||||
|
"top_bottom_thickness": { "default": 1.0, "visible": false},
|
||||||
|
"bottom_thickness": { "default": 1.0, "visible": false },
|
||||||
|
"material_print_temperature": { "default": 220, "visible": true },
|
||||||
|
"material_bed_temperature": { "default": 0, "visible": false },
|
||||||
|
"material_diameter": { "default": 1.75, "visible": true },
|
||||||
|
"speed_print": { "default": 40.0},
|
||||||
|
"speed_infill": { "default": 40.0, "visible": true },
|
||||||
|
"speed_wall": { "default": 35.0, "visible": true},
|
||||||
|
"speed_topbottom": { "default": 35.0, "visible": true },
|
||||||
|
"speed_travel": { "default": 120.0 },
|
||||||
|
"speed_layer_0": { "default": 20.0, "visible": false },
|
||||||
|
"retraction_speed": { "default": 30.0, "visible": false},
|
||||||
|
"retraction_amount": { "default": 2.0, "visible": false },
|
||||||
|
"retraction_hop": { "default": 0.075, "visible": false },
|
||||||
|
"support_enable": { "default": true }
|
||||||
|
}
|
||||||
|
}
|
@ -2,7 +2,7 @@
|
|||||||
"id": "grr_neo",
|
"id": "grr_neo",
|
||||||
"version": 1,
|
"version": 1,
|
||||||
"name": "German RepRap Neo",
|
"name": "German RepRap Neo",
|
||||||
"manufacturer": "German RepRap",
|
"manufacturer": "Other",
|
||||||
"author": "other",
|
"author": "other",
|
||||||
"icon": "icon_ultimaker.png",
|
"icon": "icon_ultimaker.png",
|
||||||
"platform": "grr_neo_platform.stl",
|
"platform": "grr_neo_platform.stl",
|
||||||
@ -21,8 +21,6 @@
|
|||||||
"machine_head_shape_max_x": { "default": 18 },
|
"machine_head_shape_max_x": { "default": 18 },
|
||||||
"machine_head_shape_max_y": { "default": 35 },
|
"machine_head_shape_max_y": { "default": 35 },
|
||||||
"machine_nozzle_gantry_distance": { "default": 55 },
|
"machine_nozzle_gantry_distance": { "default": 55 },
|
||||||
"machine_nozzle_offset_x_1": { "default": 18.0 },
|
|
||||||
"machine_nozzle_offset_y_1": { "default": 0.0 },
|
|
||||||
"machine_gcode_flavor": { "default": "RepRap (Marlin/Sprinter)" },
|
"machine_gcode_flavor": { "default": "RepRap (Marlin/Sprinter)" },
|
||||||
|
|
||||||
"machine_start_gcode": {
|
"machine_start_gcode": {
|
||||||
@ -33,13 +31,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
"categories": {
|
"overrides": {
|
||||||
"material": {
|
"material_bed_temperature": { "visible": false }
|
||||||
"settings": {
|
|
||||||
"material_bed_temperature": {
|
|
||||||
"visible": false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
82
resources/machines/maker_starter.json
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
{
|
||||||
|
"id": "maker_starter",
|
||||||
|
"version": 1,
|
||||||
|
"name": "3DMaker Starter",
|
||||||
|
"manufacturer": "Other",
|
||||||
|
"author": "Other",
|
||||||
|
"icon": "icon_ultimaker2.png",
|
||||||
|
"platform": "makerstarter_platform.stl",
|
||||||
|
|
||||||
|
"inherits": "fdmprinter.json",
|
||||||
|
|
||||||
|
"machine_settings": {
|
||||||
|
"machine_width": { "default": 210 },
|
||||||
|
"machine_depth": { "default": 185 },
|
||||||
|
"machine_height": { "default": 200 },
|
||||||
|
"machine_heated_bed": { "default": false },
|
||||||
|
|
||||||
|
"machine_center_is_zero": { "default": false },
|
||||||
|
"machine_nozzle_size": { "default": 0.4 },
|
||||||
|
"machine_head_shape_min_x": { "default": 0 },
|
||||||
|
"machine_head_shape_min_y": { "default": 0 },
|
||||||
|
"machine_head_shape_max_x": { "default": 0 },
|
||||||
|
"machine_head_shape_max_y": { "default": 0 },
|
||||||
|
"machine_nozzle_gantry_distance": { "default": 55 },
|
||||||
|
"machine_gcode_flavor": { "default": "RepRap" },
|
||||||
|
"machine_disallowed_areas": { "default": []},
|
||||||
|
"machine_platform_offset": { "default": [0.0, 0.0, 0.0] },
|
||||||
|
|
||||||
|
"machine_nozzle_tip_outer_diameter": { "default": 1.0 },
|
||||||
|
"machine_nozzle_head_distance": { "default": 3.0 },
|
||||||
|
"machine_nozzle_expansion_angle": { "default": 45 }
|
||||||
|
},
|
||||||
|
|
||||||
|
"overrides": {
|
||||||
|
"layer_height": { "default": 0.2 },
|
||||||
|
"layer_height_0": { "default": 0.2, "visible": false },
|
||||||
|
"wall_line_count": { "default": 2, "visible": true },
|
||||||
|
"top_layers": { "default": 4, "visible": true },
|
||||||
|
"bottom_layers": { "default": 4, "visible": true },
|
||||||
|
"material_print_temperature": { "visible": false },
|
||||||
|
"material_bed_temperature": { "visible": false },
|
||||||
|
"material_diameter": { "default": 1.75, "visible": false },
|
||||||
|
"material_flow": { "visible": false },
|
||||||
|
"retraction_hop": { "default": 0.2 },
|
||||||
|
"speed_print": { "default": 50.0 },
|
||||||
|
"speed_wall": { "default": 30.0 },
|
||||||
|
"speed_wall_0": { "default": 30.0 },
|
||||||
|
"speed_wall_x": { "default": 30.0 },
|
||||||
|
"speed_topbottom": { "default": 50.0 },
|
||||||
|
"speed_support": { "default": 50.0 },
|
||||||
|
"speed_travel": { "default": 120.0 },
|
||||||
|
"speed_layer_0": { "default": 20.0 },
|
||||||
|
"skirt_speed": { "default": 15.0 },
|
||||||
|
"speed_slowdown_layers": { "default": 4 },
|
||||||
|
"infill_sparse_density": { "default": 20.0 },
|
||||||
|
"cool_fan_speed_min": { "default": 50.0 },
|
||||||
|
"cool_fan_speed_max": { "default": 100.0 },
|
||||||
|
"cool_fan_full_layer": { "default": 4, "visible": true },
|
||||||
|
"cool_min_layer_time": { "default": 5.0 },
|
||||||
|
"cool_min_layer_time_fan_speed_max": { "default": 10.0 },
|
||||||
|
"support_type": { "default": "Everywhere" },
|
||||||
|
"support_angle": { "default": 45.0, "visible": true },
|
||||||
|
"support_xy_distance": { "default": 1 },
|
||||||
|
"support_z_distance": { "default": 0.2 },
|
||||||
|
"support_top_distance": { "default": 0.2 },
|
||||||
|
"support_bottom_distance": { "default": 0.24 },
|
||||||
|
"support_pattern": { "default": "ZigZag" },
|
||||||
|
"support_infill_rate": { "default": 15, "visible": true },
|
||||||
|
"adhesion_type": { "default": "Raft" },
|
||||||
|
"skirt_minimal_length": { "default": 100.0 },
|
||||||
|
"raft_base_line_spacing": { "default": 2.0 },
|
||||||
|
"raft_base_thickness": { "default": 0.3 },
|
||||||
|
"raft_base_line_width": { "default": 2.0 },
|
||||||
|
"raft_base_speed": { "default": 15.0 },
|
||||||
|
"raft_interface_thickness": { "default": 0.24 },
|
||||||
|
"raft_interface_line_width": { "default": 0.6 },
|
||||||
|
"raft_airgap": { "default": 0.2 },
|
||||||
|
"raft_surface_layers": { "default": 2 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -20,8 +20,6 @@
|
|||||||
"machine_head_shape_max_x": { "default": 18 },
|
"machine_head_shape_max_x": { "default": 18 },
|
||||||
"machine_head_shape_max_y": { "default": 35 },
|
"machine_head_shape_max_y": { "default": 35 },
|
||||||
"machine_nozzle_gantry_distance": { "default": 55 },
|
"machine_nozzle_gantry_distance": { "default": 55 },
|
||||||
"machine_nozzle_offset_x_1": { "default": 0.0 },
|
|
||||||
"machine_nozzle_offset_y_1": { "default": 0.0 },
|
|
||||||
"machine_gcode_flavor": { "default": "RepRap (Marlin/Sprinter)" },
|
"machine_gcode_flavor": { "default": "RepRap (Marlin/Sprinter)" },
|
||||||
|
|
||||||
"machine_start_gcode": {
|
"machine_start_gcode": {
|
||||||
@ -32,13 +30,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
"categories": {
|
"overrides": {
|
||||||
"material": {
|
"material_bed_temperature": { "visible": true }
|
||||||
"settings": {
|
|
||||||
"material_bed_temperature": {
|
|
||||||
"visible": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -10,6 +10,26 @@
|
|||||||
|
|
||||||
"inherits": "fdmprinter.json",
|
"inherits": "fdmprinter.json",
|
||||||
|
|
||||||
|
|
||||||
|
"machine_extruder_trains": [
|
||||||
|
{
|
||||||
|
"machine_nozzle_size": {
|
||||||
|
"default": 0.4
|
||||||
|
},
|
||||||
|
"machine_nozzle_tip_outer_diameter": {
|
||||||
|
"default": 1
|
||||||
|
},
|
||||||
|
"machine_nozzle_head_distance": {
|
||||||
|
"default": 3
|
||||||
|
},
|
||||||
|
"machine_nozzle_expansion_angle": {
|
||||||
|
"default": 45
|
||||||
|
},
|
||||||
|
"machine_heat_zone_length": {
|
||||||
|
"default": 16
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
"machine_settings": {
|
"machine_settings": {
|
||||||
"machine_start_gcode" : { "default": "" },
|
"machine_start_gcode" : { "default": "" },
|
||||||
"machine_end_gcode" : { "default": "" },
|
"machine_end_gcode" : { "default": "" },
|
||||||
@ -18,15 +38,31 @@
|
|||||||
"machine_height": { "default": 205 },
|
"machine_height": { "default": 205 },
|
||||||
"machine_heated_bed": { "default": true },
|
"machine_heated_bed": { "default": true },
|
||||||
|
|
||||||
|
"machine_head_with_fans_polygon":
|
||||||
|
{
|
||||||
|
"default": [
|
||||||
|
[
|
||||||
|
-40,
|
||||||
|
30
|
||||||
|
],
|
||||||
|
[
|
||||||
|
-40,
|
||||||
|
-10
|
||||||
|
],
|
||||||
|
[
|
||||||
|
60,
|
||||||
|
-10
|
||||||
|
],
|
||||||
|
[
|
||||||
|
60,
|
||||||
|
30
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
"machine_center_is_zero": { "default": false },
|
"machine_center_is_zero": { "default": false },
|
||||||
"machine_nozzle_size": { "default": 0.4 },
|
"machine_nozzle_size": { "default": 0.4 },
|
||||||
"machine_head_shape_min_x": { "default": 40 },
|
"gantry_height": { "default": 55 },
|
||||||
"machine_head_shape_min_y": { "default": 10 },
|
"machine_use_extruder_offset_to_offset_coords": { "default": true },
|
||||||
"machine_head_shape_max_x": { "default": 60 },
|
|
||||||
"machine_head_shape_max_y": { "default": 30 },
|
|
||||||
"machine_nozzle_gantry_distance": { "default": 55 },
|
|
||||||
"machine_nozzle_offset_x_1": { "default": 18.0 },
|
|
||||||
"machine_nozzle_offset_y_1": { "default": 0.0 },
|
|
||||||
"machine_gcode_flavor": { "default": "UltiGCode" },
|
"machine_gcode_flavor": { "default": "UltiGCode" },
|
||||||
"machine_disallowed_areas": { "default": [
|
"machine_disallowed_areas": { "default": [
|
||||||
[[-115.0, 112.5], [ -82.0, 112.5], [ -84.0, 104.5], [-115.0, 104.5]],
|
[[-115.0, 112.5], [ -82.0, 112.5], [ -84.0, 104.5], [-115.0, 104.5]],
|
||||||
@ -41,22 +77,10 @@
|
|||||||
"machine_nozzle_expansion_angle": { "default": 45 }
|
"machine_nozzle_expansion_angle": { "default": 45 }
|
||||||
},
|
},
|
||||||
|
|
||||||
"categories": {
|
"overrides": {
|
||||||
"material": {
|
"material_print_temperature": { "enabled": "False" },
|
||||||
"settings": {
|
"material_bed_temperature": { "enabled": "False" },
|
||||||
"material_print_temperature": {
|
"material_diameter": { "enabled": "False" },
|
||||||
"visible": false
|
"material_flow": { "enabled": "False" }
|
||||||
},
|
|
||||||
"material_bed_temperature": {
|
|
||||||
"visible": false
|
|
||||||
},
|
|
||||||
"material_diameter": {
|
|
||||||
"visible": false
|
|
||||||
},
|
|
||||||
"material_flow": {
|
|
||||||
"visible": false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -6,7 +6,7 @@
|
|||||||
"author": "Ultimaker",
|
"author": "Ultimaker",
|
||||||
"icon": "icon_ultimaker2.png",
|
"icon": "icon_ultimaker2.png",
|
||||||
"platform": "ultimaker2_platform.obj",
|
"platform": "ultimaker2_platform.obj",
|
||||||
"platform_texture": "Ultimaker2backplate.png",
|
"platform_texture": "Ultimaker2Extendedbackplate.png",
|
||||||
|
|
||||||
"inherits": "ultimaker2.json",
|
"inherits": "ultimaker2.json",
|
||||||
|
|
@ -6,7 +6,7 @@
|
|||||||
"author": "Ultimaker",
|
"author": "Ultimaker",
|
||||||
"icon": "icon_ultimaker2.png",
|
"icon": "icon_ultimaker2.png",
|
||||||
"platform": "ultimaker2go_platform.obj",
|
"platform": "ultimaker2go_platform.obj",
|
||||||
"platform_texture": "Ultimaker2backplate.png",
|
"platform_texture": "Ultimaker2Gobackplate.png",
|
||||||
|
|
||||||
"inherits": "ultimaker2.json",
|
"inherits": "ultimaker2.json",
|
||||||
|
|
@ -9,43 +9,72 @@
|
|||||||
|
|
||||||
"inherits": "fdmprinter.json",
|
"inherits": "fdmprinter.json",
|
||||||
|
|
||||||
"add_pages": [
|
"pages": [
|
||||||
{"page": "SelectUpgradedParts", "title": "Select Upgraded Parts"},
|
"SelectUpgradedParts",
|
||||||
{"page": "UpgradeFirmware", "title": "Upgrade Ultimaker Firmware"},
|
"UpgradeFirmware",
|
||||||
{"page": "UltimakerCheckup", "title": "Ultimaker Checkup"},
|
"UltimakerCheckup",
|
||||||
{"page": "Bedleveling", "title": "Bedleveling Wizard"}
|
"BedLeveling"
|
||||||
],
|
],
|
||||||
|
|
||||||
|
"machine_extruder_trains": [
|
||||||
|
{
|
||||||
|
"machine_nozzle_size": {
|
||||||
|
"default": 0.4
|
||||||
|
},
|
||||||
|
"machine_nozzle_tip_outer_diameter": {
|
||||||
|
"default": 1
|
||||||
|
},
|
||||||
|
"machine_nozzle_head_distance": {
|
||||||
|
"default": 3
|
||||||
|
},
|
||||||
|
"machine_nozzle_expansion_angle": {
|
||||||
|
"default": 45
|
||||||
|
},
|
||||||
|
"machine_heat_zone_length": {
|
||||||
|
"default": 16
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
"machine_settings": {
|
"machine_settings": {
|
||||||
"machine_width": { "default": 205 },
|
"machine_width": { "default": 205 },
|
||||||
"machine_height": { "default": 200 },
|
"machine_height": { "default": 200 },
|
||||||
"machine_depth": { "default": 205 },
|
"machine_depth": { "default": 205 },
|
||||||
"machine_center_is_zero": { "default": false },
|
"machine_center_is_zero": { "default": false },
|
||||||
"machine_nozzle_size": { "default": 0.4 },
|
"machine_nozzle_size": { "default": 0.4 },
|
||||||
"machine_head_shape_min_x": { "default": 75 },
|
"machine_head_with_fans_polygon":
|
||||||
"machine_head_shape_min_y": { "default": 18 },
|
{
|
||||||
"machine_head_shape_max_x": { "default": 18 },
|
"default": [
|
||||||
"machine_head_shape_max_y": { "default": 35 },
|
[
|
||||||
"machine_nozzle_gantry_distance": { "default": 55 },
|
-75,
|
||||||
"machine_nozzle_offset_x_1": { "default": 18.0 },
|
35
|
||||||
"machine_nozzle_offset_y_1": { "default": 0.0 },
|
],
|
||||||
|
[
|
||||||
|
-75,
|
||||||
|
-18
|
||||||
|
],
|
||||||
|
[
|
||||||
|
18,
|
||||||
|
35
|
||||||
|
],
|
||||||
|
[
|
||||||
|
18,
|
||||||
|
-18
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"gantry_height": { "default": 55 },
|
||||||
|
"machine_use_extruder_offset_to_offset_coords": { "default": true },
|
||||||
"machine_gcode_flavor": { "default": "RepRap (Marlin/Sprinter)" },
|
"machine_gcode_flavor": { "default": "RepRap (Marlin/Sprinter)" },
|
||||||
|
|
||||||
"machine_start_gcode": {
|
"machine_start_gcode": {
|
||||||
"default": "G21 ;metric values\nG90 ;absolute positioning\nM82 ;set extruder to absolute mode\nM107 ;start with the fan off\nG28 X0 Y0 ;move X/Y to min endstops\nG28 Z0 ;move Z to min endstops\nG1 Z15.0 F9000 ;move the platform down 15mm\nG92 E0 ;zero the extruded length\nG1 F200 E3 ;extrude 3mm of feed stock\nG92 E0 ;zero the extruded length again\nG1 F9000\n;Put printing message on LCD screen\nM117 Printing..."
|
"default": "G21 ;metric values\nG90 ;absolute positioning\nM82 ;set extruder to absolute mode\nM107 ;start with the fan off\nG28 X0 Y0 ;move X/Y to min endstops\nG28 Z0 ;move Z to min endstops\nG1 Z15.0 F9000 ;move the platform down 15mm\nG92 E0 ;zero the extruded length\nG1 F200 E6 ;extrude 3mm of feed stock\nG92 E0 ;zero the extruded length again\nG1 F9000\n;Put printing message on LCD screen\nM117 Printing..."
|
||||||
},
|
},
|
||||||
"machine_end_gcode": {
|
"machine_end_gcode": {
|
||||||
"default": "M104 S0 ;extruder heater off\nM140 S0 ;heated bed heater off (if you have it)\nG91 ;relative positioning\nG1 E-1 F300 ;retract the filament a bit before lifting the nozzle, to release some of the pressure\nG1 Z+0.5 E-5 X-20 Y-20 F9000 ;move Z up a bit and retract filament even more\nG28 X0 Y0 ;move X/Y to min endstops, so the head is out of the way\nM84 ;steppers off\nG90 ;absolute positioning"
|
"default": "M104 S0 ;extruder heater off\nM140 S0 ;heated bed heater off (if you have it)\nG91 ;relative positioning\nG1 E-1 F300 ;retract the filament a bit before lifting the nozzle, to release some of the pressure\nG1 Z+0.5 E-5 X-20 Y-20 F9000 ;move Z up a bit and retract filament even more\nG28 X0 Y0 ;move X/Y to min endstops, so the head is out of the way\nM84 ;steppers off\nG90 ;absolute positioning"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
"categories": {
|
"overrides": {
|
||||||
"material": {
|
"material_bed_temperature": { "visible": false }
|
||||||
"settings": {
|
|
||||||
"material_bed_temperature": {
|
|
||||||
"visible": false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -10,6 +10,12 @@
|
|||||||
|
|
||||||
"inherits": "ultimaker_original.json",
|
"inherits": "ultimaker_original.json",
|
||||||
|
|
||||||
|
"pages": [
|
||||||
|
"UpgradeFirmware",
|
||||||
|
"UltimakerCheckup",
|
||||||
|
"BedLeveling"
|
||||||
|
],
|
||||||
|
|
||||||
"machine_settings": {
|
"machine_settings": {
|
||||||
"machine_heated_bed": { "default": true }
|
"machine_heated_bed": { "default": true }
|
||||||
}
|
}
|
BIN
resources/meshes/makerstarter_platform.stl
Normal file
BIN
resources/meshes/rigidbot_platform.stl
Normal file
BIN
resources/meshes/rigidbotbig_platform.stl
Normal file
6
resources/profiles/High+Quality.cfg
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
[general]
|
||||||
|
version = 1
|
||||||
|
name = High Quality
|
||||||
|
|
||||||
|
[settings]
|
||||||
|
layer_height = 0.06
|
6
resources/profiles/Normal+Quality.cfg
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
[general]
|
||||||
|
version = 1
|
||||||
|
name = Normal Quality
|
||||||
|
|
||||||
|
[settings]
|
||||||
|
layer_height = 0.1
|
@ -5,17 +5,21 @@ import QtQuick 2.2
|
|||||||
import QtQuick.Controls 1.1
|
import QtQuick.Controls 1.1
|
||||||
import QtQuick.Window 2.1
|
import QtQuick.Window 2.1
|
||||||
|
|
||||||
import UM 1.0 as UM
|
import UM 1.1 as UM
|
||||||
|
|
||||||
UM.Dialog {
|
UM.Dialog
|
||||||
|
{
|
||||||
id: base
|
id: base
|
||||||
|
|
||||||
//: About dialog title
|
//: About dialog title
|
||||||
title: qsTr("About Cura")
|
title: catalog.i18nc("@title:window","About Cura")
|
||||||
minimumWidth: 400
|
minimumWidth: 400
|
||||||
minimumHeight: 300
|
minimumHeight: 300;
|
||||||
|
//UM.I18nCatalog { id: catalog; }
|
||||||
|
|
||||||
Image {
|
|
||||||
|
Image
|
||||||
|
{
|
||||||
id: logo
|
id: logo
|
||||||
width: parent.width * 0.75
|
width: parent.width * 0.75
|
||||||
height: width * (1/4.25)
|
height: width * (1/4.25)
|
||||||
@ -26,9 +30,11 @@ UM.Dialog {
|
|||||||
sourceSize.height: height
|
sourceSize.height: height
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
anchors.verticalCenterOffset : -(height * 0.5)
|
anchors.verticalCenterOffset : -(height * 0.5)
|
||||||
|
UM.I18nCatalog{id: catalog; name:"cura"}
|
||||||
}
|
}
|
||||||
|
|
||||||
Label {
|
Label
|
||||||
|
{
|
||||||
id: version
|
id: version
|
||||||
|
|
||||||
text: "Cura %1".arg(UM.Application.version)
|
text: "Cura %1".arg(UM.Application.version)
|
||||||
@ -39,30 +45,33 @@ UM.Dialog {
|
|||||||
anchors.topMargin : 5
|
anchors.topMargin : 5
|
||||||
}
|
}
|
||||||
|
|
||||||
Label {
|
Label
|
||||||
|
{
|
||||||
id: description
|
id: description
|
||||||
width: parent.width
|
width: parent.width
|
||||||
|
|
||||||
//: About dialog application description
|
//: About dialog application description
|
||||||
text: qsTr("End-to-end solution for fused filament 3D printing.")
|
text: catalog.i18nc("@label","End-to-end solution for fused filament 3D printing.")
|
||||||
wrapMode: Text.WordWrap
|
wrapMode: Text.WordWrap
|
||||||
anchors.top: version.bottom
|
anchors.top: version.bottom
|
||||||
anchors.topMargin : 10
|
anchors.topMargin : 10
|
||||||
}
|
}
|
||||||
|
|
||||||
Label {
|
Label
|
||||||
|
{
|
||||||
id: author_note
|
id: author_note
|
||||||
width: parent.width
|
width: parent.width
|
||||||
|
|
||||||
//: About dialog application author note
|
//: About dialog application author note
|
||||||
text: qsTr("Cura has been developed by Ultimaker B.V. in cooperation with the community.")
|
text: catalog.i18nc("@info:credit","Cura has been developed by Ultimaker B.V. in cooperation with the community.")
|
||||||
wrapMode: Text.WordWrap
|
wrapMode: Text.WordWrap
|
||||||
anchors.top: description.bottom
|
anchors.top: description.bottom
|
||||||
}
|
}
|
||||||
|
|
||||||
rightButtons: Button {
|
rightButtons: Button
|
||||||
|
{
|
||||||
//: Close about dialog button
|
//: Close about dialog button
|
||||||
text: qsTr("Close");
|
text: catalog.i18nc("@action:button","Close");
|
||||||
|
|
||||||
onClicked: base.visible = false;
|
onClicked: base.visible = false;
|
||||||
}
|
}
|
||||||
|
@ -3,11 +3,11 @@
|
|||||||
|
|
||||||
import QtQuick 2.2
|
import QtQuick 2.2
|
||||||
import QtQuick.Controls 1.1
|
import QtQuick.Controls 1.1
|
||||||
import UM 1.0 as UM
|
import UM 1.1 as UM
|
||||||
|
|
||||||
Item {
|
Item
|
||||||
|
{
|
||||||
property alias open: openAction;
|
property alias open: openAction;
|
||||||
property alias save: saveAction;
|
|
||||||
property alias quit: quitAction;
|
property alias quit: quitAction;
|
||||||
|
|
||||||
property alias undo: undoAction;
|
property alias undo: undoAction;
|
||||||
@ -23,7 +23,6 @@ Item {
|
|||||||
//property alias unMergeObjects: unMergeObjectsAction;
|
//property alias unMergeObjects: unMergeObjectsAction;
|
||||||
|
|
||||||
property alias multiplyObject: multiplyObjectAction;
|
property alias multiplyObject: multiplyObjectAction;
|
||||||
property alias splitObject: splitObjectAction;
|
|
||||||
|
|
||||||
property alias deleteAll: deleteAllAction;
|
property alias deleteAll: deleteAllAction;
|
||||||
property alias reloadAll: reloadAllAction;
|
property alias reloadAll: reloadAllAction;
|
||||||
@ -32,6 +31,7 @@ Item {
|
|||||||
|
|
||||||
property alias addMachine: addMachineAction;
|
property alias addMachine: addMachineAction;
|
||||||
property alias configureMachines: settingsAction;
|
property alias configureMachines: settingsAction;
|
||||||
|
property alias manageProfiles: manageProfilesAction;
|
||||||
|
|
||||||
property alias preferences: preferencesAction;
|
property alias preferences: preferencesAction;
|
||||||
|
|
||||||
@ -40,172 +40,181 @@ Item {
|
|||||||
property alias reportBug: reportBugAction;
|
property alias reportBug: reportBugAction;
|
||||||
property alias about: aboutAction;
|
property alias about: aboutAction;
|
||||||
|
|
||||||
Action {
|
property alias toggleFullScreen: toggleFullScreenAction;
|
||||||
|
|
||||||
|
UM.I18nCatalog{id: catalog; name:"cura"}
|
||||||
|
|
||||||
|
Action
|
||||||
|
{
|
||||||
|
id:toggleFullScreenAction
|
||||||
|
shortcut: StandardKey.FullScreen;
|
||||||
|
text: catalog.i18nc("@action:inmenu","Toggle Fu&ll Screen");
|
||||||
|
iconName: "view-fullscreen";
|
||||||
|
}
|
||||||
|
|
||||||
|
Action
|
||||||
|
{
|
||||||
id: undoAction;
|
id: undoAction;
|
||||||
//: Undo action
|
text: catalog.i18nc("@action:inmenu","&Undo");
|
||||||
text: qsTr("&Undo");
|
|
||||||
iconName: "edit-undo";
|
iconName: "edit-undo";
|
||||||
shortcut: StandardKey.Undo;
|
shortcut: StandardKey.Undo;
|
||||||
}
|
}
|
||||||
|
|
||||||
Action {
|
Action
|
||||||
|
{
|
||||||
id: redoAction;
|
id: redoAction;
|
||||||
//: Redo action
|
text: catalog.i18nc("@action:inmenu","&Redo");
|
||||||
text: qsTr("&Redo");
|
|
||||||
iconName: "edit-redo";
|
iconName: "edit-redo";
|
||||||
shortcut: StandardKey.Redo;
|
shortcut: StandardKey.Redo;
|
||||||
}
|
}
|
||||||
|
|
||||||
Action {
|
Action
|
||||||
|
{
|
||||||
id: quitAction;
|
id: quitAction;
|
||||||
//: Quit action
|
text: catalog.i18nc("@action:inmenu","&Quit");
|
||||||
text: qsTr("&Quit");
|
|
||||||
iconName: "application-exit";
|
iconName: "application-exit";
|
||||||
shortcut: StandardKey.Quit;
|
shortcut: StandardKey.Quit;
|
||||||
}
|
}
|
||||||
|
|
||||||
Action {
|
Action
|
||||||
|
{
|
||||||
id: preferencesAction;
|
id: preferencesAction;
|
||||||
//: Preferences action
|
text: catalog.i18nc("@action:inmenu","&Preferences...");
|
||||||
text: qsTr("&Preferences...");
|
|
||||||
iconName: "configure";
|
iconName: "configure";
|
||||||
}
|
}
|
||||||
|
|
||||||
Action {
|
Action
|
||||||
|
{
|
||||||
id: addMachineAction;
|
id: addMachineAction;
|
||||||
//: Add Printer action
|
text: catalog.i18nc("@action:inmenu","&Add Printer...");
|
||||||
text: qsTr("&Add Printer...");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Action {
|
Action
|
||||||
|
{
|
||||||
id: settingsAction;
|
id: settingsAction;
|
||||||
//: Configure Printers action
|
text: catalog.i18nc("@action:inmenu","Manage Pr&inters...");
|
||||||
text: qsTr("&Configure Printers");
|
|
||||||
iconName: "configure";
|
iconName: "configure";
|
||||||
}
|
}
|
||||||
|
|
||||||
Action {
|
Action
|
||||||
|
{
|
||||||
|
id: manageProfilesAction;
|
||||||
|
text: catalog.i18nc("@action:inmenu","Manage Profiles...");
|
||||||
|
iconName: "configure";
|
||||||
|
}
|
||||||
|
|
||||||
|
Action
|
||||||
|
{
|
||||||
id: documentationAction;
|
id: documentationAction;
|
||||||
//: Show Online Documentation action
|
text: catalog.i18nc("@action:inmenu","Show Online &Documentation");
|
||||||
text: qsTr("Show Online &Documentation");
|
|
||||||
iconName: "help-contents";
|
iconName: "help-contents";
|
||||||
shortcut: StandardKey.Help;
|
shortcut: StandardKey.Help;
|
||||||
}
|
}
|
||||||
|
|
||||||
Action {
|
Action {
|
||||||
id: reportBugAction;
|
id: reportBugAction;
|
||||||
//: Report a Bug Action
|
text: catalog.i18nc("@action:inmenu","Report a &Bug");
|
||||||
text: qsTr("Report a &Bug");
|
|
||||||
iconName: "tools-report-bug";
|
iconName: "tools-report-bug";
|
||||||
}
|
}
|
||||||
|
|
||||||
Action {
|
Action
|
||||||
|
{
|
||||||
id: aboutAction;
|
id: aboutAction;
|
||||||
//: About action
|
text: catalog.i18nc("@action:inmenu","&About...");
|
||||||
text: qsTr("&About...");
|
|
||||||
iconName: "help-about";
|
iconName: "help-about";
|
||||||
}
|
}
|
||||||
|
|
||||||
Action {
|
Action
|
||||||
|
{
|
||||||
id: deleteSelectionAction;
|
id: deleteSelectionAction;
|
||||||
//: Delete selection action
|
text: catalog.i18nc("@action:inmenu","Delete &Selection");
|
||||||
text: qsTr("Delete Selection");
|
|
||||||
iconName: "edit-delete";
|
iconName: "edit-delete";
|
||||||
shortcut: StandardKey.Delete;
|
shortcut: StandardKey.Delete;
|
||||||
}
|
}
|
||||||
|
|
||||||
Action {
|
Action
|
||||||
|
{
|
||||||
id: deleteObjectAction;
|
id: deleteObjectAction;
|
||||||
//: Delete object action
|
text: catalog.i18nc("@action:inmenu","Delete Object");
|
||||||
text: qsTr("Delete Object");
|
|
||||||
iconName: "edit-delete";
|
iconName: "edit-delete";
|
||||||
|
shortcut: StandardKey.Backspace;
|
||||||
}
|
}
|
||||||
|
|
||||||
Action {
|
Action
|
||||||
|
{
|
||||||
id: centerObjectAction;
|
id: centerObjectAction;
|
||||||
//: Center object action
|
text: catalog.i18nc("@action:inmenu","Ce&nter Object on Platform");
|
||||||
text: qsTr("Center Object on Platform");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Action
|
Action
|
||||||
{
|
{
|
||||||
id: groupObjectsAction
|
id: groupObjectsAction
|
||||||
text: qsTr("Group objects");
|
text: catalog.i18nc("@action:inmenu","&Group Objects");
|
||||||
enabled: UM.Scene.numObjectsSelected > 1 ? true: false
|
enabled: UM.Scene.numObjectsSelected > 1 ? true: false
|
||||||
|
iconName: "object-group"
|
||||||
}
|
}
|
||||||
|
|
||||||
Action
|
Action
|
||||||
{
|
{
|
||||||
id: unGroupObjectsAction
|
id: unGroupObjectsAction
|
||||||
text: qsTr("Ungroup objects");
|
text: catalog.i18nc("@action:inmenu","Ungroup Objects");
|
||||||
enabled: UM.Scene.isGroupSelected
|
enabled: UM.Scene.isGroupSelected
|
||||||
|
iconName: "object-ungroup"
|
||||||
}
|
}
|
||||||
|
|
||||||
Action
|
Action
|
||||||
{
|
{
|
||||||
id: mergeObjectsAction
|
id: mergeObjectsAction
|
||||||
text: qsTr("Merge objects");
|
text: catalog.i18nc("@action:inmenu","&Merge Objects");
|
||||||
enabled: UM.Scene.numObjectsSelected > 1 ? true: false
|
enabled: UM.Scene.numObjectsSelected > 1 ? true: false
|
||||||
|
iconName: "merge";
|
||||||
}
|
}
|
||||||
|
|
||||||
Action {
|
Action
|
||||||
|
{
|
||||||
id: multiplyObjectAction;
|
id: multiplyObjectAction;
|
||||||
//: Duplicate object action
|
text: catalog.i18nc("@action:inmenu","&Duplicate Object");
|
||||||
text: qsTr("Duplicate Object");
|
iconName: "edit-duplicate"
|
||||||
}
|
}
|
||||||
|
|
||||||
Action {
|
Action
|
||||||
id: splitObjectAction;
|
{
|
||||||
//: Split object action
|
|
||||||
text: qsTr("Split Object into Parts");
|
|
||||||
enabled: false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Action {
|
|
||||||
id: deleteAllAction;
|
id: deleteAllAction;
|
||||||
//: Clear build platform action
|
text: catalog.i18nc("@action:inmenu","&Clear Build Platform");
|
||||||
text: qsTr("Clear Build Platform");
|
iconName: "edit-delete";
|
||||||
iconName: "edit-clear";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Action {
|
Action
|
||||||
|
{
|
||||||
id: reloadAllAction;
|
id: reloadAllAction;
|
||||||
//: Reload all objects action
|
text: catalog.i18nc("@action:inmenu","Re&load All Objects");
|
||||||
text: qsTr("Reload All Objects");
|
iconName: "document-revert";
|
||||||
}
|
}
|
||||||
|
|
||||||
Action {
|
Action
|
||||||
|
{
|
||||||
id: resetAllTranslationAction;
|
id: resetAllTranslationAction;
|
||||||
//: Reset all positions action
|
text: catalog.i18nc("@action:inmenu","Reset All Object Positions");
|
||||||
text: qsTr("Reset All Object Positions");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Action {
|
Action
|
||||||
|
{
|
||||||
id: resetAllAction;
|
id: resetAllAction;
|
||||||
//: Reset all positions action
|
text: catalog.i18nc("@action:inmenu","Reset All Object &Transformations");
|
||||||
text: qsTr("Reset All Object Transformations");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Action {
|
Action
|
||||||
|
{
|
||||||
id: openAction;
|
id: openAction;
|
||||||
//: Open file action
|
text: catalog.i18nc("@action:inmenu","&Open File...");
|
||||||
text: qsTr("&Open...");
|
|
||||||
iconName: "document-open";
|
iconName: "document-open";
|
||||||
shortcut: StandardKey.Open;
|
shortcut: StandardKey.Open;
|
||||||
}
|
}
|
||||||
|
|
||||||
Action {
|
Action
|
||||||
id: saveAction;
|
{
|
||||||
//: Save file action
|
|
||||||
text: qsTr("&Save...");
|
|
||||||
iconName: "document-save";
|
|
||||||
shortcut: StandardKey.Save;
|
|
||||||
}
|
|
||||||
|
|
||||||
Action {
|
|
||||||
id: showEngineLogAction;
|
id: showEngineLogAction;
|
||||||
//: Show engine log action
|
text: catalog.i18nc("@action:inmenu","Show Engine &Log...");
|
||||||
text: qsTr("Show engine &log...");
|
|
||||||
iconName: "view-list-text";
|
iconName: "view-list-text";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,11 +6,27 @@ import QtQuick.Controls 1.1
|
|||||||
import QtQuick.Layouts 1.1
|
import QtQuick.Layouts 1.1
|
||||||
import QtQuick.Window 2.1
|
import QtQuick.Window 2.1
|
||||||
|
|
||||||
import UM 1.0 as UM
|
import UM 1.1 as UM
|
||||||
|
import Cura 1.0 as Cura
|
||||||
|
|
||||||
UM.Wizard{
|
import "WizardPages"
|
||||||
id: base
|
|
||||||
property bool printer: true
|
UM.Wizard
|
||||||
file: "ultimaker2.json"
|
{
|
||||||
firstRun: printer ? false : true
|
id: base;
|
||||||
|
|
||||||
|
title: catalog.i18nc("@title:window", "Add Printer")
|
||||||
|
|
||||||
|
// This part is optional
|
||||||
|
// This part checks whether there is a printer -> if not: some of the functions (delete for example) are disabled
|
||||||
|
firstRun: false
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
base.appendPage(Qt.resolvedUrl("WizardPages/AddMachine.qml"), catalog.i18nc("@title", "Add Printer"));
|
||||||
|
base.currentPage = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
UM.I18nCatalog { id: catalog; name: "cura"; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,43 +9,56 @@ import QtQuick.Dialogs 1.1
|
|||||||
|
|
||||||
import UM 1.1 as UM
|
import UM 1.1 as UM
|
||||||
|
|
||||||
UM.MainWindow {
|
UM.MainWindow
|
||||||
|
{
|
||||||
id: base
|
id: base
|
||||||
visible: true
|
|
||||||
|
|
||||||
//: Cura application window title
|
//: Cura application window title
|
||||||
title: qsTr("Cura");
|
title: catalog.i18nc("@title:window","Cura");
|
||||||
|
|
||||||
Item {
|
viewportRect: Qt.rect(0, 0, (base.width - sidebar.width) / base.width, 1.0)
|
||||||
|
|
||||||
|
Item
|
||||||
|
{
|
||||||
id: backgroundItem;
|
id: backgroundItem;
|
||||||
anchors.fill: parent;
|
anchors.fill: parent;
|
||||||
|
UM.I18nCatalog{id: catalog; name:"cura"}
|
||||||
UM.ApplicationMenu {
|
UM.ApplicationMenu
|
||||||
|
{
|
||||||
id: menu
|
id: menu
|
||||||
window: base
|
window: base
|
||||||
|
|
||||||
Menu {
|
Menu
|
||||||
|
{
|
||||||
id: fileMenu
|
id: fileMenu
|
||||||
//: File menu
|
//: File menu
|
||||||
title: qsTr("&File");
|
title: catalog.i18nc("@title:menu","&File");
|
||||||
|
|
||||||
MenuItem { action: actions.open; }
|
MenuItem {
|
||||||
|
action: actions.open;
|
||||||
|
}
|
||||||
|
|
||||||
Menu {
|
Menu
|
||||||
|
{
|
||||||
id: recentFilesMenu;
|
id: recentFilesMenu;
|
||||||
title: "Open Recent"
|
title: catalog.i18nc("@title:menu", "Open &Recent")
|
||||||
iconName: "document-open-recent";
|
iconName: "document-open-recent";
|
||||||
|
|
||||||
enabled: Printer.recentFiles.length > 0;
|
enabled: Printer.recentFiles.length > 0;
|
||||||
|
|
||||||
Instantiator {
|
Instantiator
|
||||||
|
{
|
||||||
model: Printer.recentFiles
|
model: Printer.recentFiles
|
||||||
MenuItem {
|
MenuItem
|
||||||
text: {
|
{
|
||||||
|
text:
|
||||||
|
{
|
||||||
var path = modelData.toString()
|
var path = modelData.toString()
|
||||||
return (index + 1) + ". " + path.slice(path.lastIndexOf("/") + 1);
|
return (index + 1) + ". " + path.slice(path.lastIndexOf("/") + 1);
|
||||||
}
|
}
|
||||||
onTriggered: UM.MeshFileHandler.readLocalFile(modelData);
|
onTriggered: {
|
||||||
|
UM.MeshFileHandler.readLocalFile(modelData);
|
||||||
|
openDialog.sendMeshName(modelData.toString())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
onObjectAdded: recentFilesMenu.insertItem(index, object)
|
onObjectAdded: recentFilesMenu.insertItem(index, object)
|
||||||
onObjectRemoved: recentFilesMenu.removeItem(object)
|
onObjectRemoved: recentFilesMenu.removeItem(object)
|
||||||
@ -54,52 +67,66 @@ UM.MainWindow {
|
|||||||
|
|
||||||
MenuSeparator { }
|
MenuSeparator { }
|
||||||
|
|
||||||
MenuItem {
|
MenuItem
|
||||||
text: "Save Selection to File";
|
{
|
||||||
|
text: catalog.i18nc("@action:inmenu", "&Save Selection to File");
|
||||||
enabled: UM.Selection.hasSelection;
|
enabled: UM.Selection.hasSelection;
|
||||||
iconName: "document-save-as";
|
iconName: "document-save-as";
|
||||||
onTriggered: devicesModel.requestWriteSelectionToDevice("local_file");
|
onTriggered: UM.OutputDeviceManager.requestWriteSelectionToDevice("local_file");
|
||||||
}
|
}
|
||||||
Menu {
|
Menu
|
||||||
|
{
|
||||||
id: saveAllMenu
|
id: saveAllMenu
|
||||||
title: "Save All"
|
title: catalog.i18nc("@title:menu","Save &All")
|
||||||
iconName: "document-save";
|
iconName: "document-save-all";
|
||||||
enabled: devicesModel.count > 0 && UM.Backend.progress > 0.99;
|
enabled: devicesModel.rowCount() > 0 && UM.Backend.progress > 0.99;
|
||||||
|
|
||||||
Instantiator {
|
Instantiator
|
||||||
|
{
|
||||||
model: UM.OutputDevicesModel { id: devicesModel; }
|
model: UM.OutputDevicesModel { id: devicesModel; }
|
||||||
|
|
||||||
MenuItem {
|
MenuItem
|
||||||
text: model.description
|
{
|
||||||
onTriggered: devicesModel.requestWriteToDevice(model.id);
|
text: model.description;
|
||||||
|
onTriggered: UM.OutputDeviceManager.requestWriteToDevice(model.id);
|
||||||
}
|
}
|
||||||
onObjectAdded: saveAllMenu.insertItem(index, object)
|
onObjectAdded: saveAllMenu.insertItem(index, object)
|
||||||
onObjectRemoved: saveAllMenu.removeItem(object)
|
onObjectRemoved: saveAllMenu.removeItem(object)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MenuItem { action: actions.reloadAll; }
|
||||||
|
|
||||||
MenuSeparator { }
|
MenuSeparator { }
|
||||||
|
|
||||||
MenuItem { action: actions.quit; }
|
MenuItem { action: actions.quit; }
|
||||||
}
|
}
|
||||||
|
|
||||||
Menu {
|
Menu
|
||||||
|
{
|
||||||
//: Edit menu
|
//: Edit menu
|
||||||
title: qsTr("&Edit");
|
title: catalog.i18nc("@title:menu","&Edit");
|
||||||
|
|
||||||
MenuItem { action: actions.undo; }
|
MenuItem { action: actions.undo; }
|
||||||
MenuItem { action: actions.redo; }
|
MenuItem { action: actions.redo; }
|
||||||
MenuSeparator { }
|
MenuSeparator { }
|
||||||
MenuItem { action: actions.deleteSelection; }
|
MenuItem { action: actions.deleteSelection; }
|
||||||
MenuItem { action: actions.deleteAll; }
|
MenuItem { action: actions.deleteAll; }
|
||||||
|
MenuItem { action: actions.resetAllTranslation; }
|
||||||
|
MenuItem { action: actions.resetAll; }
|
||||||
|
MenuSeparator { }
|
||||||
|
MenuItem { action: actions.groupObjects;}
|
||||||
|
MenuItem { action: actions.mergeObjects;}
|
||||||
|
MenuItem { action: actions.unGroupObjects;}
|
||||||
}
|
}
|
||||||
|
|
||||||
Menu
|
Menu
|
||||||
{
|
{
|
||||||
title: qsTr("&View");
|
title: catalog.i18nc("@title:menu","&View");
|
||||||
id: top_view_menu
|
id: top_view_menu
|
||||||
Instantiator
|
Instantiator
|
||||||
{
|
{
|
||||||
model: UM.Models.viewModel
|
model: UM.ViewModel { }
|
||||||
MenuItem
|
MenuItem
|
||||||
{
|
{
|
||||||
text: model.name;
|
text: model.name;
|
||||||
@ -112,20 +139,27 @@ UM.MainWindow {
|
|||||||
onObjectRemoved: top_view_menu.removeItem(object)
|
onObjectRemoved: top_view_menu.removeItem(object)
|
||||||
}
|
}
|
||||||
ExclusiveGroup { id: view_menu_top_group; }
|
ExclusiveGroup { id: view_menu_top_group; }
|
||||||
|
|
||||||
|
MenuSeparator { }
|
||||||
|
|
||||||
|
MenuItem { action: actions.toggleFullScreen; }
|
||||||
}
|
}
|
||||||
Menu {
|
Menu
|
||||||
|
{
|
||||||
id: machineMenu;
|
id: machineMenu;
|
||||||
//: Machine menu
|
//: Machine menu
|
||||||
title: qsTr("&Machine");
|
title: catalog.i18nc("@title:menu","&Machine");
|
||||||
|
|
||||||
Instantiator {
|
Instantiator
|
||||||
model: UM.Models.machinesModel
|
{
|
||||||
MenuItem {
|
model: UM.MachineInstancesModel { }
|
||||||
|
MenuItem
|
||||||
|
{
|
||||||
text: model.name;
|
text: model.name;
|
||||||
checkable: true;
|
checkable: true;
|
||||||
checked: model.active;
|
checked: model.active;
|
||||||
exclusiveGroup: machineMenuGroup;
|
exclusiveGroup: machineMenuGroup;
|
||||||
onTriggered: UM.Models.machinesModel.setActive(index)
|
onTriggered: UM.MachineManager.setActiveMachineInstance(model.name)
|
||||||
}
|
}
|
||||||
onObjectAdded: machineMenu.insertItem(index, object)
|
onObjectAdded: machineMenu.insertItem(index, object)
|
||||||
onObjectRemoved: machineMenu.removeItem(object)
|
onObjectRemoved: machineMenu.removeItem(object)
|
||||||
@ -135,14 +169,59 @@ UM.MainWindow {
|
|||||||
|
|
||||||
MenuSeparator { }
|
MenuSeparator { }
|
||||||
|
|
||||||
|
Instantiator
|
||||||
|
{
|
||||||
|
model: UM.MachineVariantsModel { }
|
||||||
|
MenuItem {
|
||||||
|
text: model.name;
|
||||||
|
checkable: true;
|
||||||
|
checked: model.active;
|
||||||
|
exclusiveGroup: machineVariantsGroup;
|
||||||
|
onTriggered: UM.MachineManager.setActiveMachineVariant(model.name)
|
||||||
|
}
|
||||||
|
onObjectAdded: machineMenu.insertItem(index, object)
|
||||||
|
onObjectRemoved: machineMenu.removeItem(object)
|
||||||
|
}
|
||||||
|
|
||||||
|
ExclusiveGroup { id: machineVariantsGroup; }
|
||||||
|
|
||||||
|
MenuSeparator { visible: UM.MachineManager.hasVariants; }
|
||||||
|
|
||||||
MenuItem { action: actions.addMachine; }
|
MenuItem { action: actions.addMachine; }
|
||||||
MenuItem { action: actions.configureMachines; }
|
MenuItem { action: actions.configureMachines; }
|
||||||
}
|
}
|
||||||
|
|
||||||
Menu {
|
Menu
|
||||||
|
{
|
||||||
|
id: profileMenu
|
||||||
|
title: catalog.i18nc("@title:menu", "&Profile")
|
||||||
|
|
||||||
|
Instantiator
|
||||||
|
{
|
||||||
|
model: UM.ProfilesModel { }
|
||||||
|
MenuItem {
|
||||||
|
text: model.name;
|
||||||
|
checkable: true;
|
||||||
|
checked: model.active;
|
||||||
|
exclusiveGroup: profileMenuGroup;
|
||||||
|
onTriggered: UM.MachineManager.setActiveProfile(model.name)
|
||||||
|
}
|
||||||
|
onObjectAdded: profileMenu.insertItem(index, object)
|
||||||
|
onObjectRemoved: profileMenu.removeItem(object)
|
||||||
|
}
|
||||||
|
|
||||||
|
ExclusiveGroup { id: profileMenuGroup; }
|
||||||
|
|
||||||
|
MenuSeparator { }
|
||||||
|
|
||||||
|
MenuItem { action: actions.manageProfiles; }
|
||||||
|
}
|
||||||
|
|
||||||
|
Menu
|
||||||
|
{
|
||||||
id: extension_menu
|
id: extension_menu
|
||||||
//: Extensions menu
|
//: Extensions menu
|
||||||
title: qsTr("E&xtensions");
|
title: catalog.i18nc("@title:menu","E&xtensions");
|
||||||
|
|
||||||
Instantiator
|
Instantiator
|
||||||
{
|
{
|
||||||
@ -152,7 +231,8 @@ UM.MainWindow {
|
|||||||
{
|
{
|
||||||
id: sub_menu
|
id: sub_menu
|
||||||
title: model.name;
|
title: model.name;
|
||||||
|
visible: actions != null
|
||||||
|
enabled:actions != null
|
||||||
Instantiator
|
Instantiator
|
||||||
{
|
{
|
||||||
model: actions
|
model: actions
|
||||||
@ -171,16 +251,18 @@ UM.MainWindow {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Menu {
|
Menu
|
||||||
|
{
|
||||||
//: Settings menu
|
//: Settings menu
|
||||||
title: qsTr("&Settings");
|
title: catalog.i18nc("@title:menu","&Settings");
|
||||||
|
|
||||||
MenuItem { action: actions.preferences; }
|
MenuItem { action: actions.preferences; }
|
||||||
}
|
}
|
||||||
|
|
||||||
Menu {
|
Menu
|
||||||
|
{
|
||||||
//: Help menu
|
//: Help menu
|
||||||
title: qsTr("&Help");
|
title: catalog.i18nc("@title:menu","&Help");
|
||||||
|
|
||||||
MenuItem { action: actions.showEngineLog; }
|
MenuItem { action: actions.showEngineLog; }
|
||||||
MenuItem { action: actions.documentation; }
|
MenuItem { action: actions.documentation; }
|
||||||
@ -190,7 +272,8 @@ UM.MainWindow {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Item {
|
Item
|
||||||
|
{
|
||||||
id: contentItem;
|
id: contentItem;
|
||||||
|
|
||||||
y: menu.height
|
y: menu.height
|
||||||
@ -199,23 +282,31 @@ UM.MainWindow {
|
|||||||
|
|
||||||
Keys.forwardTo: menu
|
Keys.forwardTo: menu
|
||||||
|
|
||||||
DropArea {
|
DropArea
|
||||||
|
{
|
||||||
anchors.fill: parent;
|
anchors.fill: parent;
|
||||||
onDropped: {
|
onDropped:
|
||||||
if(drop.urls.length > 0) {
|
{
|
||||||
for(var i in drop.urls) {
|
if(drop.urls.length > 0)
|
||||||
|
{
|
||||||
|
for(var i in drop.urls)
|
||||||
|
{
|
||||||
UM.MeshFileHandler.readLocalFile(drop.urls[i]);
|
UM.MeshFileHandler.readLocalFile(drop.urls[i]);
|
||||||
|
if (i == drop.urls.length - 1)
|
||||||
|
{
|
||||||
|
openDialog.sendMeshName(drop.urls[i].toString())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
UM.MessageStack {
|
UM.MessageStack
|
||||||
anchors {
|
{
|
||||||
left: toolbar.right;
|
anchors
|
||||||
leftMargin: UM.Theme.sizes.window_margin.width;
|
{
|
||||||
right: sidebar.left;
|
horizontalCenter: parent.horizontalCenter
|
||||||
rightMargin: UM.Theme.sizes.window_margin.width;
|
horizontalCenterOffset: -(UM.Theme.sizes.logo.width/ 2)
|
||||||
top: parent.verticalCenter;
|
top: parent.verticalCenter;
|
||||||
bottom: parent.bottom;
|
bottom: parent.bottom;
|
||||||
}
|
}
|
||||||
@ -240,27 +331,34 @@ UM.MainWindow {
|
|||||||
source: UM.ActiveView.valid ? UM.ActiveView.activeViewPanel : "";
|
source: UM.ActiveView.valid ? UM.ActiveView.activeViewPanel : "";
|
||||||
}
|
}
|
||||||
|
|
||||||
Button {
|
Button
|
||||||
|
{
|
||||||
id: openFileButton;
|
id: openFileButton;
|
||||||
|
//style: UM.Backend.progress < 0 ? UM.Theme.styles.open_file_button : UM.Theme.styles.tool_button;
|
||||||
iconSource: UM.Theme.icons.open;
|
//style: UM.Theme.styles.open_file_button
|
||||||
style: UM.Backend.progress < 0 ? UM.Theme.styles.open_file_button : UM.Theme.styles.tool_button;
|
text: catalog.i18nc("@action:button","Open File");
|
||||||
|
iconSource: UM.Theme.icons.load
|
||||||
|
style: UM.Theme.styles.open_file_button
|
||||||
tooltip: '';
|
tooltip: '';
|
||||||
anchors {
|
anchors
|
||||||
|
{
|
||||||
top: parent.top;
|
top: parent.top;
|
||||||
topMargin: UM.Theme.sizes.window_margin.height;
|
//topMargin: UM.Theme.sizes.loadfile_margin.height
|
||||||
left: parent.left;
|
left: parent.left;
|
||||||
leftMargin: UM.Theme.sizes.window_margin.width;
|
//leftMargin: UM.Theme.sizes.loadfile_margin.width
|
||||||
}
|
}
|
||||||
|
|
||||||
action: actions.open;
|
action: actions.open;
|
||||||
}
|
}
|
||||||
|
|
||||||
Image {
|
Image
|
||||||
anchors {
|
{
|
||||||
verticalCenter: openFileButton.verticalCenter;
|
id: logo
|
||||||
left: openFileButton.right;
|
anchors
|
||||||
leftMargin: UM.Theme.sizes.window_margin.width;
|
{
|
||||||
|
left: parent.left
|
||||||
|
leftMargin: UM.Theme.sizes.default_margin.width;
|
||||||
|
bottom: parent.bottom
|
||||||
|
bottomMargin: UM.Theme.sizes.default_margin.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
source: UM.Theme.images.logo;
|
source: UM.Theme.images.logo;
|
||||||
@ -271,25 +369,29 @@ UM.MainWindow {
|
|||||||
sourceSize.height: height;
|
sourceSize.height: height;
|
||||||
}
|
}
|
||||||
|
|
||||||
Button {
|
Button
|
||||||
anchors {
|
{
|
||||||
|
id: viewModeButton
|
||||||
|
property bool verticalTooltip: true
|
||||||
|
anchors
|
||||||
|
{
|
||||||
top: parent.top;
|
top: parent.top;
|
||||||
topMargin: UM.Theme.sizes.window_margin.height;
|
|
||||||
right: sidebar.left;
|
right: sidebar.left;
|
||||||
rightMargin: UM.Theme.sizes.window_margin.width;
|
rightMargin: UM.Theme.sizes.window_margin.width;
|
||||||
}
|
}
|
||||||
id: viewModeButton
|
text: catalog.i18nc("@action:button","View Mode");
|
||||||
//: View Mode toolbar button
|
|
||||||
text: qsTr("View Mode");
|
|
||||||
iconSource: UM.Theme.icons.viewmode;
|
iconSource: UM.Theme.icons.viewmode;
|
||||||
|
|
||||||
style: UM.Theme.styles.tool_button;
|
style: UM.Theme.styles.tool_button;
|
||||||
tooltip: '';
|
tooltip: '';
|
||||||
menu: Menu {
|
menu: Menu
|
||||||
|
{
|
||||||
id: viewMenu;
|
id: viewMenu;
|
||||||
Instantiator {
|
Instantiator
|
||||||
model: UM.Models.viewModel;
|
{
|
||||||
MenuItem {
|
model: UM.ViewModel { }
|
||||||
|
MenuItem
|
||||||
|
{
|
||||||
text: model.name;
|
text: model.name;
|
||||||
checkable: true;
|
checkable: true;
|
||||||
checked: model.active;
|
checked: model.active;
|
||||||
@ -304,39 +406,47 @@ UM.MainWindow {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Toolbar {
|
Toolbar
|
||||||
|
{
|
||||||
id: toolbar;
|
id: toolbar;
|
||||||
|
|
||||||
anchors {
|
anchors {
|
||||||
left: parent.left;
|
left: parent.left
|
||||||
leftMargin: UM.Theme.sizes.window_margin.width;
|
top: parent.top
|
||||||
bottom: parent.bottom;
|
topMargin: 74
|
||||||
bottomMargin: UM.Theme.sizes.window_margin.height;
|
//horizontalCenter: parent.horizontalCenter
|
||||||
|
//horizontalCenterOffset: -(UM.Theme.sizes.sidebar.width / 2)
|
||||||
|
//top: parent.top;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Sidebar {
|
Sidebar
|
||||||
|
{
|
||||||
id: sidebar;
|
id: sidebar;
|
||||||
|
|
||||||
anchors {
|
anchors
|
||||||
|
{
|
||||||
top: parent.top;
|
top: parent.top;
|
||||||
bottom: parent.bottom;
|
bottom: parent.bottom;
|
||||||
right: parent.right;
|
right: parent.right;
|
||||||
}
|
}
|
||||||
|
|
||||||
width: UM.Theme.sizes.panel.width;
|
width: UM.Theme.sizes.sidebar.width;
|
||||||
|
|
||||||
addMachineAction: actions.addMachine;
|
addMachineAction: actions.addMachine;
|
||||||
configureMachinesAction: actions.configureMachines;
|
configureMachinesAction: actions.configureMachines;
|
||||||
|
manageProfilesAction: actions.manageProfiles;
|
||||||
}
|
}
|
||||||
|
|
||||||
Rectangle {
|
Rectangle
|
||||||
|
{
|
||||||
x: base.mouseX + UM.Theme.sizes.default_margin.width;
|
x: base.mouseX + UM.Theme.sizes.default_margin.width;
|
||||||
y: base.mouseY + UM.Theme.sizes.default_margin.height;
|
y: base.mouseY + UM.Theme.sizes.default_margin.height;
|
||||||
|
|
||||||
width: childrenRect.width;
|
width: childrenRect.width;
|
||||||
height: childrenRect.height;
|
height: childrenRect.height;
|
||||||
Label {
|
Label
|
||||||
|
{
|
||||||
text: UM.ActiveTool.properties.Rotation != undefined ? "%1°".arg(UM.ActiveTool.properties.Rotation) : "";
|
text: UM.ActiveTool.properties.Rotation != undefined ? "%1°".arg(UM.ActiveTool.properties.Rotation) : "";
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -345,20 +455,29 @@ UM.MainWindow {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
UM.PreferencesDialog {
|
UM.PreferencesDialog
|
||||||
|
{
|
||||||
id: preferences
|
id: preferences
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted:
|
||||||
|
{
|
||||||
|
//; Remove & re-add the general page as we want to use our own instead of uranium standard.
|
||||||
|
removePage(0);
|
||||||
|
insertPage(0, catalog.i18nc("@title:tab","General") , "" , Qt.resolvedUrl("./GeneralPage.qml"));
|
||||||
|
|
||||||
//: View preferences page title
|
//: View preferences page title
|
||||||
insertPage(1, qsTr("View"), "view-preview", Qt.resolvedUrl("./ViewPage.qml"));
|
insertPage(1, catalog.i18nc("@title:tab","View"), "view-preview", Qt.resolvedUrl("./ViewPage.qml"));
|
||||||
|
|
||||||
|
//Force refresh
|
||||||
|
setPage(0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Actions {
|
Actions
|
||||||
|
{
|
||||||
id: actions;
|
id: actions;
|
||||||
|
|
||||||
open.onTriggered: openDialog.open();
|
open.onTriggered: openDialog.open();
|
||||||
save.onTriggered: saveDialog.open();
|
|
||||||
|
|
||||||
quit.onTriggered: base.visible = false;
|
quit.onTriggered: base.visible = false;
|
||||||
|
|
||||||
@ -367,28 +486,36 @@ UM.MainWindow {
|
|||||||
redo.onTriggered: UM.OperationStack.redo();
|
redo.onTriggered: UM.OperationStack.redo();
|
||||||
redo.enabled: UM.OperationStack.canRedo;
|
redo.enabled: UM.OperationStack.canRedo;
|
||||||
|
|
||||||
deleteSelection.onTriggered: {
|
deleteSelection.onTriggered:
|
||||||
if(objectContextMenu.objectId != 0) {
|
{
|
||||||
|
if(objectContextMenu.objectId != 0)
|
||||||
|
{
|
||||||
Printer.deleteObject(objectContextMenu.objectId);
|
Printer.deleteObject(objectContextMenu.objectId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
deleteObject.onTriggered: {
|
deleteObject.onTriggered:
|
||||||
if(objectContextMenu.objectId != 0) {
|
{
|
||||||
|
if(objectContextMenu.objectId != 0)
|
||||||
|
{
|
||||||
Printer.deleteObject(objectContextMenu.objectId);
|
Printer.deleteObject(objectContextMenu.objectId);
|
||||||
objectContextMenu.objectId = 0;
|
objectContextMenu.objectId = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
multiplyObject.onTriggered: {
|
multiplyObject.onTriggered:
|
||||||
if(objectContextMenu.objectId != 0) {
|
{
|
||||||
|
if(objectContextMenu.objectId != 0)
|
||||||
|
{
|
||||||
Printer.multiplyObject(objectContextMenu.objectId, 1);
|
Printer.multiplyObject(objectContextMenu.objectId, 1);
|
||||||
objectContextMenu.objectId = 0;
|
objectContextMenu.objectId = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
centerObject.onTriggered: {
|
centerObject.onTriggered:
|
||||||
if(objectContextMenu.objectId != 0) {
|
{
|
||||||
|
if(objectContextMenu.objectId != 0)
|
||||||
|
{
|
||||||
Printer.centerObject(objectContextMenu.objectId);
|
Printer.centerObject(objectContextMenu.objectId);
|
||||||
objectContextMenu.objectId = 0;
|
objectContextMenu.objectId = 0;
|
||||||
}
|
}
|
||||||
@ -418,94 +545,117 @@ UM.MainWindow {
|
|||||||
|
|
||||||
preferences.onTriggered: preferences.visible = true;
|
preferences.onTriggered: preferences.visible = true;
|
||||||
configureMachines.onTriggered: { preferences.visible = true; preferences.setPage(2); }
|
configureMachines.onTriggered: { preferences.visible = true; preferences.setPage(2); }
|
||||||
|
manageProfiles.onTriggered: { preferences.visible = true; preferences.setPage(4); }
|
||||||
|
|
||||||
documentation.onTriggered: CuraActions.openDocumentation();
|
documentation.onTriggered: CuraActions.openDocumentation();
|
||||||
reportBug.onTriggered: CuraActions.openBugReportPage();
|
reportBug.onTriggered: CuraActions.openBugReportPage();
|
||||||
showEngineLog.onTriggered: engineLog.visible = true;
|
showEngineLog.onTriggered: engineLog.visible = true;
|
||||||
about.onTriggered: aboutDialog.visible = true;
|
about.onTriggered: aboutDialog.visible = true;
|
||||||
|
toggleFullScreen.onTriggered: base.toggleFullscreen()
|
||||||
}
|
}
|
||||||
|
|
||||||
Menu {
|
Menu
|
||||||
|
{
|
||||||
id: objectContextMenu;
|
id: objectContextMenu;
|
||||||
|
|
||||||
property variant objectId: -1;
|
property variant objectId: -1;
|
||||||
MenuItem { action: actions.centerObject; }
|
MenuItem { action: actions.centerObject; }
|
||||||
MenuItem { action: actions.deleteObject; }
|
MenuItem { action: actions.deleteObject; }
|
||||||
MenuItem { action: actions.multiplyObject; }
|
MenuItem { action: actions.multiplyObject; }
|
||||||
MenuItem { action: actions.splitObject; }
|
|
||||||
|
|
||||||
MenuSeparator { }
|
MenuSeparator { }
|
||||||
MenuItem { action: actions.deleteAll; }
|
MenuItem { action: actions.deleteAll; }
|
||||||
MenuItem { action: actions.reloadAll; }
|
MenuItem { action: actions.reloadAll; }
|
||||||
MenuItem { action: actions.resetAllTranslation; }
|
MenuItem { action: actions.resetAllTranslation; }
|
||||||
MenuItem { action: actions.resetAll; }
|
MenuItem { action: actions.resetAll; }
|
||||||
MenuItem { action: actions.groupObjects;}
|
MenuItem { action: actions.groupObjects;}
|
||||||
MenuItem { action: actions.unGroupObjects;}
|
|
||||||
MenuItem { action: actions.mergeObjects;}
|
MenuItem { action: actions.mergeObjects;}
|
||||||
|
MenuItem { action: actions.unGroupObjects;}
|
||||||
}
|
}
|
||||||
|
|
||||||
Menu {
|
Menu
|
||||||
|
{
|
||||||
id: contextMenu;
|
id: contextMenu;
|
||||||
MenuItem { action: actions.deleteAll; }
|
MenuItem { action: actions.deleteAll; }
|
||||||
MenuItem { action: actions.reloadAll; }
|
MenuItem { action: actions.reloadAll; }
|
||||||
MenuItem { action: actions.resetAllTranslation; }
|
MenuItem { action: actions.resetAllTranslation; }
|
||||||
MenuItem { action: actions.resetAll; }
|
MenuItem { action: actions.resetAll; }
|
||||||
MenuItem { action: actions.groupObjects;}
|
MenuItem { action: actions.groupObjects;}
|
||||||
MenuItem { action: actions.unGroupObjects;}
|
|
||||||
MenuItem { action: actions.mergeObjects;}
|
MenuItem { action: actions.mergeObjects;}
|
||||||
|
MenuItem { action: actions.unGroupObjects;}
|
||||||
}
|
}
|
||||||
|
|
||||||
Connections {
|
Connections
|
||||||
|
{
|
||||||
target: UM.Controller
|
target: UM.Controller
|
||||||
onContextMenuRequested: {
|
onContextMenuRequested:
|
||||||
if(objectId == 0) {
|
{
|
||||||
|
if(objectId == 0)
|
||||||
|
{
|
||||||
contextMenu.popup();
|
contextMenu.popup();
|
||||||
} else {
|
} else
|
||||||
|
{
|
||||||
objectContextMenu.objectId = objectId;
|
objectContextMenu.objectId = objectId;
|
||||||
objectContextMenu.popup();
|
objectContextMenu.popup();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FileDialog {
|
FileDialog
|
||||||
|
{
|
||||||
id: openDialog;
|
id: openDialog;
|
||||||
|
|
||||||
//: File open dialog title
|
//: File open dialog title
|
||||||
title: qsTr("Open File")
|
title: catalog.i18nc("@title:window","Open File")
|
||||||
modality: UM.Application.platform == "linux" ? Qt.NonModal : Qt.WindowModal;
|
modality: UM.Application.platform == "linux" ? Qt.NonModal : Qt.WindowModal;
|
||||||
//TODO: Support multiple file selection, workaround bug in KDE file dialog
|
//TODO: Support multiple file selection, workaround bug in KDE file dialog
|
||||||
//selectMultiple: true
|
//selectMultiple: true
|
||||||
|
|
||||||
|
signal hasMesh(string name)
|
||||||
|
|
||||||
|
function sendMeshName(path){
|
||||||
|
var fileName = path.slice(path.lastIndexOf("/") + 1)
|
||||||
|
var fileBase = fileName.slice(0, fileName.lastIndexOf("."))
|
||||||
|
openDialog.hasMesh(fileBase)
|
||||||
|
}
|
||||||
nameFilters: UM.MeshFileHandler.supportedReadFileTypes;
|
nameFilters: UM.MeshFileHandler.supportedReadFileTypes;
|
||||||
|
|
||||||
onAccepted:
|
onAccepted:
|
||||||
{
|
{
|
||||||
UM.MeshFileHandler.readLocalFile(fileUrl)
|
UM.MeshFileHandler.readLocalFile(fileUrl)
|
||||||
Printer.setPlatformActivity(true)
|
openDialog.sendMeshName(fileUrl.toString())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
EngineLog {
|
EngineLog
|
||||||
|
{
|
||||||
id: engineLog;
|
id: engineLog;
|
||||||
}
|
}
|
||||||
|
|
||||||
AddMachineWizard {
|
AddMachineWizard
|
||||||
|
{
|
||||||
id: addMachineWizard
|
id: addMachineWizard
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
AboutDialog {
|
AboutDialog
|
||||||
|
{
|
||||||
id: aboutDialog
|
id: aboutDialog
|
||||||
}
|
}
|
||||||
|
|
||||||
Connections {
|
Connections
|
||||||
|
{
|
||||||
target: Printer
|
target: Printer
|
||||||
onRequestAddPrinter: {
|
onRequestAddPrinter:
|
||||||
|
{
|
||||||
addMachineWizard.visible = true
|
addMachineWizard.visible = true
|
||||||
addMachineWizard.printer = false
|
addMachineWizard.firstRun = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Component.onCompleted: UM.Theme.load(UM.Resources.getPath(UM.Resources.ThemesLocation, "cura"))
|
Component.onCompleted:
|
||||||
|
{
|
||||||
|
UM.Theme.load(UM.Resources.getPath(UM.Resources.Themes, "cura"))
|
||||||
|
base.visible = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,40 +5,48 @@ import QtQuick 2.2
|
|||||||
import QtQuick.Controls 1.1
|
import QtQuick.Controls 1.1
|
||||||
import QtQuick.Layouts 1.1
|
import QtQuick.Layouts 1.1
|
||||||
|
|
||||||
import UM 1.0 as UM
|
import UM 1.1 as UM
|
||||||
|
|
||||||
UM.Dialog {
|
UM.Dialog
|
||||||
|
{
|
||||||
id: dialog;
|
id: dialog;
|
||||||
|
|
||||||
//: Engine Log dialog title
|
//: Engine Log dialog title
|
||||||
title: qsTr("Engine Log");
|
title: catalog.i18nc("@title:window","Engine Log");
|
||||||
|
|
||||||
modality: Qt.NonModal;
|
modality: Qt.NonModal;
|
||||||
|
|
||||||
TextArea {
|
TextArea
|
||||||
|
{
|
||||||
id: textArea
|
id: textArea
|
||||||
anchors.fill: parent;
|
anchors.fill: parent;
|
||||||
|
|
||||||
Timer {
|
Timer
|
||||||
|
{
|
||||||
id: updateTimer;
|
id: updateTimer;
|
||||||
interval: 1000;
|
interval: 1000;
|
||||||
running: false;
|
running: false;
|
||||||
repeat: true;
|
repeat: true;
|
||||||
onTriggered: textArea.text = Printer.getEngineLog();
|
onTriggered: textArea.text = Printer.getEngineLog();
|
||||||
}
|
}
|
||||||
|
UM.I18nCatalog{id: catalog; name:"cura"}
|
||||||
}
|
}
|
||||||
|
|
||||||
rightButtons: Button {
|
rightButtons: Button
|
||||||
|
{
|
||||||
//: Close engine log button
|
//: Close engine log button
|
||||||
text: qsTr("Close");
|
text: catalog.i18nc("@action:button","Close");
|
||||||
onClicked: dialog.visible = false;
|
onClicked: dialog.visible = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
onVisibleChanged: {
|
onVisibleChanged:
|
||||||
if(visible) {
|
{
|
||||||
|
if(visible)
|
||||||
|
{
|
||||||
textArea.text = Printer.getEngineLog();
|
textArea.text = Printer.getEngineLog();
|
||||||
updateTimer.start();
|
updateTimer.start();
|
||||||
} else {
|
} else
|
||||||
|
{
|
||||||
updateTimer.stop();
|
updateTimer.stop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
202
resources/qml/GeneralPage.qml
Normal file
@ -0,0 +1,202 @@
|
|||||||
|
// Copyright (c) 2015 Ultimaker B.V.
|
||||||
|
// Uranium is released under the terms of the AGPLv3 or higher.
|
||||||
|
|
||||||
|
import QtQuick 2.1
|
||||||
|
import QtQuick.Controls 1.1
|
||||||
|
import QtQuick.Layouts 1.1
|
||||||
|
import QtQuick.Controls.Styles 1.1
|
||||||
|
|
||||||
|
import UM 1.1 as UM
|
||||||
|
|
||||||
|
UM.PreferencesPage
|
||||||
|
{
|
||||||
|
//: General configuration page title
|
||||||
|
title: catalog.i18nc("@title:tab","General");
|
||||||
|
|
||||||
|
function reset()
|
||||||
|
{
|
||||||
|
UM.Preferences.resetPreference("general/language")
|
||||||
|
UM.Preferences.resetPreference("physics/automatic_push_free")
|
||||||
|
UM.Preferences.resetPreference("mesh/scale_to_fit")
|
||||||
|
UM.Preferences.resetPreference("info/send_slice_info")
|
||||||
|
pushFreeCheckbox.checked = boolCheck(UM.Preferences.getValue("physics/automatic_push_free"))
|
||||||
|
sendDataCheckbox.checked = boolCheck(UM.Preferences.getValue("info/send_slice_info"))
|
||||||
|
scaleToFitCheckbox.checked = boolCheck(UM.Preferences.getValue("mesh/scale_to_fit"))
|
||||||
|
languageComboBox.currentIndex = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
GridLayout
|
||||||
|
{
|
||||||
|
columns: 2;
|
||||||
|
//: Language selection label
|
||||||
|
UM.I18nCatalog{id: catalog; name:"cura"}
|
||||||
|
Label
|
||||||
|
{
|
||||||
|
id: languageLabel
|
||||||
|
text: catalog.i18nc("@label","Language")
|
||||||
|
}
|
||||||
|
|
||||||
|
ComboBox
|
||||||
|
{
|
||||||
|
id: languageComboBox
|
||||||
|
model: ListModel
|
||||||
|
{
|
||||||
|
id: languageList
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
append({ text: catalog.i18nc("@item:inlistbox", "Bulgarian"), code: "bg" })
|
||||||
|
append({ text: catalog.i18nc("@item:inlistbox", "Czech"), code: "cs" })
|
||||||
|
append({ text: catalog.i18nc("@item:inlistbox", "English"), code: "en" })
|
||||||
|
append({ text: catalog.i18nc("@item:inlistbox", "Finnish"), code: "fi" })
|
||||||
|
append({ text: catalog.i18nc("@item:inlistbox", "French"), code: "fr" })
|
||||||
|
append({ text: catalog.i18nc("@item:inlistbox", "German"), code: "de" })
|
||||||
|
append({ text: catalog.i18nc("@item:inlistbox", "Italian"), code: "it" })
|
||||||
|
append({ text: catalog.i18nc("@item:inlistbox", "Polish"), code: "pl" })
|
||||||
|
append({ text: catalog.i18nc("@item:inlistbox", "Russian"), code: "ru" })
|
||||||
|
append({ text: catalog.i18nc("@item:inlistbox", "Spanish"), code: "es" })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
currentIndex:
|
||||||
|
{
|
||||||
|
var code = UM.Preferences.getValue("general/language");
|
||||||
|
for(var i = 0; i < languageList.count; ++i)
|
||||||
|
{
|
||||||
|
if(model.get(i).code == code)
|
||||||
|
{
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onActivated: UM.Preferences.setValue("general/language", model.get(index).code)
|
||||||
|
|
||||||
|
anchors.left: languageLabel.right
|
||||||
|
anchors.top: languageLabel.top
|
||||||
|
anchors.leftMargin: 20
|
||||||
|
|
||||||
|
Component.onCompleted:
|
||||||
|
{
|
||||||
|
// Because ListModel is stupid and does not allow using qsTr() for values.
|
||||||
|
for(var i = 0; i < languageList.count; ++i)
|
||||||
|
{
|
||||||
|
languageList.setProperty(i, "text", catalog.i18n(languageList.get(i).text));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Glorious hack time. ComboBox does not update the text properly after changing the
|
||||||
|
// model. So change the indices around to force it to update.
|
||||||
|
currentIndex += 1;
|
||||||
|
currentIndex -= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Label
|
||||||
|
{
|
||||||
|
id: languageCaption;
|
||||||
|
Layout.columnSpan: 2
|
||||||
|
|
||||||
|
//: Language change warning
|
||||||
|
text: catalog.i18nc("@label", "You will need to restart the application for language changes to have effect.")
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
|
font.italic: true
|
||||||
|
}
|
||||||
|
|
||||||
|
CheckBox
|
||||||
|
{
|
||||||
|
id: pushFreeCheckbox
|
||||||
|
checked: boolCheck(UM.Preferences.getValue("physics/automatic_push_free"))
|
||||||
|
onCheckedChanged: UM.Preferences.setValue("physics/automatic_push_free", checked)
|
||||||
|
}
|
||||||
|
Button
|
||||||
|
{
|
||||||
|
id: pushFreeText //is a button so the user doesn't have te click inconvenientley precise to enable or disable the checkbox
|
||||||
|
|
||||||
|
//: Display Overhang preference checkbox
|
||||||
|
text: catalog.i18nc("@option:check", "Ensure objects are kept apart");
|
||||||
|
onClicked: pushFreeCheckbox.checked = !pushFreeCheckbox.checked
|
||||||
|
|
||||||
|
//: Display Overhang preference tooltip
|
||||||
|
tooltip: catalog.i18nc("@info:tooltip", "Should objects on the platform be moved so that they no longer intersect.")
|
||||||
|
|
||||||
|
style: ButtonStyle
|
||||||
|
{
|
||||||
|
background: Rectangle
|
||||||
|
{
|
||||||
|
border.width: 0
|
||||||
|
color: "transparent"
|
||||||
|
}
|
||||||
|
label: Text
|
||||||
|
{
|
||||||
|
renderType: Text.NativeRendering
|
||||||
|
horizontalAlignment: Text.AlignLeft
|
||||||
|
text: control.text
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CheckBox
|
||||||
|
{
|
||||||
|
id: sendDataCheckbox
|
||||||
|
checked: boolCheck(UM.Preferences.getValue("info/send_slice_info"))
|
||||||
|
onCheckedChanged: UM.Preferences.setValue("info/send_slice_info", checked)
|
||||||
|
}
|
||||||
|
Button
|
||||||
|
{
|
||||||
|
id: sendDataText //is a button so the user doesn't have te click inconvenientley precise to enable or disable the checkbox
|
||||||
|
|
||||||
|
//: Display Overhang preference checkbox
|
||||||
|
text: catalog.i18nc("@option:check","Send (Anonymous) Print Information");
|
||||||
|
onClicked: sendDataCheckbox.checked = !sendDataCheckbox.checked
|
||||||
|
|
||||||
|
//: Display Overhang preference tooltip
|
||||||
|
tooltip: catalog.i18nc("@info:tooltip","Should anonymous data about your print be sent to Ultimaker? Note, no models, IP addresses or other personally identifiable information is sent or stored.")
|
||||||
|
|
||||||
|
style: ButtonStyle
|
||||||
|
{
|
||||||
|
background: Rectangle
|
||||||
|
{
|
||||||
|
border.width: 0
|
||||||
|
color: "transparent"
|
||||||
|
}
|
||||||
|
label: Text
|
||||||
|
{
|
||||||
|
renderType: Text.NativeRendering
|
||||||
|
horizontalAlignment: Text.AlignLeft
|
||||||
|
text: control.text
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CheckBox
|
||||||
|
{
|
||||||
|
id: scaleToFitCheckbox
|
||||||
|
checked: boolCheck(UM.Preferences.getValue("mesh/scale_to_fit"))
|
||||||
|
onCheckedChanged: UM.Preferences.setValue("mesh/scale_to_fit", checked)
|
||||||
|
}
|
||||||
|
Button
|
||||||
|
{
|
||||||
|
id: scaleToFitText //is a button so the user doesn't have te click inconvenientley precise to enable or disable the checkbox
|
||||||
|
|
||||||
|
//: Display Overhang preference checkbox
|
||||||
|
text: catalog.i18nc("@option:check","Scale Too Large Files");
|
||||||
|
onClicked: scaleToFitCheckbox.checked = !scaleToFitCheckbox.checked
|
||||||
|
|
||||||
|
//: Display Overhang preference tooltip
|
||||||
|
tooltip: catalog.i18nc("@info:tooltip","Should opened files be scaled to the build volume when they are too large?")
|
||||||
|
|
||||||
|
style: ButtonStyle
|
||||||
|
{
|
||||||
|
background: Rectangle
|
||||||
|
{
|
||||||
|
border.width: 0
|
||||||
|
color: "transparent"
|
||||||
|
}
|
||||||
|
label: Text
|
||||||
|
{
|
||||||
|
renderType: Text.NativeRendering
|
||||||
|
horizontalAlignment: Text.AlignLeft
|
||||||
|
text: control.text
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Item { Layout.fillHeight: true; Layout.columnSpan: 2 }
|
||||||
|
}
|
||||||
|
}
|
155
resources/qml/ProfileSetup.qml
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
// Copyright (c) 2015 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.1 as UM
|
||||||
|
|
||||||
|
Column{
|
||||||
|
id: base;
|
||||||
|
UM.I18nCatalog { id: catalog; name:"cura"}
|
||||||
|
property int totalHeightProfileSetup: childrenRect.height
|
||||||
|
property Action manageProfilesAction
|
||||||
|
spacing: 0
|
||||||
|
|
||||||
|
Rectangle{
|
||||||
|
id: variantItem;
|
||||||
|
height: UM.Theme.sizes.sidebar_setup.height
|
||||||
|
width: base.width
|
||||||
|
visible: UM.MachineManager.hasVariants;
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: variantRow
|
||||||
|
width: base.width
|
||||||
|
height: parent.heigth
|
||||||
|
|
||||||
|
Label{
|
||||||
|
id: variantLabel
|
||||||
|
text: catalog.i18nc("@label","Variant:");
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.leftMargin: UM.Theme.sizes.default_margin.width;
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
width: parent.width/100*45
|
||||||
|
font: UM.Theme.fonts.default;
|
||||||
|
}
|
||||||
|
|
||||||
|
ToolButton {
|
||||||
|
id: variantSelection
|
||||||
|
text: UM.MachineManager.activeMachineVariant
|
||||||
|
width: parent.width/100*55
|
||||||
|
height: UM.Theme.sizes.setting_control.height
|
||||||
|
tooltip: UM.MachineManager.activeMachineInstance;
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.rightMargin: UM.Theme.sizes.default_margin.width
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
style: UM.Theme.styles.sidebar_header_button
|
||||||
|
|
||||||
|
menu: Menu
|
||||||
|
{
|
||||||
|
id: variantsSelectionMenu
|
||||||
|
Instantiator
|
||||||
|
{
|
||||||
|
model: UM.MachineVariantsModel { }
|
||||||
|
MenuItem
|
||||||
|
{
|
||||||
|
text: model.name;
|
||||||
|
checkable: true;
|
||||||
|
checked: model.active;
|
||||||
|
exclusiveGroup: variantSelectionMenuGroup;
|
||||||
|
onTriggered: UM.MachineManager.setActiveMachineVariant(model.getItem(index).name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ExclusiveGroup { id: variantSelectionMenuGroup; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle{
|
||||||
|
id: globalProfileRow;
|
||||||
|
height: UM.Theme.sizes.sidebar_setup.height
|
||||||
|
width: base.width
|
||||||
|
|
||||||
|
Label{
|
||||||
|
id: globalProfileLabel
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.leftMargin: UM.Theme.sizes.default_margin.width;
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
text: catalog.i18nc("@label","Global Profile:");
|
||||||
|
width: parent.width/100*45
|
||||||
|
font: UM.Theme.fonts.default;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ToolButton {
|
||||||
|
id: globalProfileSelection
|
||||||
|
text: UM.MachineManager.activeProfile
|
||||||
|
width: parent.width/100*55
|
||||||
|
height: UM.Theme.sizes.setting_control.height
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.rightMargin: UM.Theme.sizes.default_margin.width
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
tooltip: UM.MachineManager.activeProfile
|
||||||
|
style: UM.Theme.styles.sidebar_header_button
|
||||||
|
|
||||||
|
menu: Menu
|
||||||
|
{
|
||||||
|
id: profileSelectionMenu
|
||||||
|
Instantiator
|
||||||
|
{
|
||||||
|
model: UM.ProfilesModel { }
|
||||||
|
MenuItem
|
||||||
|
{
|
||||||
|
text: model.name
|
||||||
|
checkable: true;
|
||||||
|
checked: model.active;
|
||||||
|
exclusiveGroup: profileSelectionMenuGroup;
|
||||||
|
onTriggered: UM.MachineManager.setActiveProfile(model.name)
|
||||||
|
}
|
||||||
|
onObjectAdded: profileSelectionMenu.insertItem(index, object)
|
||||||
|
onObjectRemoved: profileSelectionMenu.removeItem(object)
|
||||||
|
}
|
||||||
|
ExclusiveGroup { id: profileSelectionMenuGroup; }
|
||||||
|
|
||||||
|
MenuSeparator { }
|
||||||
|
MenuItem {
|
||||||
|
action: base.manageProfilesAction;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Button {
|
||||||
|
// id: saveProfileButton
|
||||||
|
// visible: true
|
||||||
|
// anchors.top: parent.top
|
||||||
|
// x: globalProfileSelection.width + 2
|
||||||
|
// width: parent.width/100*25
|
||||||
|
// text: catalog.i18nc("@action:button", "Save");
|
||||||
|
// height: parent.height
|
||||||
|
//
|
||||||
|
// style: ButtonStyle {
|
||||||
|
// background: Rectangle {
|
||||||
|
// color: control.hovered ? UM.Theme.colors.load_save_button_hover : UM.Theme.colors.load_save_button
|
||||||
|
// Behavior on color { ColorAnimation { duration: 50; } }
|
||||||
|
// width: actualLabel.width + UM.Theme.sizes.default_margin.width
|
||||||
|
// Label {
|
||||||
|
// id: actualLabel
|
||||||
|
// anchors.centerIn: parent
|
||||||
|
// color: UM.Theme.colors.load_save_button_text
|
||||||
|
// font: UM.Theme.fonts.default
|
||||||
|
// text: control.text;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// label: Item { }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Rectangle{
|
||||||
|
width: base.width
|
||||||
|
height: UM.Theme.sizes.default_margin.width/2
|
||||||
|
}
|
||||||
|
}
|
@ -14,171 +14,249 @@ Rectangle {
|
|||||||
property real progress: UM.Backend.progress;
|
property real progress: UM.Backend.progress;
|
||||||
property bool activity: Printer.getPlatformActivity;
|
property bool activity: Printer.getPlatformActivity;
|
||||||
Behavior on progress { NumberAnimation { duration: 250; } }
|
Behavior on progress { NumberAnimation { duration: 250; } }
|
||||||
|
property int totalHeight: childrenRect.height
|
||||||
|
property string fileBaseName
|
||||||
|
property variant activeMachineInstance: UM.MachineManager.activeMachineInstance
|
||||||
|
|
||||||
|
onActiveMachineInstanceChanged:
|
||||||
|
{
|
||||||
|
base.createFileName()
|
||||||
|
}
|
||||||
|
|
||||||
|
UM.I18nCatalog { id: catalog; name:"cura"}
|
||||||
|
|
||||||
property variant printDuration: PrintInformation.currentPrintTime;
|
property variant printDuration: PrintInformation.currentPrintTime;
|
||||||
property real printMaterialAmount: PrintInformation.materialAmount;
|
property real printMaterialAmount: PrintInformation.materialAmount;
|
||||||
|
|
||||||
|
function createFileName(){
|
||||||
|
var splitMachineName = UM.MachineManager.activeMachineInstance.split(" ")
|
||||||
|
var abbrMachine = ''
|
||||||
|
for (var i = 0; i < splitMachineName.length; i++){
|
||||||
|
if (splitMachineName[i].search(/ultimaker/i) != -1){
|
||||||
|
abbrMachine += 'UM'
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
if (splitMachineName[i].charAt(0).search(/[0-9]/g) == -1)
|
||||||
|
abbrMachine += splitMachineName[i].charAt(0)
|
||||||
|
}
|
||||||
|
var regExpAdditives = /[0-9\+]/g;
|
||||||
|
var resultAdditives = splitMachineName[i].match(regExpAdditives);
|
||||||
|
if (resultAdditives != null){
|
||||||
|
for (var j = 0; j < resultAdditives.length; j++){
|
||||||
|
abbrMachine += resultAdditives[j]
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printJobTextfield.text = abbrMachine + '_' + base.fileBaseName
|
||||||
|
}
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: openDialog
|
||||||
|
onHasMesh: {
|
||||||
|
base.fileBaseName = name
|
||||||
|
base.createFileName()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Rectangle{
|
Rectangle{
|
||||||
id: background
|
id: printJobRow
|
||||||
implicitWidth: base.width;
|
implicitWidth: base.width;
|
||||||
implicitHeight: parent.height;
|
implicitHeight: UM.Theme.sizes.sidebar_header.height
|
||||||
color: UM.Theme.colors.save_button_background;
|
|
||||||
border.width: UM.Theme.sizes.save_button_border.width
|
|
||||||
border.color: UM.Theme.colors.save_button_border
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
id: infoBox
|
|
||||||
width: parent.width - UM.Theme.sizes.default_margin.width * 2;
|
|
||||||
height: UM.Theme.sizes.save_button_slicing_bar.height
|
|
||||||
|
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
anchors.topMargin: UM.Theme.sizes.default_margin.height;
|
color: UM.Theme.colors.sidebar_header_bar
|
||||||
|
Label{
|
||||||
|
id: printJobTextfieldLabel
|
||||||
|
text: catalog.i18nc("@label:textbox", "Printjob Name");
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.leftMargin: UM.Theme.sizes.default_margin.width;
|
anchors.leftMargin: UM.Theme.sizes.default_margin.width;
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
font: UM.Theme.fonts.default;
|
||||||
|
color: UM.Theme.colors.text_white
|
||||||
|
}
|
||||||
|
TextField {
|
||||||
|
id: printJobTextfield
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.rightMargin: UM.Theme.sizes.default_margin.width;
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
width: parent.width/100*55
|
||||||
|
height: UM.Theme.sizes.sidebar_inputFields.height
|
||||||
|
property int unremovableSpacing: 5
|
||||||
|
text: ''
|
||||||
|
onEditingFinished: {
|
||||||
|
if (printJobTextfield.text != ''){
|
||||||
|
printJobTextfield.focus = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
validator: RegExpValidator {
|
||||||
|
regExp: /^[^\\ \/ \.]*$/
|
||||||
|
}
|
||||||
|
style: TextFieldStyle{
|
||||||
|
textColor: UM.Theme.colors.setting_control_text;
|
||||||
|
font: UM.Theme.fonts.default;
|
||||||
|
background: Rectangle {
|
||||||
|
radius: 0
|
||||||
|
implicitWidth: parent.width
|
||||||
|
implicitHeight: parent.height
|
||||||
|
border.width: 1;
|
||||||
|
border.color: UM.Theme.colors.slider_groove_border;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
border.width: UM.Theme.sizes.save_button_border.width
|
Rectangle {
|
||||||
border.color: UM.Theme.colors.save_button_border
|
id: specsRow
|
||||||
color: UM.Theme.colors.save_button_estimated_text_background;
|
implicitWidth: base.width
|
||||||
Label {
|
implicitHeight: UM.Theme.sizes.sidebar_specs_bar.height
|
||||||
id: label;
|
anchors.top: printJobRow.bottom
|
||||||
|
Item{
|
||||||
|
id: time
|
||||||
|
width: childrenRect.width;
|
||||||
|
height: parent.height
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.leftMargin: UM.Theme.sizes.default_margin.width
|
||||||
|
anchors.top: parent.top
|
||||||
|
visible: base.printMaterialAmount > 0 ? true : false
|
||||||
|
UM.RecolorImage {
|
||||||
|
id: timeIcon
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.leftMargin: UM.Theme.sizes.save_button_text_margin.width;
|
width: UM.Theme.sizes.save_button_specs_icons.width
|
||||||
visible: base.progress >= 0 && base.progress < 0.99 ? false : true
|
height: UM.Theme.sizes.save_button_specs_icons.height
|
||||||
color: UM.Theme.colors.save_button_estimated_text;
|
sourceSize.width: width
|
||||||
font: UM.Theme.fonts.small;
|
sourceSize.height: width
|
||||||
text: {
|
color: UM.Theme.colors.text_hover
|
||||||
if(base.activity == false) {
|
source: UM.Theme.icons.print_time;
|
||||||
//: Save button label
|
|
||||||
return qsTr("Please load a 3D model");
|
|
||||||
} else if (base.progress < 0.99) {
|
|
||||||
//: Save button label
|
|
||||||
return qsTr("Calculating Print-time");
|
|
||||||
} else if (base.printDuration.days > 0 || base.progress == null){
|
|
||||||
return qsTr("");
|
|
||||||
}
|
}
|
||||||
else if (base.progress > 0.99){
|
Label{
|
||||||
//: Save button label
|
id: timeSpec
|
||||||
return qsTr("Estimated Print-time");
|
|
||||||
}
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Label {
|
|
||||||
id: printDurationLabel
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
anchors.left: label.right;
|
anchors.left: timeIcon.right
|
||||||
anchors.leftMargin: UM.Theme.sizes.save_button_text_margin.width;
|
anchors.leftMargin: UM.Theme.sizes.default_margin.width/2
|
||||||
color: UM.Theme.colors.save_button_printtime_text;
|
font: UM.Theme.fonts.default
|
||||||
font: UM.Theme.fonts.small;
|
color: UM.Theme.colors.text
|
||||||
visible: base.activity == false || base.progress < 0.99 ? false : true
|
text: (!base.printDuration || !base.printDuration.valid) ? "" : base.printDuration.getDisplayString(UM.DurationFormat.Short)
|
||||||
text: (!base.printDuration || !base.printDuration.valid) ? "" : base.printDuration.getDisplayString(UM.DurationFormat.Long);
|
|
||||||
}
|
}
|
||||||
Label {
|
}
|
||||||
id: printMaterialLabel
|
Item{
|
||||||
|
width: parent.width / 100 * 55
|
||||||
|
height: parent.height
|
||||||
|
anchors.left: time.right
|
||||||
|
anchors.leftMargin: UM.Theme.sizes.default_margin.width;
|
||||||
|
anchors.top: parent.top
|
||||||
|
visible: base.printMaterialAmount > 0 ? true : false
|
||||||
|
UM.RecolorImage {
|
||||||
|
id: lengthIcon
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
anchors.left: printDurationLabel.right;
|
anchors.left: parent.left
|
||||||
anchors.leftMargin: UM.Theme.sizes.save_button_text_margin.width;
|
width: UM.Theme.sizes.save_button_specs_icons.width
|
||||||
color: base.printDuration.days > 0 ? UM.Theme.colors.save_button_estimated_text : UM.Theme.colors.save_button_printtime_text;
|
height: UM.Theme.sizes.save_button_specs_icons.height
|
||||||
font: UM.Theme.fonts.small;
|
sourceSize.width: width
|
||||||
property bool mediumLengthDuration: base.printDuration.hours > 9 && base.printMaterialAmount > 9.99 && base.printDuration.days == 0
|
sourceSize.height: width
|
||||||
width: mediumLengthDuration ? 50 : undefined
|
color: UM.Theme.colors.text_hover
|
||||||
elide: mediumLengthDuration ? Text.ElideRight : Text.ElideNone
|
source: UM.Theme.icons.category_material;
|
||||||
visible: base.activity == false || base.progress < 0.99 ? false : true
|
}
|
||||||
//: Print material amount save button label
|
Label{
|
||||||
text: base.printMaterialAmount < 0 ? "" : qsTr("%1m of Material").arg(base.printMaterialAmount);
|
id: lengthSpec
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
anchors.left: lengthIcon.right
|
||||||
|
anchors.leftMargin: UM.Theme.sizes.default_margin.width/2
|
||||||
|
font: UM.Theme.fonts.default
|
||||||
|
color: UM.Theme.colors.text
|
||||||
|
text: base.printMaterialAmount <= 0 ? "" : catalog.i18nc("@label %1 is length of filament","%1 m").arg(base.printMaterialAmount)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Rectangle {
|
|
||||||
id: infoBoxOverlay
|
|
||||||
anchors {
|
|
||||||
left: infoBox.left;
|
|
||||||
top: infoBox.top;
|
|
||||||
bottom: infoBox.bottom;
|
|
||||||
}
|
|
||||||
width: Math.max(infoBox.width * base.progress);
|
|
||||||
color: UM.Theme.colors.save_button_active
|
|
||||||
visible: progress > 0.99 ? false : true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Rectangle{
|
||||||
|
id: saveRow
|
||||||
|
width: base.width
|
||||||
|
height: saveToButton.height + (UM.Theme.sizes.default_margin.height / 2) // height + bottomMargin
|
||||||
|
anchors.top: specsRow.bottom
|
||||||
|
anchors.left: parent.left
|
||||||
|
|
||||||
Button {
|
Button {
|
||||||
id: saveToButton
|
id: saveToButton
|
||||||
anchors.top: infoBox.bottom
|
property int resizedWidth
|
||||||
anchors.topMargin: UM.Theme.sizes.save_button_text_margin.height;
|
x: base.width - saveToButton.resizedWidth - UM.Theme.sizes.default_margin.width - UM.Theme.sizes.save_button_save_to_button.height
|
||||||
anchors.left: parent.left
|
tooltip: UM.OutputDeviceManager.activeDeviceDescription;
|
||||||
anchors.leftMargin: UM.Theme.sizes.default_margin.width;
|
enabled: base.progress > 0.99 && base.activity == true
|
||||||
tooltip: devicesModel.activeDevice.description;
|
|
||||||
enabled: progress > 0.99 && base.activity == true
|
|
||||||
|
|
||||||
width: infoBox.width/6*4.5
|
|
||||||
height: UM.Theme.sizes.save_button_save_to_button.height
|
height: UM.Theme.sizes.save_button_save_to_button.height
|
||||||
|
width: 150
|
||||||
text: devicesModel.activeDevice.short_description;
|
anchors.top:parent.top
|
||||||
|
text: UM.OutputDeviceManager.activeDeviceShortDescription
|
||||||
|
onClicked:
|
||||||
|
{
|
||||||
|
UM.OutputDeviceManager.requestWriteToDevice(UM.OutputDeviceManager.activeDevice)
|
||||||
|
}
|
||||||
|
|
||||||
style: ButtonStyle {
|
style: ButtonStyle {
|
||||||
background: Rectangle {
|
background: Rectangle {
|
||||||
color: !control.enabled ? UM.Theme.colors.save_button_inactive : control.hovered ? UM.Theme.colors.save_button_active_hover : UM.Theme.colors.save_button_active;
|
color: control.hovered ? UM.Theme.colors.load_save_button_hover : UM.Theme.colors.load_save_button
|
||||||
|
Behavior on color { ColorAnimation { duration: 50; } }
|
||||||
|
width: {
|
||||||
|
var w = 0;
|
||||||
|
if (base.width*0.55 > actualLabel.width + (UM.Theme.sizes.default_margin.width * 2)){
|
||||||
|
saveToButton.resizedWidth = base.width*0.55
|
||||||
|
w = base.width*0.55
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
saveToButton.resizedWidth = actualLabel.width + (UM.Theme.sizes.default_margin.width * 2)
|
||||||
|
w = actualLabel.width + (UM.Theme.sizes.default_margin.width * 2)
|
||||||
|
}
|
||||||
|
|
||||||
|
if(w < base.width * 0.55) {
|
||||||
|
w = base.width * 0.55;
|
||||||
|
}
|
||||||
|
|
||||||
|
return w;
|
||||||
|
}
|
||||||
Label {
|
Label {
|
||||||
|
id: actualLabel
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
color: UM.Theme.colors.save_button_safe_to_text;
|
color: UM.Theme.colors.load_save_button_text
|
||||||
font: UM.Theme.fonts.sidebar_save_to;
|
font: UM.Theme.fonts.default
|
||||||
text: control.text;
|
text: control.text;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
label: Item { }
|
label: Item { }
|
||||||
}
|
}
|
||||||
onClicked: devicesModel.requestWriteToDevice(devicesModel.activeDevice.id)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Button {
|
Button {
|
||||||
id: deviceSelectionMenu;
|
id: deviceSelectionMenu
|
||||||
anchors.top: infoBox.bottom
|
tooltip: catalog.i18nc("@info:tooltip","Select the active output device");
|
||||||
anchors.topMargin: UM.Theme.sizes.save_button_text_margin.height
|
anchors.top:parent.top
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.rightMargin: UM.Theme.sizes.default_margin.width;
|
anchors.rightMargin: UM.Theme.sizes.default_margin.width
|
||||||
|
width: UM.Theme.sizes.save_button_save_to_button.height
|
||||||
tooltip: qsTr("Select the active output device");
|
|
||||||
|
|
||||||
width: infoBox.width/6*1.3 - UM.Theme.sizes.save_button_text_margin.height;
|
|
||||||
height: UM.Theme.sizes.save_button_save_to_button.height
|
height: UM.Theme.sizes.save_button_save_to_button.height
|
||||||
|
//iconSource: UM.Theme.icons[UM.OutputDeviceManager.activeDeviceIconName];
|
||||||
iconSource: UM.Theme.icons[devicesModel.activeDevice.icon_name];
|
|
||||||
|
|
||||||
style: ButtonStyle {
|
style: ButtonStyle {
|
||||||
background: Rectangle {
|
background: Rectangle {
|
||||||
color: UM.Theme.colors.save_button_background;
|
|
||||||
border.width: control.hovered ? UM.Theme.sizes.save_button_border.width : 0
|
|
||||||
border.color: UM.Theme.colors.save_button_border
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
id: deviceSelectionIcon
|
id: deviceSelectionIcon
|
||||||
color: UM.Theme.colors.save_button_background;
|
color: control.hovered ? UM.Theme.colors.load_save_button_hover : UM.Theme.colors.load_save_button
|
||||||
|
Behavior on color { ColorAnimation { duration: 50; } }
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.leftMargin: UM.Theme.sizes.save_button_text_margin.width / 2;
|
anchors.leftMargin: UM.Theme.sizes.save_button_text_margin.width / 2;
|
||||||
anchors.verticalCenter: parent.verticalCenter;
|
width: parent.height
|
||||||
width: parent.height - UM.Theme.sizes.save_button_text_margin.width ;
|
height: parent.height
|
||||||
height: parent.height - UM.Theme.sizes.save_button_text_margin.width;
|
|
||||||
|
|
||||||
UM.RecolorImage {
|
UM.RecolorImage {
|
||||||
anchors.fill: parent;
|
id: lengthIcon
|
||||||
sourceSize.width: width;
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
sourceSize.height: height;
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
color: UM.Theme.colors.save_button_active
|
width: UM.Theme.sizes.standard_arrow.width
|
||||||
source: control.iconSource;
|
height: UM.Theme.sizes.standard_arrow.height
|
||||||
|
sourceSize.width: width
|
||||||
|
sourceSize.height: width
|
||||||
|
color: UM.Theme.colors.load_save_button_text
|
||||||
|
source: UM.Theme.icons.arrow_bottom
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Label {
|
label: Label{ }
|
||||||
id: deviceSelectionArrow
|
|
||||||
anchors.right: parent.right;
|
|
||||||
anchors.rightMargin: UM.Theme.sizes.save_button_text_margin.height
|
|
||||||
anchors.verticalCenter: parent.verticalCenter;
|
|
||||||
text: "▼";
|
|
||||||
font: UM.Theme.fonts.tiny;
|
|
||||||
color: UM.Theme.colors.save_button_active;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
label: Item { }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
menu: Menu {
|
menu: Menu {
|
||||||
@ -188,10 +266,10 @@ Rectangle {
|
|||||||
MenuItem {
|
MenuItem {
|
||||||
text: model.description
|
text: model.description
|
||||||
checkable: true;
|
checkable: true;
|
||||||
checked: model.id == devicesModel.activeDevice.id;
|
checked: model.id == UM.OutputDeviceManager.activeDevice;
|
||||||
exclusiveGroup: devicesMenuGroup;
|
exclusiveGroup: devicesMenuGroup;
|
||||||
onTriggered: {
|
onTriggered: {
|
||||||
devicesModel.setActiveDevice(model.id);
|
UM.OutputDeviceManager.setActiveDevice(model.id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
onObjectAdded: devicesMenu.insertItem(index, object)
|
onObjectAdded: devicesMenu.insertItem(index, object)
|
||||||
@ -200,9 +278,6 @@ Rectangle {
|
|||||||
ExclusiveGroup { id: devicesMenuGroup; }
|
ExclusiveGroup { id: devicesMenuGroup; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
UM.OutputDevicesModel { id: devicesModel; }
|
||||||
|
|
||||||
UM.OutputDevicesModel {
|
|
||||||
id: devicesModel;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,53 +6,56 @@ import QtQuick.Controls 1.1
|
|||||||
import QtQuick.Controls.Styles 1.1
|
import QtQuick.Controls.Styles 1.1
|
||||||
import QtQuick.Layouts 1.1
|
import QtQuick.Layouts 1.1
|
||||||
|
|
||||||
import UM 1.0 as UM
|
import UM 1.1 as UM
|
||||||
|
|
||||||
Rectangle {
|
Rectangle
|
||||||
|
{
|
||||||
id: base;
|
id: base;
|
||||||
|
|
||||||
property Action addMachineAction;
|
property Action addMachineAction;
|
||||||
property Action configureMachinesAction;
|
property Action configureMachinesAction;
|
||||||
|
property Action manageProfilesAction;
|
||||||
|
|
||||||
color: UM.Theme.colors.sidebar;
|
color: UM.Theme.colors.sidebar;
|
||||||
|
UM.I18nCatalog { id: catalog; name:"cura"}
|
||||||
|
|
||||||
function showTooltip(item, position, text) {
|
function showTooltip(item, position, text)
|
||||||
|
{
|
||||||
tooltip.text = text;
|
tooltip.text = text;
|
||||||
position = item.mapToItem(base, position.x, position.y / 2);
|
position = item.mapToItem(base, position.x, position.y / 2);
|
||||||
tooltip.show(position);
|
tooltip.show(position);
|
||||||
}
|
}
|
||||||
|
|
||||||
function hideTooltip() {
|
function hideTooltip()
|
||||||
|
{
|
||||||
tooltip.hide();
|
tooltip.hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
MouseArea {
|
MouseArea
|
||||||
|
{
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
acceptedButtons: Qt.AllButtons;
|
acceptedButtons: Qt.AllButtons;
|
||||||
|
|
||||||
onWheel: {
|
onWheel:
|
||||||
|
{
|
||||||
wheel.accepted = true;
|
wheel.accepted = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ColumnLayout {
|
|
||||||
anchors.fill: parent;
|
|
||||||
anchors.topMargin: UM.Theme.sizes.default_margin.height;
|
|
||||||
|
|
||||||
spacing: UM.Theme.sizes.default_margin.height;
|
|
||||||
|
|
||||||
SidebarHeader {
|
SidebarHeader {
|
||||||
id: header;
|
id: header
|
||||||
|
width: parent.width
|
||||||
Layout.fillWidth: true;
|
height: totalHeightHeader
|
||||||
|
|
||||||
addMachineAction: base.addMachineAction;
|
addMachineAction: base.addMachineAction;
|
||||||
configureMachinesAction: base.configureMachinesAction;
|
configureMachinesAction: base.configureMachinesAction;
|
||||||
modesModel: modesListModel;
|
modesModel: modesListModel;
|
||||||
|
|
||||||
currentModeIndex: {
|
currentModeIndex:
|
||||||
|
{
|
||||||
var index = parseInt(UM.Preferences.getValue("cura/active_mode"))
|
var index = parseInt(UM.Preferences.getValue("cura/active_mode"))
|
||||||
if(index) {
|
if(index)
|
||||||
|
{
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@ -60,13 +63,23 @@ Rectangle {
|
|||||||
onCurrentModeIndexChanged: UM.Preferences.setValue("cura/active_mode", currentModeIndex);
|
onCurrentModeIndexChanged: UM.Preferences.setValue("cura/active_mode", currentModeIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
Loader {
|
ProfileSetup {
|
||||||
|
id: profileItem
|
||||||
|
manageProfilesAction: base.manageProfilesAction
|
||||||
|
anchors.top: header.bottom
|
||||||
|
width: parent.width
|
||||||
|
height: totalHeightProfileSetup
|
||||||
|
}
|
||||||
|
|
||||||
|
Loader
|
||||||
|
{
|
||||||
id: sidebarContents;
|
id: sidebarContents;
|
||||||
|
anchors.bottom: saveButton.top
|
||||||
|
anchors.top: profileItem.bottom
|
||||||
|
anchors.left: base.left
|
||||||
|
anchors.right: base.right
|
||||||
|
|
||||||
Layout.fillWidth: true;
|
source: modesListModel.count > header.currentModeIndex ? modesListModel.get(header.currentModeIndex).file : "";
|
||||||
Layout.fillHeight: true;
|
|
||||||
|
|
||||||
source: modesListModel.get(header.currentModeIndex).file;
|
|
||||||
|
|
||||||
property Item sidebar: base;
|
property Item sidebar: base;
|
||||||
|
|
||||||
@ -87,29 +100,28 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SaveButton {
|
SaveButton
|
||||||
|
{
|
||||||
id: saveButton;
|
id: saveButton;
|
||||||
implicitWidth: base.width
|
implicitWidth: base.width
|
||||||
implicitHeight: UM.Theme.sizes.save_button_text_margin.height * 2 + UM.Theme.sizes.save_button_slicing_bar.height + UM.Theme.sizes.save_button_save_to_button.height + UM.Theme.sizes.default_margin.height
|
implicitHeight: totalHeight
|
||||||
}
|
anchors.bottom: parent.bottom
|
||||||
}
|
}
|
||||||
|
|
||||||
SidebarTooltip {
|
SidebarTooltip
|
||||||
|
{
|
||||||
id: tooltip;
|
id: tooltip;
|
||||||
}
|
}
|
||||||
|
|
||||||
ListModel {
|
ListModel
|
||||||
|
{
|
||||||
id: modesListModel;
|
id: modesListModel;
|
||||||
//: Simple configuration mode option
|
|
||||||
ListElement { text: QT_TR_NOOP("Simple"); file: "SidebarSimple.qml" }
|
|
||||||
//: Advanced configuration mode option
|
|
||||||
ListElement { text: QT_TR_NOOP("Advanced"); file: "SidebarAdvanced.qml" }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted:
|
||||||
for(var i = 0; i < modesListModel.count; ++i)
|
|
||||||
{
|
{
|
||||||
modesListModel.setProperty(i, "text", qsTr(modesListModel.get(i).text));
|
modesListModel.append({ text: catalog.i18nc("@title:tab", "Simple"), file: "SidebarSimple.qml" })
|
||||||
}
|
modesListModel.append({ text: catalog.i18nc("@title:tab", "Advanced"), file: "SidebarAdvanced.qml" })
|
||||||
|
sidebarContents.setSource(modesListModel.get(header.currentModeIndex).file)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|