Merge branch 'master' of github.com:Ultimaker/Cura into feature_extruder_buttons

This commit is contained in:
Jaime van Kessel 2017-04-24 16:39:15 +02:00
commit 33d92f9596
27 changed files with 698 additions and 192 deletions

View File

@ -1,10 +1,21 @@
# Copyright (c) 2017 Ultimaker B.V.
# Cura is released under the terms of the AGPLv3 or higher.
from PyQt5.QtCore import QObject, QUrl
from PyQt5.QtGui import QDesktopServices
from UM.FlameProfiler import pyqtSlot
from UM.Event import CallFunctionEvent
from UM.Application import Application
from UM.Math.Vector import Vector
from UM.Scene.Selection import Selection
from UM.Operations.GroupedOperation import GroupedOperation
from UM.Operations.RemoveSceneNodeOperation import RemoveSceneNodeOperation
from UM.Operations.SetTransformOperation import SetTransformOperation
from cura.SetParentOperation import SetParentOperation
from cura.MultiplyObjectsJob import MultiplyObjectsJob
from cura.Settings.SetObjectExtruderOperation import SetObjectExtruderOperation
class CuraActions(QObject):
def __init__(self, parent = None):
@ -23,5 +34,58 @@ class CuraActions(QObject):
event = CallFunctionEvent(self._openUrl, [QUrl("http://github.com/Ultimaker/Cura/issues")], {})
Application.getInstance().functionEvent(event)
## Center all objects in the selection
@pyqtSlot()
def centerSelection(self) -> None:
operation = GroupedOperation()
for node in Selection.getAllSelectedObjects():
current_node = node
while current_node.getParent() and current_node.getParent().callDecoration("isGroup"):
current_node = current_node.getParent()
center_operation = SetTransformOperation(current_node, Vector())
operation.addOperation(center_operation)
operation.push()
## Multiply all objects in the selection
#
# \param count The number of times to multiply the selection.
@pyqtSlot(int)
def multiplySelection(self, count: int) -> None:
job = MultiplyObjectsJob(Selection.getAllSelectedObjects(), count, 8)
job.start()
## Delete all selected objects.
@pyqtSlot()
def deleteSelection(self) -> None:
if not Application.getInstance().getController().getToolsEnabled():
return
removed_group_nodes = []
op = GroupedOperation()
nodes = Selection.getAllSelectedObjects()
for node in nodes:
op.addOperation(RemoveSceneNodeOperation(node))
group_node = node.getParent()
if group_node and group_node.callDecoration("isGroup") and group_node not in removed_group_nodes:
remaining_nodes_in_group = list(set(group_node.getChildren()) - set(nodes))
if len(remaining_nodes_in_group) == 1:
removed_group_nodes.append(group_node)
op.addOperation(SetParentOperation(remaining_nodes_in_group[0], group_node.getParent()))
op.addOperation(RemoveSceneNodeOperation(group_node))
op.push()
## Set the extruder that should be used to print the selection.
#
# \param extruder_id The ID of the extruder stack to use for the selected objects.
@pyqtSlot(str)
def setExtruderForSelection(self, extruder_id: str) -> None:
operation = GroupedOperation()
for node in Selection.getAllSelectedObjects():
if node.callDecoration("getActiveExtruder") == extruder_id:
continue
operation.addOperation(SetObjectExtruderOperation(node, extruder_id))
operation.push()
def _openUrl(self, url):
QDesktopServices.openUrl(url)
QDesktopServices.openUrl(url)

View File

@ -26,6 +26,7 @@ from UM.Message import Message
from UM.i18n import i18nCatalog
from UM.Workspace.WorkspaceReader import WorkspaceReader
from UM.Platform import Platform
from UM.Decorators import deprecated
from UM.Operations.AddSceneNodeOperation import AddSceneNodeOperation
from UM.Operations.RemoveSceneNodeOperation import RemoveSceneNodeOperation
@ -109,6 +110,10 @@ class CuraApplication(QtApplication):
Q_ENUMS(ResourceTypes)
def __init__(self):
# this list of dir names will be used by UM to detect an old cura directory
for dir_name in ["extruders", "machine_instances", "materials", "plugins", "quality", "user", "variants"]:
Resources.addExpectedDirNameInData(dir_name)
Resources.addSearchPath(os.path.join(QtApplication.getInstallPrefix(), "share", "cura", "resources"))
if not hasattr(sys, "frozen"):
Resources.addSearchPath(os.path.join(os.path.abspath(os.path.dirname(__file__)), "..", "resources"))
@ -214,6 +219,7 @@ class CuraApplication(QtApplication):
self.getController().getScene().sceneChanged.connect(self.updatePlatformActivity)
self.getController().toolOperationStopped.connect(self._onToolOperationStopped)
self.getController().contextMenuRequested.connect(self._onContextMenuRequested)
Resources.addType(self.ResourceTypes.QmlFiles, "qml")
Resources.addType(self.ResourceTypes.Firmware, "firmware")
@ -803,6 +809,7 @@ class CuraApplication(QtApplication):
# Remove all selected objects from the scene.
@pyqtSlot()
@deprecated("Moved to CuraActions", "2.6")
def deleteSelection(self):
if not self.getController().getToolsEnabled():
return
@ -823,6 +830,7 @@ class CuraApplication(QtApplication):
## Remove an object from the scene.
# Note that this only removes an object if it is selected.
@pyqtSlot("quint64")
@deprecated("Use deleteSelection instead", "2.6")
def deleteObject(self, object_id):
if not self.getController().getToolsEnabled():
return
@ -850,13 +858,22 @@ class CuraApplication(QtApplication):
# \param count number of copies
# \param min_offset minimum offset to other objects.
@pyqtSlot("quint64", int)
@deprecated("Use CuraActions::multiplySelection", "2.6")
def multiplyObject(self, object_id, count, min_offset = 8):
job = MultiplyObjectsJob(object_id, count, min_offset)
node = self.getController().getScene().findObject(object_id)
if not node:
node = Selection.getSelectedObject(0)
while node.getParent() and node.getParent().callDecoration("isGroup"):
node = node.getParent()
job = MultiplyObjectsJob([node], count, min_offset)
job.start()
return
## Center object on platform.
@pyqtSlot("quint64")
@deprecated("Use CuraActions::centerSelection", "2.6")
def centerObject(self, object_id):
node = self.getController().getScene().findObject(object_id)
if not node and object_id != 0: # Workaround for tool handles overlapping the selected object
@ -1316,3 +1333,10 @@ class CuraApplication(QtApplication):
except Exception as e:
Logger.log("e", "Could not check file %s: %s", file_url, e)
return False
def _onContextMenuRequested(self, x: float, y: float) -> None:
# Ensure we select the object if we request a context menu over an object without having a selection.
if not Selection.hasSelection():
node = self.getController().getScene().findObject(self.getRenderer().getRenderPass("selection").getIdAtPosition(x, y))
if node:
Selection.add(node)

View File

@ -24,9 +24,9 @@ from UM.Operations.AddSceneNodeOperation import AddSceneNodeOperation
class MultiplyObjectsJob(Job):
def __init__(self, object_id, count, min_offset = 8):
def __init__(self, objects, count, min_offset = 8):
super().__init__()
self._object_id = object_id
self._objects = objects
self._count = count
self._min_offset = min_offset
@ -35,38 +35,42 @@ class MultiplyObjectsJob(Job):
dismissable=False, progress=0)
status_message.show()
scene = Application.getInstance().getController().getScene()
node = scene.findObject(self._object_id)
if not node and self._object_id != 0: # Workaround for tool handles overlapping the selected object
node = Selection.getSelectedObject(0)
# If object is part of a group, multiply group
current_node = node
while current_node.getParent() and current_node.getParent().callDecoration("isGroup"):
current_node = current_node.getParent()
total_progress = len(self._objects) * self._count
current_progress = 0
root = scene.getRoot()
arranger = Arrange.create(scene_root=root)
node_too_big = False
if node.getBoundingBox().width < 300 or node.getBoundingBox().depth < 300:
offset_shape_arr, hull_shape_arr = ShapeArray.fromNode(current_node, min_offset=self._min_offset)
else:
node_too_big = True
nodes = []
found_solution_for_all = True
for i in range(self._count):
# We do place the nodes one by one, as we want to yield in between.
if not node_too_big:
node, solution_found = arranger.findNodePlacement(current_node, offset_shape_arr, hull_shape_arr)
if node_too_big or not solution_found:
found_solution_for_all = False
new_location = node.getPosition()
new_location = new_location.set(z = 100 - i * 20)
node.setPosition(new_location)
for node in self._objects:
# If object is part of a group, multiply group
current_node = node
while current_node.getParent() and current_node.getParent().callDecoration("isGroup"):
current_node = current_node.getParent()
node_too_big = False
if node.getBoundingBox().width < 300 or node.getBoundingBox().depth < 300:
offset_shape_arr, hull_shape_arr = ShapeArray.fromNode(current_node, min_offset=self._min_offset)
else:
node_too_big = True
found_solution_for_all = True
for i in range(self._count):
# We do place the nodes one by one, as we want to yield in between.
if not node_too_big:
node, solution_found = arranger.findNodePlacement(current_node, offset_shape_arr, hull_shape_arr)
if node_too_big or not solution_found:
found_solution_for_all = False
new_location = node.getPosition()
new_location = new_location.set(z = 100 - i * 20)
node.setPosition(new_location)
nodes.append(node)
current_progress += 1
status_message.setProgress((current_progress / total_progress) * 100)
Job.yieldThread()
nodes.append(node)
Job.yieldThread()
status_message.setProgress((i + 1) / self._count * 100)
if nodes:
op = GroupedOperation()

View File

@ -8,12 +8,13 @@ from UM.Application import Application #To get the global container stack to fin
from UM.Logger import Logger
from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator
from UM.Scene.SceneNode import SceneNode
from UM.Scene.Selection import Selection
from UM.Settings.ContainerRegistry import ContainerRegistry #Finding containers by ID.
from UM.Settings.InstanceContainer import InstanceContainer
from UM.Settings.SettingFunction import SettingFunction
from UM.Settings.ContainerStack import ContainerStack
from UM.Settings.DefinitionContainer import DefinitionContainer
from typing import Optional
from typing import Optional, List
## Manages all existing extruder stacks.
#
@ -34,10 +35,13 @@ class ExtruderManager(QObject):
super().__init__(parent)
self._extruder_trains = { } #Per machine, a dictionary of extruder container stack IDs.
self._active_extruder_index = 0
self._selected_object_extruders = []
Application.getInstance().globalContainerStackChanged.connect(self.__globalContainerStackChanged)
self._global_container_stack_definition_id = None
self._addCurrentMachineExtruders()
Selection.selectionChanged.connect(self.resetSelectedObjectExtruders)
## Gets the unique identifier of the currently active extruder stack.
#
# The currently active extruder stack is the stack that is currently being
@ -117,6 +121,34 @@ class ExtruderManager(QObject):
except IndexError:
return ""
## Emitted whenever the selectedObjectExtruders property changes.
selectedObjectExtrudersChanged = pyqtSignal()
## Provides a list of extruder IDs used by the current selected objects.
@pyqtProperty("QVariantList", notify = selectedObjectExtrudersChanged)
def selectedObjectExtruders(self) -> List[str]:
if not self._selected_object_extruders:
object_extruders = set()
for node in Selection.getAllSelectedObjects():
extruder = node.callDecoration("getActiveExtruder")
if extruder:
object_extruders.add(extruder)
else:
global_stack = Application.getInstance().getGlobalContainerStack()
object_extruders.add(self._extruder_trains[global_stack.getId()]["0"].getId())
self._selected_object_extruders = list(object_extruders)
return self._selected_object_extruders
## Reset the internal list used for the selectedObjectExtruders property
#
# This will trigger a recalculation of the extruders used for the
# selection.
def resetSelectedObjectExtruders(self) -> None:
self._selected_object_extruders = []
self.selectedObjectExtrudersChanged.emit()
def getActiveExtruderStack(self) -> ContainerStack:
global_container_stack = Application.getInstance().getGlobalContainerStack()
@ -444,6 +476,8 @@ class ExtruderManager(QObject):
self.globalContainerStackDefinitionChanged.emit()
self.activeExtruderChanged.emit()
self.resetSelectedObjectExtruders()
## Adds the extruders of the currently active machine.
def _addCurrentMachineExtruders(self) -> None:
global_stack = Application.getInstance().getGlobalContainerStack()

View File

@ -1,7 +1,7 @@
# Copyright (c) 2016 Ultimaker B.V.
# Cura is released under the terms of the AGPLv3 or higher.
from PyQt5.QtCore import Qt, pyqtSignal, pyqtProperty
from PyQt5.QtCore import Qt, pyqtSignal, pyqtProperty, pyqtSlot
import UM.Qt.ListModel
from UM.Application import Application
@ -33,6 +33,12 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel):
# The ID of the definition of the extruder.
DefinitionRole = Qt.UserRole + 5
# The material of the extruder.
MaterialRole = Qt.UserRole + 6
# The variant of the extruder.
VariantRole = Qt.UserRole + 7
## List of colours to display if there is no material or the material has no known
# colour.
defaultColors = ["#ffc924", "#86ec21", "#22eeee", "#245bff", "#9124ff", "#ff24c8"]
@ -49,6 +55,8 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel):
self.addRoleName(self.ColorRole, "color")
self.addRoleName(self.IndexRole, "index")
self.addRoleName(self.DefinitionRole, "definition")
self.addRoleName(self.MaterialRole, "material")
self.addRoleName(self.VariantRole, "variant")
self._add_global = False
self._simple_names = False
@ -140,6 +148,7 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel):
for extruder in manager.getMachineExtruders(global_container_stack.getId()):
extruder_name = extruder.getName()
material = extruder.findContainer({ "type": "material" })
variant = extruder.findContainer({"type": "variant"})
position = extruder.getMetaDataEntry("position", default = "0") # Get the position
try:
position = int(position)
@ -152,7 +161,9 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel):
"name": extruder_name,
"color": color,
"index": position,
"definition": extruder.getBottom().getId()
"definition": extruder.getBottom().getId(),
"material": material.getName() if material else "",
"variant": variant.getName() if variant else "",
}
items.append(item)
changed = True

View File

@ -0,0 +1,27 @@
# Copyright (c) 2017 Ultimaker B.V.
# Cura is released under the terms of the AGPLv3 or higher.
from UM.Scene.SceneNode import SceneNode
from UM.Operations.Operation import Operation
from cura.Settings.SettingOverrideDecorator import SettingOverrideDecorator
## Simple operation to set the extruder a certain object should be printed with.
class SetObjectExtruderOperation(Operation):
def __init__(self, node: SceneNode, extruder_id: str) -> None:
self._node = node
self._extruder_id = extruder_id
self._previous_extruder_id = None
self._decorator_added = False
def undo(self):
if self._previous_extruder_id:
self._node.callDecoration("setActiveExtruder", self._previous_extruder_id)
def redo(self):
stack = self._node.callDecoration("getStack") #Don't try to get the active extruder since it may be None anyway.
if not stack:
self._node.addDecorator(SettingOverrideDecorator())
self._previous_extruder_id = self._node.callDecoration("getActiveExtruder")
self._node.callDecoration("setActiveExtruder", self._extruder_id)

View File

@ -109,10 +109,13 @@ class SettingInheritanceManager(QObject):
self._settings_with_inheritance_warning.remove(key)
settings_with_inheritance_warning_changed = True
# Find the topmost parent (Assumed to be a category)
parent = definitions[0].parent
while parent.parent is not None:
parent = parent.parent
# Find the topmost parent (Assumed to be a category)
if parent is not None:
while parent.parent is not None:
parent = parent.parent
else:
parent = definitions[0] # Already at a category
if parent.key not in self._settings_with_inheritance_warning and has_overwritten_inheritance:
# Category was not in the list yet, so needs to be added now.

View File

@ -109,6 +109,7 @@ class SettingOverrideDecorator(SceneNodeDecorator):
def setActiveExtruder(self, extruder_stack_id):
self._extruder_stack = extruder_stack_id
self._updateNextStack()
ExtruderManager.getInstance().resetSelectedObjectExtruders()
self.activeExtruderChanged.emit()
def getStack(self):

View File

@ -283,10 +283,8 @@ class NetworkPrinterOutputDevice(PrinterOutputDevice):
#
# /param temperature The new target temperature of the bed.
def _setTargetBedTemperature(self, temperature):
if self._target_bed_temperature == temperature:
if not self._updateTargetBedTemperature(temperature):
return
self._target_bed_temperature = temperature
self.targetBedTemperatureChanged.emit()
url = QUrl("http://" + self._address + self._api_prefix + "printer/bed/temperature/target")
data = str(temperature)
@ -294,6 +292,17 @@ class NetworkPrinterOutputDevice(PrinterOutputDevice):
put_request.setHeader(QNetworkRequest.ContentTypeHeader, "application/json")
self._manager.put(put_request, data.encode())
## Updates the target bed temperature from the printer, and emit a signal if it was changed.
#
# /param temperature The new target temperature of the bed.
# /return boolean, True if the temperature was changed, false if the new temperature has the same value as the already stored temperature
def _updateTargetBedTemperature(self, temperature):
if self._target_bed_temperature == temperature:
return False
self._target_bed_temperature = temperature
self.targetBedTemperatureChanged.emit()
return True
def _stopCamera(self):
self._camera_timer.stop()
if self._image_reply:
@ -528,7 +537,7 @@ class NetworkPrinterOutputDevice(PrinterOutputDevice):
bed_temperature = self._json_printer_state["bed"]["temperature"]["current"]
self._setBedTemperature(bed_temperature)
target_bed_temperature = self._json_printer_state["bed"]["temperature"]["target"]
self._setTargetBedTemperature(target_bed_temperature)
self._updateTargetBedTemperature(target_bed_temperature)
head_x = self._json_printer_state["heads"][0]["position"]["x"]
head_y = self._json_printer_state["heads"][0]["position"]["y"]

View File

@ -3,6 +3,7 @@
import copy
import io
from typing import Optional
import xml.etree.ElementTree as ET
from UM.Resources import Resources
@ -11,7 +12,7 @@ from UM.Util import parseBool
from cura.CuraApplication import CuraApplication
import UM.Dictionary
from UM.Settings.InstanceContainer import InstanceContainer
from UM.Settings.InstanceContainer import InstanceContainer, InvalidInstanceError
from UM.Settings.ContainerRegistry import ContainerRegistry
## Handles serializing and deserializing material containers from an XML file
@ -370,8 +371,30 @@ class XmlMaterialProfile(InstanceContainer):
self._dirty = False
self._path = ""
def getConfigurationTypeFromSerialized(self, serialized: str) -> Optional[str]:
return "material"
def getVersionFromSerialized(self, serialized: str) -> Optional[int]:
version = None
data = ET.fromstring(serialized)
metadata = data.iterfind("./um:metadata/*", self.__namespaces)
for entry in metadata:
tag_name = _tag_without_namespace(entry)
if tag_name == "version":
try:
version = int(entry.text)
except Exception as e:
raise InvalidInstanceError("Invalid version string '%s': %s" % (entry.text, e))
break
if version is None:
raise InvalidInstanceError("Missing version in metadata")
return version
## Overridden from InstanceContainer
def deserialize(self, serialized):
# update the serialized data first
from UM.Settings.Interfaces import ContainerInterface
serialized = ContainerInterface.deserialize(self, serialized)
data = ET.fromstring(serialized)
# Reset previous metadata
@ -406,10 +429,10 @@ class XmlMaterialProfile(InstanceContainer):
continue
meta_data[tag_name] = entry.text
if not "description" in meta_data:
if "description" not in meta_data:
meta_data["description"] = ""
if not "adhesion_info" in meta_data:
if "adhesion_info" not in meta_data:
meta_data["adhesion_info"] = ""
property_values = {}
@ -583,7 +606,8 @@ class XmlMaterialProfile(InstanceContainer):
"Ultimaker 2 Extended": "ultimaker2_extended",
"Ultimaker 2 Extended+": "ultimaker2_extended_plus",
"Ultimaker Original": "ultimaker_original",
"Ultimaker Original+": "ultimaker_original_plus"
"Ultimaker Original+": "ultimaker_original_plus",
"IMADE3D JellyBOX": "imade3d_jellybox"
}
# Map of recognised namespaces with a proper prefix.

View File

@ -845,7 +845,7 @@
"unit": "mm",
"default_value": 0.8,
"minimum_value": "0",
"minimum_value_warning": "3 * resolveOrValue('layer_height')",
"minimum_value_warning": "0.2 + resolveOrValue('layer_height')",
"maximum_value": "machine_height",
"type": "float",
"value": "top_bottom_thickness",
@ -860,7 +860,7 @@
"minimum_value": "0",
"maximum_value_warning": "100",
"type": "int",
"minimum_value_warning": "4",
"minimum_value_warning": "2",
"value": "0 if infill_sparse_density == 100 else math.ceil(round(top_thickness / resolveOrValue('layer_height'), 4))",
"settable_per_mesh": true
}
@ -873,7 +873,7 @@
"unit": "mm",
"default_value": 0.6,
"minimum_value": "0",
"minimum_value_warning": "3 * resolveOrValue('layer_height')",
"minimum_value_warning": "0.2 + resolveOrValue('layer_height')",
"type": "float",
"value": "top_bottom_thickness",
"maximum_value": "machine_height",
@ -885,7 +885,7 @@
"label": "Bottom Layers",
"description": "The number of bottom layers. When calculated by the bottom thickness, this value is rounded to a whole number.",
"minimum_value": "0",
"minimum_value_warning": "4",
"minimum_value_warning": "2",
"default_value": 6,
"type": "int",
"value": "999999 if infill_sparse_density == 100 else math.ceil(round(bottom_thickness / resolveOrValue('layer_height'), 4))",
@ -1301,7 +1301,7 @@
"type": "int",
"minimum_value": "0",
"maximum_value_warning": "4",
"maximum_value": "(20 - math.log(infill_line_distance) / math.log(2)) if infill_line_distance > 0 and not spaghetti_infill_enabled else 0",
"maximum_value": "0 if spaghetti_infill_enabled else (999999 if infill_line_distance == 0 else (20 - math.log(infill_line_distance) / math.log(2)))",
"enabled": "infill_sparse_density > 0 and infill_pattern != 'cubicsubdiv' and not spaghetti_infill_enabled",
"settable_per_mesh": true
},
@ -2332,7 +2332,6 @@
"unit": "mm/s",
"type": "float",
"minimum_value": "0.1",
"minimum_value_warning": "5",
"maximum_value_warning": "50",
"default_value": 20,
"enabled": "resolveOrValue('jerk_enabled')",
@ -2346,7 +2345,6 @@
"unit": "mm/s",
"type": "float",
"minimum_value": "0.1",
"minimum_value_warning": "5",
"maximum_value_warning": "50",
"default_value": 20,
"value": "jerk_print",
@ -2360,7 +2358,6 @@
"unit": "mm/s",
"type": "float",
"minimum_value": "0.1",
"minimum_value_warning": "5",
"maximum_value_warning": "50",
"default_value": 20,
"value": "jerk_print",
@ -2375,7 +2372,6 @@
"unit": "mm/s",
"type": "float",
"minimum_value": "0.1",
"minimum_value_warning": "5",
"maximum_value_warning": "50",
"default_value": 20,
"value": "jerk_wall",
@ -2389,7 +2385,6 @@
"unit": "mm/s",
"type": "float",
"minimum_value": "0.1",
"minimum_value_warning": "5",
"maximum_value_warning": "50",
"default_value": 20,
"value": "jerk_wall",
@ -2405,7 +2400,6 @@
"unit": "mm/s",
"type": "float",
"minimum_value": "0.1",
"minimum_value_warning": "5",
"maximum_value_warning": "50",
"default_value": 20,
"value": "jerk_print",
@ -2419,7 +2413,6 @@
"unit": "mm/s",
"type": "float",
"minimum_value": "0.1",
"minimum_value_warning": "5",
"maximum_value_warning": "50",
"default_value": 20,
"value": "jerk_print",
@ -2438,7 +2431,6 @@
"default_value": 20,
"value": "jerk_support",
"minimum_value": "0.1",
"minimum_value_warning": "5",
"maximum_value_warning": "50",
"enabled": "resolveOrValue('jerk_enabled') and support_enable",
"limit_to_extruder": "support_infill_extruder_nr",
@ -2454,7 +2446,6 @@
"default_value": 20,
"value": "jerk_support",
"minimum_value": "0.1",
"minimum_value_warning": "5",
"maximum_value_warning": "50",
"enabled": "resolveOrValue('jerk_enabled') and extruderValue(support_interface_extruder_nr, 'support_interface_enable') and support_enable",
"limit_to_extruder": "support_interface_extruder_nr",
@ -2470,7 +2461,6 @@
"unit": "mm/s",
"type": "float",
"minimum_value": "0.1",
"minimum_value_warning": "5",
"maximum_value_warning": "50",
"default_value": 20,
"value": "jerk_print",
@ -2487,7 +2477,6 @@
"type": "float",
"default_value": 30,
"minimum_value": "0.1",
"minimum_value_warning": "5",
"maximum_value_warning": "50",
"value": "jerk_print if magic_spiralize else 30",
"enabled": "resolveOrValue('jerk_enabled')",
@ -2502,7 +2491,6 @@
"default_value": 20,
"value": "jerk_print",
"minimum_value": "0.1",
"minimum_value_warning": "5",
"maximum_value_warning": "50",
"enabled": "resolveOrValue('jerk_enabled')",
"settable_per_mesh": true,
@ -2517,7 +2505,6 @@
"default_value": 20,
"value": "jerk_layer_0",
"minimum_value": "0.1",
"minimum_value_warning": "5",
"maximum_value_warning": "50",
"enabled": "resolveOrValue('jerk_enabled')",
"settable_per_mesh": true
@ -2531,7 +2518,6 @@
"default_value": 20,
"value": "jerk_layer_0 * jerk_travel / jerk_print",
"minimum_value": "0.1",
"minimum_value_warning": "5",
"maximum_value_warning": "50",
"enabled": "resolveOrValue('jerk_enabled')",
"settable_per_extruder": true,
@ -2547,7 +2533,6 @@
"type": "float",
"default_value": 20,
"minimum_value": "0.1",
"minimum_value_warning": "5",
"maximum_value_warning": "50",
"value": "jerk_layer_0",
"enabled": "resolveOrValue('jerk_enabled')",

View File

@ -32,7 +32,7 @@
"machine_center_is_zero": { "default_value": false },
"machine_gcode_flavor": { "default_value": "RepRap (Marlin/Sprinter)" },
"machine_start_gcode": {
"default_value": ";---------------------------------------\n; ; ; Jellybox Start Script Begin ; ; ;\n;_______________________________________\n; M92 E140 ;optionally adjust steps per mm for your filament\n\n; Print Settings Summary\n; (leave these alone: this is only a list of the slicing settings)\n; (overwriting these values will NOT change your printer's behavior)\n; sliced for : {machine_name}\n; nozzle diameter : {machine_nozzle_size}\n; filament diameter : {material_diameter}\n; layer height : {layer_height}\n; 1st layer height : {layer_height_0}\n; line width : {line_width}\n; outer wall wipe dist. : {wall_0_wipe_dist}\n; infill line width : {infill_line_width}\n; wall thickness : {wall_thickness}\n; top thickness : {top_thickness}\n; bottom thickness : {bottom_thickness}\n; infill density : {infill_sparse_density}\n; infill pattern : {infill_pattern}\n; print temperature : {material_print_temperature}\n; 1st layer print temp. : {material_print_temperature_layer_0}\n; heated bed temperature : {material_bed_temperature}\n; 1st layer bed temp. : {material_bed_temperature_layer_0}\n; regular fan speed : {cool_fan_speed_min}\n; max fan speed : {cool_fan_speed_max}\n; retraction amount : {retraction_amount}\n; retr. retract speed : {retraction_retract_speed}\n; retr. prime speed : {retraction_prime_speed}\n; build plate adhesion : {adhesion_type}\n; support ? {support_enable}\n; spiralized ? {magic_spiralize}\n\nM117 Preparing ;write Preparing\nM140 S{material_bed_temperature_layer_0} ;set bed temperature and move on\nM104 S{material_print_temperature_layer_0} ;set extruder temperature and move on\nM206 X10.0 Y0.0 ;set x homing offset for default bed leveling\nG21 ;metric values\nG90 ;absolute positioning\nM107 ;start with the fan off\nM82 ;set extruder to absolute mode\nG28 ;home all axes\nM203 Z4 ;slow Z speed down for greater accuracy when probing\nG29 ;auto bed leveling procedure\nM203 Z7 ;pick up z speed again for printing\nM190 S{material_bed_temperature_layer_0} ;wait for the bed to reach desired temperature\nM109 S{material_print_temperature_layer_0} ;wait for the extruder to reach desired temperature\nG92 E0 ;reset the extruder position\nG1 F1500 E15 ;extrude 15mm of feed stock\nG92 E0 ;reset the extruder position again\nM117 Print starting ;write Print starting\n;---------------------------------------------\n; ; ; Jellybox Printer Start Script End ; ; ;\n;_____________________________________________\n"
"default_value": ";---------------------------------------\n; ; ; Jellybox Start Script Begin ; ; ;\n;_______________________________________\n; M92 E140 ;optionally adjust steps per mm for your filament\n\n; Print Settings Summary\n; (leave these alone: this is only a list of the slicing settings)\n; (overwriting these values will NOT change your printer's behavior)\n; sliced for : {machine_name}\n; nozzle diameter : {machine_nozzle_size}\n; filament diameter : {material_diameter}\n; layer height : {layer_height}\n; 1st layer height : {layer_height_0}\n; line width : {line_width}\n; outer wall wipe dist. : {wall_0_wipe_dist}\n; infill line width : {infill_line_width}\n; wall thickness : {wall_thickness}\n; top thickness : {top_thickness}\n; bottom thickness : {bottom_thickness}\n; infill density : {infill_sparse_density}\n; infill pattern : {infill_pattern}\n; print temperature : {material_print_temperature}\n; 1st layer print temp. : {material_print_temperature_layer_0}\n; heated bed temperature : {material_bed_temperature}\n; 1st layer bed temp. : {material_bed_temperature_layer_0}\n; regular fan speed : {cool_fan_speed_min}\n; max fan speed : {cool_fan_speed_max}\n; retraction amount : {retraction_amount}\n; retr. retract speed : {retraction_retract_speed}\n; retr. prime speed : {retraction_prime_speed}\n; build plate adhesion : {adhesion_type}\n; support ? {support_enable}\n; spiralized ? {magic_spiralize}\n\nM117 Preparing ;write Preparing\nM140 S{material_bed_temperature_layer_0} ;set bed temperature and move on\nM109 S{material_print_temperature} ; wait for the extruder to reach desired temperature\nM206 X10.0 Y0.0 ;set x homing offset for default bed leveling\nG21 ;metric values\nG90 ;absolute positioning\nM107 ;start with the fan off\nM82 ;set extruder to absolute mode\nG28 ;home all axes\nM203 Z4 ;slow Z speed down for greater accuracy when probing\nG29 ;auto bed leveling procedure\nM203 Z7 ;pick up z speed again for printing\nM190 S{material_bed_temperature_layer_0} ;wait for the bed to reach desired temperature\nM109 S{material_print_temperature_layer_0} ;wait for the extruder to reach desired temperature\nG92 E0 ;reset the extruder position\nG1 F1500 E15 ;extrude 15mm of feed stock\nG92 E0 ;reset the extruder position again\nM117 Print starting ;write Print starting\n;---------------------------------------------\n; ; ; Jellybox Printer Start Script End ; ; ;\n;_____________________________________________\n"
},
"machine_end_gcode": {
"default_value": "\n;---------------------------------\n;;; Jellybox End Script Begin ;;;\n;_________________________________\nM117 Finishing Up ;write Finishing Up\n\nM104 S0 ;extruder heater off\nM140 S0 ;bed heater off (if you have it)\nG91 ;relative positioning\nG1 E-1 F300 ;retract the filament a bit before lifting the nozzle, to release some of the pressure\nG1 Z+0.5 E-5 X-20 Y-20 F9000 ;move Z up a bit and retract filament even more\nG90 ;absolute positioning\nG28 X ;home x, so the head is out of the way\nG1 Y100 ;move Y forward, so the print is more accessible\nM84 ;steppers off\n\nM117 Print finished ;write Print finished\n;---------------------------------------\n;;; Jellybox End Script End ;;;\n;_______________________________________"

View File

@ -0,0 +1,130 @@
{
"id": "rigid3d_zero2",
"name": "Rigid3D Zero2",
"version": 2,
"inherits": "fdmprinter",
"metadata": {
"visible": true,
"author": "Rigid3D",
"manufacturer": "Rigid3D",
"category": "Other",
"has_materials": false,
"file_formats": "text/x-gcode",
"platform": "rigid3d_zero2_platform.stl",
"platform_offset": [ 5, 0, -35]
},
"overrides": {
"machine_name": { "default_value": "Rigid3D Zero2" },
"machine_head_with_fans_polygon": {
"default_value": [[ 30, 30], [ 30, 70], [ 30, 70], [ 30, 30]]
},
"z_seam_type": {
"default_value": "random"
},
"machine_heated_bed": {
"default_value": true
},
"layer_height": {
"default_value": 0.2
},
"layer_height_0": {
"default_value": 0.2
},
"wall_thickness": {
"default_value": 0.8
},
"top_bottom_thickness": {
"default_value": 0.8
},
"xy_offset": {
"default_value": -0.2
},
"material_print_temperature": {
"value": 235
},
"material_bed_temperature": {
"default_value": 100
},
"material_diameter": {
"default_value": 1.75
},
"speed_print": {
"default_value": 40
},
"speed_layer_0": {
"value": 15
},
"speed_tarvel": {
"value": 100
},
"support_enable": {
"default_value": false
},
"infill_sparse_density": {
"default_value": 15
},
"infill_pattern": {
"default_value": "lines",
"value": "lines"
},
"retraction_amount": {
"default_value": 1
},
"machine_width": {
"default_value": 200
},
"machine_height": {
"default_value": 200
},
"machine_depth": {
"default_value": 200
},
"machine_center_is_zero": {
"default_value": false
},
"machine_nozzle_size": {
"default_value": 0.4
},
"gantry_height": {
"default_value": 25
},
"machine_gcode_flavor": {
"default_value": "RepRap"
},
"cool_fan_enabled": {
"default_value": false
},
"cool_fan_speed": {
"default_value": 50,
"value": 50
},
"cool_fan_speed_min": {
"default_value": 0
},
"cool_fan_full_at_height": {
"default_value": 1.0,
"value": 1.0
},
"support_z_distance": {
"default_value": 0.2
},
"support_interface_enable": {
"default_value": true
},
"support_interface_height": {
"default_value": 0.8
},
"support_interface_density": {
"default_value": 70
},
"support_interface_pattern": {
"default_value": "grid"
},
"machine_start_gcode": {
"default_value": "G21\nG28 ; Home extruder\nM107 ; Turn off fan\nG91 ; Relative positioning\nG1 Z5 F180;\nG1 X100 Y100 F3000;\nG1 Z-5 F180;\nG90 ; Absolute positioning\nM82 ; Extruder in absolute mode\nG92 E0 ; Reset extruder position\n"
},
"machine_end_gcode": {
"default_value": "G1 X0 Y180 ; Get extruder out of way.\nM107 ; Turn off fan\nG91 ; Relative positioning\nG0 Z20 ; Lift extruder up\nT0\nG1 E-1 ; Reduce filament pressure\nM104 T0 S0 ; Turn extruder heater off\nG90 ; Absolute positioning\nG92 E0 ; Reset extruder position\nM140 S0 ; Disable heated bed\nM84 ; Turn steppers off\n"
}
}
}

View File

@ -70,7 +70,7 @@
"machine_start_gcode": { "default_value": "" },
"machine_end_gcode": { "default_value": "" },
"prime_tower_position_x": { "default_value": 175 },
"prime_tower_position_y": { "default_value": 179 },
"prime_tower_position_y": { "default_value": 178 },
"prime_tower_wipe_enabled": { "default_value": false },
"acceleration_enabled": { "value": "True" },

Binary file not shown.

View File

@ -18,6 +18,8 @@ Item
property alias redo: redoAction;
property alias deleteSelection: deleteSelectionAction;
property alias centerSelection: centerSelectionAction;
property alias multiplySelection: multiplySelectionAction;
property alias deleteObject: deleteObjectAction;
property alias centerObject: centerObjectAction;
@ -181,11 +183,28 @@ Item
Action
{
id: deleteSelectionAction;
text: catalog.i18nc("@action:inmenu menubar:edit","Delete &Selection");
enabled: UM.Controller.toolsEnabled;
text: catalog.i18ncp("@action:inmenu menubar:edit", "Delete &Selected Model", "Delete &Selected Models", UM.Selection.selectionCount);
enabled: UM.Controller.toolsEnabled && UM.Selection.hasSelection;
iconName: "edit-delete";
shortcut: StandardKey.Delete;
onTriggered: CuraApplication.deleteSelection();
onTriggered: CuraActions.deleteSelection();
}
Action
{
id: centerSelectionAction;
text: catalog.i18ncp("@action:inmenu menubar:edit", "Center Selected Model", "Center Selected Models", UM.Selection.selectionCount);
enabled: UM.Controller.toolsEnabled && UM.Selection.hasSelection;
iconName: "align-vertical-center";
onTriggered: CuraActions.centerSelection();
}
Action
{
id: multiplySelectionAction;
text: catalog.i18ncp("@action:inmenu menubar:edit", "Multiply Selected Model", "Multiply Selected Models", UM.Selection.selectionCount);
enabled: UM.Controller.toolsEnabled && UM.Selection.hasSelection;
iconName: "edit-duplicate";
}
Action

View File

@ -180,7 +180,7 @@ UM.Dialog
anchors.bottom:parent.bottom
spacing: UM.Theme.getSize("default_margin").width
Label
Text
{
text: catalog.i18nc("@label", "Printer Name:")
anchors.verticalCenter: machineName.verticalCenter

View File

@ -594,102 +594,8 @@ UM.MainWindow
}
}
Menu
{
id: objectContextMenu;
property variant objectId: -1;
MenuItem { action: Cura.Actions.centerObject; }
MenuItem { action: Cura.Actions.deleteObject; }
MenuItem { action: Cura.Actions.multiplyObject; }
MenuSeparator { }
MenuItem { action: Cura.Actions.selectAll; }
MenuItem { action: Cura.Actions.arrangeAll; }
MenuItem { action: Cura.Actions.deleteAll; }
MenuItem { action: Cura.Actions.reloadAll; }
MenuItem { action: Cura.Actions.resetAllTranslation; }
MenuItem { action: Cura.Actions.resetAll; }
MenuSeparator { }
MenuItem { action: Cura.Actions.groupObjects; }
MenuItem { action: Cura.Actions.mergeObjects; }
MenuItem { action: Cura.Actions.unGroupObjects; }
Connections
{
target: Cura.Actions.deleteObject
onTriggered:
{
if(objectContextMenu.objectId != 0)
{
CuraApplication.deleteObject(objectContextMenu.objectId);
objectContextMenu.objectId = 0;
}
}
}
MultiplyObjectOptions
{
id: multiplyObjectOptions
}
Connections
{
target: Cura.Actions.multiplyObject
onTriggered:
{
if(objectContextMenu.objectId != 0)
{
multiplyObjectOptions.objectId = objectContextMenu.objectId;
multiplyObjectOptions.visible = true;
multiplyObjectOptions.reset();
objectContextMenu.objectId = 0;
}
}
}
Connections
{
target: Cura.Actions.centerObject
onTriggered:
{
if(objectContextMenu.objectId != 0)
{
CuraApplication.centerObject(objectContextMenu.objectId);
objectContextMenu.objectId = 0;
}
}
}
}
Menu
{
id: contextMenu;
MenuItem { action: Cura.Actions.selectAll; }
MenuItem { action: Cura.Actions.arrangeAll; }
MenuItem { action: Cura.Actions.deleteAll; }
MenuItem { action: Cura.Actions.reloadAll; }
MenuItem { action: Cura.Actions.resetAllTranslation; }
MenuItem { action: Cura.Actions.resetAll; }
MenuSeparator { }
MenuItem { action: Cura.Actions.groupObjects; }
MenuItem { action: Cura.Actions.mergeObjects; }
MenuItem { action: Cura.Actions.unGroupObjects; }
}
Connections
{
target: UM.Controller
onContextMenuRequested:
{
if(objectId == 0)
{
contextMenu.popup();
} else
{
objectContextMenu.objectId = objectId;
objectContextMenu.popup();
}
}
ContextMenu {
id: contextMenu
}
Connections

View File

@ -132,7 +132,7 @@ Item {
}
}
Label
Text
{
id: boundingSpec
anchors.top: jobNameRow.bottom
@ -169,7 +169,7 @@ Item {
color: UM.Theme.getColor("text_subtext")
source: UM.Theme.getIcon("print_time")
}
Label
Text
{
id: timeSpec
anchors.right: lengthIcon.left
@ -192,7 +192,7 @@ Item {
color: UM.Theme.getColor("text_subtext")
source: UM.Theme.getIcon("category_material")
}
Label
Text
{
id: lengthSpec
anchors.right: parent.right

View File

@ -0,0 +1,138 @@
// Copyright (c) 2016 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.Dialogs 1.2
import QtQuick.Window 2.1
import UM 1.2 as UM
import Cura 1.0 as Cura
Menu
{
id: base
property bool shouldShowExtruders: machineExtruderCount.properties.value > 1;
// Selection-related actions.
MenuItem { action: Cura.Actions.centerSelection; }
MenuItem { action: Cura.Actions.deleteSelection; }
MenuItem { action: Cura.Actions.multiplySelection; }
// Extruder selection - only visible if there is more than 1 extruder
MenuSeparator { visible: base.shouldShowExtruders }
MenuItem { id: extruderHeader; text: catalog.i18ncp("@label", "Print Selected Model With:", "Print Selected Models With:", UM.Selection.selectionCount); enabled: false; visible: base.shouldShowExtruders }
Instantiator
{
model: Cura.ExtrudersModel { id: extrudersModel }
MenuItem {
text: "%1: %2 - %3".arg(model.name).arg(model.material).arg(model.variant)
visible: base.shouldShowExtruders
enabled: UM.Selection.hasSelection
checkable: true
checked: ExtruderManager.selectedObjectExtruders.indexOf(model.id) != -1
onTriggered: CuraActions.setExtruderForSelection(model.id)
shortcut: "Ctrl+" + (model.index + 1)
}
onObjectAdded: base.insertItem(base.findItemIndex(extruderHeader) + index, object)
onObjectRemoved: base.removeItem(object)
}
// Global actions
MenuSeparator { }
MenuItem { action: Cura.Actions.selectAll; }
MenuItem { action: Cura.Actions.arrangeAll; }
MenuItem { action: Cura.Actions.deleteAll; }
MenuItem { action: Cura.Actions.reloadAll; }
MenuItem { action: Cura.Actions.resetAllTranslation; }
MenuItem { action: Cura.Actions.resetAll; }
// Group actions
MenuSeparator { }
MenuItem { action: Cura.Actions.groupObjects; }
MenuItem { action: Cura.Actions.mergeObjects; }
MenuItem { action: Cura.Actions.unGroupObjects; }
Connections
{
target: UM.Controller
onContextMenuRequested: base.popup();
}
Connections
{
target: Cura.Actions.multiplySelection
onTriggered: multiplyDialog.open()
}
UM.SettingPropertyProvider
{
id: machineExtruderCount
containerStackId: Cura.MachineManager.activeMachineId
key: "machine_extruder_count"
watchedProperties: [ "value" ]
}
Dialog
{
id: multiplyDialog
title: catalog.i18ncp("@title:window", "Multiply Selected Model", "Multiply Selected Models", UM.Selection.selectionCount)
width: 400 * Screen.devicePixelRatio
height: 80 * Screen.devicePixelRatio
onAccepted: CuraActions.multiplySelection(copiesField.value)
signal reset()
onReset:
{
copiesField.value = 1;
copiesField.focus = true;
}
standardButtons: StandardButton.Ok | StandardButton.Cancel
Row
{
spacing: UM.Theme.getSize("default_margin").width
Label
{
text: catalog.i18nc("@label", "Number of Copies")
anchors.verticalCenter: copiesField.verticalCenter
}
SpinBox
{
id: copiesField
minimumValue: 1
maximumValue: 99
}
}
}
// Find the index of an item in the list of child items of this menu.
//
// This is primarily intended as a helper function so we do not have to
// hard-code the position of the extruder selection actions.
//
// \param item The item to find the index of.
//
// \return The index of the item or -1 if it was not found.
function findItemIndex(item)
{
for(var i in base.items)
{
if(base.items[i] == item)
{
return i;
}
}
return -1;
}
UM.I18nCatalog { id: catalog; name: "cura" }
}

View File

@ -66,7 +66,7 @@ UM.ManagementPage
visible: base.currentItem != null
anchors.fill: parent
Label
Text
{
id: machineName
text: base.currentItem && base.currentItem.name ? base.currentItem.name : ""
@ -146,26 +146,28 @@ UM.ManagementPage
property var connectedPrinter: printerConnected ? Cura.MachineManager.printerOutputDevices[0] : null
property bool printerAcceptsCommands: printerConnected && Cura.MachineManager.printerOutputDevices[0].acceptsCommands
Label
Text
{
text: catalog.i18nc("@label", "Printer type:")
visible: base.currentItem && "definition_name" in base.currentItem.metadata
}
Label {
Text
{
text: (base.currentItem && "definition_name" in base.currentItem.metadata) ? base.currentItem.metadata.definition_name : ""
}
Label
Text
{
text: catalog.i18nc("@label", "Connection:")
visible: base.currentItem && base.currentItem.id == Cura.MachineManager.activeMachineId
}
Label {
Text
{
width: parent.width * 0.7
text: machineInfo.printerConnected ? machineInfo.connectedPrinter.connectionText : catalog.i18nc("@info:status", "The printer is not connected.")
visible: base.currentItem && base.currentItem.id == Cura.MachineManager.activeMachineId
wrapMode: Text.WordWrap
}
Label
Text
{
text: catalog.i18nc("@label", "State:")
visible: base.currentItem && base.currentItem.id == Cura.MachineManager.activeMachineId && machineInfo.printerAcceptsCommands

View File

@ -273,17 +273,28 @@ TabView
{
id: spinBox
anchors.left: label.right
value: parseFloat(provider.properties.value);
width: base.secondColumnWidth;
value: {
if (!isNaN(parseFloat(materialPropertyProvider.properties.value)))
{
return parseFloat(materialPropertyProvider.properties.value);
}
if (!isNaN(parseFloat(machinePropertyProvider.properties.value)))
{
return parseFloat(machinePropertyProvider.properties.value);
}
return 0;
}
width: base.secondColumnWidth
readOnly: !base.editingEnabled
suffix: model.unit
suffix: " " + model.unit
maximumValue: 99999
decimals: model.unit == "mm" ? 2 : 0
onEditingFinished: provider.setPropertyValue("value", value)
onEditingFinished: materialPropertyProvider.setPropertyValue("value", value)
}
UM.ContainerPropertyProvider { id: provider; containerId: base.containerId; watchedProperties: [ "value" ]; key: model.key }
UM.ContainerPropertyProvider { id: materialPropertyProvider; containerId: base.containerId; watchedProperties: [ "value" ]; key: model.key }
UM.ContainerPropertyProvider { id: machinePropertyProvider; containerId: Cura.MachineManager.activeDefinitionId; watchedProperties: [ "value" ]; key: model.key }
}
}
}

View File

@ -649,6 +649,7 @@ Column
sourceComponent: monitorItem
property string label: catalog.i18nc("@label", "Estimated time left")
property string value: connectedPrinter != null ? getPrettyTime(connectedPrinter.timeTotal - connectedPrinter.timeElapsed) : ""
visible: connectedPrinter != null && (connectedPrinter.jobState == "printing" || connectedPrinter.jobState == "resuming" || connectedPrinter.jobState == "pausing" || connectedPrinter.jobState == "paused")
}
Component

93
resources/qml/Sidebar.qml Normal file → Executable file
View File

@ -407,14 +407,81 @@ Rectangle
}
}
ExclusiveGroup { id: modeMenuGroup; }
ListView{
id: modesList
property var index: 0
model: modesListModel
delegate: wizardDelegate
anchors.top: parent.top
anchors.left: parent.left
width: parent.width
Text
{
id: toggleLeftText
anchors.right: modeToggleSwitch.left
anchors.rightMargin: UM.Theme.getSize("toggle_button_text_anchoring_margin").width
anchors.verticalCenter: parent.verticalCenter
text: ""
color: UM.Theme.getColor("toggle_active_text")
font: UM.Theme.getFont("default")
MouseArea
{
anchors.fill: parent
onClicked:
{
modeToggleSwitch.checked = false;
}
Component.onCompleted:
{
clicked.connect(modeToggleSwitch.clicked)
}
}
}
Switch
{
id: modeToggleSwitch
checked: false
anchors.right: toggleRightText.left
anchors.rightMargin: UM.Theme.getSize("toggle_button_text_anchoring_margin").width
anchors.verticalCenter: parent.verticalCenter
onClicked:
{
var index = 0;
if (checked)
{
index = 1;
}
updateActiveMode(index);
}
function updateActiveMode(index)
{
base.currentModeIndex = index;
UM.Preferences.setValue("cura/active_mode", index);
}
style: UM.Theme.styles.toggle_button
}
Text
{
id: toggleRightText
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
text: ""
color: UM.Theme.getColor("toggle_active_text")
font: UM.Theme.getFont("default")
MouseArea
{
anchors.fill: parent
onClicked:
{
modeToggleSwitch.checked = true;
}
Component.onCompleted:
{
clicked.connect(modeToggleSwitch.clicked)
}
}
}
}
@ -541,10 +608,14 @@ Rectangle
})
sidebarContents.push({ "item": modesListModel.get(base.currentModeIndex).item, "immediate": true });
var index = parseInt(UM.Preferences.getValue("cura/active_mode"))
if(index)
toggleLeftText.text = modesListModel.get(0).text;
toggleRightText.text = modesListModel.get(1).text;
var index = parseInt(UM.Preferences.getValue("cura/active_mode"));
if (index)
{
currentModeIndex = index;
modeToggleSwitch.checked = index > 0;
}
}
@ -567,4 +638,4 @@ Rectangle
watchedProperties: [ "value" ]
storeIndex: 0
}
}
}

View File

@ -20,7 +20,6 @@ cool_min_layer_time_fan_speed_max = 5
cool_min_speed = 5
infill_line_width = =round(line_width * 0.4 / 0.35, 2)
infill_overlap = 0
infill_overlap_mm = 0.05
infill_pattern = triangles
infill_wipe_dist = 0.1
jerk_enabled = True

View File

@ -8,6 +8,44 @@ import QtQuick.Controls.Styles 1.1
import UM 1.1 as UM
QtObject {
property Component toggle_button: Component {
SwitchStyle {
groove: Rectangle {
implicitWidth: UM.Theme.getSize("toggle_button_background_implicit_size").width
implicitHeight: UM.Theme.getSize("toggle_button_background_implicit_size").height
radius: UM.Theme.getSize("toggle_button_radius").width
border.color: {
if (control.pressed || (control.checkable && control.checked)) {
return UM.Theme.getColor("sidebar_header_active");
} else if(control.hovered) {
return UM.Theme.getColor("sidebar_header_hover");
} else {
return UM.Theme.getColor("sidebar_header_bar");
}
}
Behavior on border.color { ColorAnimation { duration: 50; } }
border.width: 1
}
handle: Rectangle {
implicitWidth: UM.Theme.getSize("toggle_button_knob_implicit_size").width
implicitHeight: UM.Theme.getSize("toggle_button_knob_implicit_size").height
radius: UM.Theme.getSize("toggle_button_radius").width
color: {
if (control.pressed || (control.checkable && control.checked)) {
return UM.Theme.getColor("sidebar_header_active");
} else if(control.hovered) {
return UM.Theme.getColor("sidebar_header_hover");
} else {
return UM.Theme.getColor("sidebar_header_bar");
}
}
Behavior on color { ColorAnimation { duration: 50; } }
}
}
}
property Component sidebar_header_button: Component {
ButtonStyle {
background: Rectangle {

View File

@ -319,6 +319,11 @@
"infill_button_margin": [0.5, 0.5],
"jobspecs_line": [2.0, 2.0]
"jobspecs_line": [2.0, 2.0],
"toggle_button_text_anchoring_margin": [1.0, 1.0],
"toggle_button_radius": [1.0, 1.0],
"toggle_button_background_implicit_size": [2.0, 1.0],
"toggle_button_knob_implicit_size": [1.0, 1.0]
}
}