Merge branch 'master' into feature_multiextruder_machinesettings

This commit is contained in:
Jack Ha 2017-05-02 17:26:27 +02:00
commit 5d15d6e792
32 changed files with 1541 additions and 689 deletions

View file

@ -600,6 +600,7 @@ class BuildVolume(SceneNode):
result_areas[extruder_id].append(polygon) #Don't perform the offset on these.
# Add prime tower location as disallowed area.
if len(used_extruders) > 1: #No prime tower in single-extrusion.
prime_tower_collision = False
prime_tower_areas = self._computeDisallowedAreasPrinted(used_extruders)
for extruder_id in prime_tower_areas:
@ -955,4 +956,4 @@ class BuildVolume(SceneNode):
_tower_settings = ["prime_tower_enable", "prime_tower_size", "prime_tower_position_x", "prime_tower_position_y"]
_ooze_shield_settings = ["ooze_shield_enabled", "ooze_shield_dist"]
_distance_settings = ["infill_wipe_dist", "travel_avoid_distance", "support_offset", "support_enable", "travel_avoid_other_parts"]
_extruder_settings = ["support_enable", "support_interface_enable", "support_infill_extruder_nr", "support_extruder_nr_layer_0", "support_interface_extruder_nr", "brim_line_count", "adhesion_extruder_nr", "adhesion_type"] #Settings that can affect which extruders are used.
_extruder_settings = ["support_enable", "support_bottom_enable", "support_roof_enable", "support_infill_extruder_nr", "support_extruder_nr_layer_0", "support_bottom_extruder_nr", "support_roof_extruder_nr", "brim_line_count", "adhesion_extruder_nr", "adhesion_type"] #Settings that can affect which extruders are used.

View file

@ -1,10 +1,23 @@
# 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.Scene.Iterator.BreadthFirstIterator import BreadthFirstIterator
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
from cura.Settings.ExtruderManager import ExtruderManager
class CuraActions(QObject):
def __init__(self, parent = None):
@ -23,5 +36,84 @@ 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()
nodes_to_change = []
for node in Selection.getAllSelectedObjects():
# Do not change any nodes that already have the right extruder set.
if node.callDecoration("getActiveExtruder") == extruder_id:
continue
# If the node is a group, apply the active extruder to all children of the group.
if node.callDecoration("isGroup"):
for grouped_node in BreadthFirstIterator(node):
if grouped_node.callDecoration("getActiveExtruder") == extruder_id:
continue
if grouped_node.callDecoration("isGroup"):
continue
nodes_to_change.append(grouped_node)
continue
nodes_to_change.append(node)
if not nodes_to_change:
# If there are no changes to make, we still need to reset the selected extruders.
# This is a workaround for checked menu items being deselected while still being
# selected.
ExtruderManager.getInstance().resetSelectedObjectExtruders()
return
for node in nodes_to_change:
operation.addOperation(SetObjectExtruderOperation(node, extruder_id))
operation.push()
def _openUrl(self, 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
@ -221,6 +222,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")
@ -810,6 +812,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
@ -830,6 +833,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
@ -857,13 +861,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
@ -1323,3 +1336,13 @@ 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:
while(node.getParent() and node.getParent().callDecoration("isGroup")):
node = node.getParent()
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,24 +35,25 @@ 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)
total_progress = len(self._objects) * self._count
current_progress = 0
root = scene.getRoot()
arranger = Arrange.create(scene_root=root)
nodes = []
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()
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.
@ -65,8 +66,11 @@ class MultiplyObjectsJob(Job):
node.setPosition(new_location)
nodes.append(node)
current_progress += 1
status_message.setProgress((current_progress / total_progress) * 100)
Job.yieldThread()
Job.yieldThread()
status_message.setProgress((i + 1) / self._count * 100)
if nodes:
op = GroupedOperation()

View file

@ -8,12 +8,14 @@ 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.Scene.Iterator.BreadthFirstIterator import BreadthFirstIterator
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 +36,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 +122,48 @@ 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()
# First, build a list of the actual selected objects (including children of groups, excluding group nodes)
selected_nodes = []
for node in Selection.getAllSelectedObjects():
if node.callDecoration("isGroup"):
for grouped_node in BreadthFirstIterator(node):
if grouped_node.callDecoration("isGroup"):
continue
selected_nodes.append(grouped_node)
else:
selected_nodes.append(node)
# Then, figure out which nodes are used by those selected nodes.
for node in selected_nodes:
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()
@ -357,7 +404,8 @@ class ExtruderManager(QObject):
#Get the extruders of all meshes in the scene.
support_enabled = False
support_interface_enabled = False
support_bottom_enabled = False
support_roof_enabled = False
scene_root = Application.getInstance().getController().getScene().getRoot()
meshes = [node for node in DepthFirstIterator(scene_root) if type(node) is SceneNode and node.isSelectable()] #Only use the nodes that will be printed.
for mesh in meshes:
@ -370,18 +418,22 @@ class ExtruderManager(QObject):
per_mesh_stack = mesh.callDecoration("getStack")
if per_mesh_stack:
support_enabled |= per_mesh_stack.getProperty("support_enable", "value")
support_interface_enabled |= per_mesh_stack.getProperty("support_interface_enable", "value")
support_bottom_enabled |= per_mesh_stack.getProperty("support_bottom_enable", "value")
support_roof_enabled |= per_mesh_stack.getProperty("support_roof_enable", "value")
else: #Take the setting from the build extruder stack.
extruder_stack = container_registry.findContainerStacks(id = extruder_stack_id)[0]
support_enabled |= extruder_stack.getProperty("support_enable", "value")
support_interface_enabled |= extruder_stack.getProperty("support_enable", "value")
support_bottom_enabled |= extruder_stack.getProperty("support_bottom_enable", "value")
support_roof_enabled |= extruder_stack.getProperty("support_roof_enable", "value")
#The support extruders.
if support_enabled:
used_extruder_stack_ids.add(self.extruderIds[str(global_stack.getProperty("support_infill_extruder_nr", "value"))])
used_extruder_stack_ids.add(self.extruderIds[str(global_stack.getProperty("support_extruder_nr_layer_0", "value"))])
if support_interface_enabled:
used_extruder_stack_ids.add(self.extruderIds[str(global_stack.getProperty("support_interface_extruder_nr", "value"))])
if support_bottom_enabled:
used_extruder_stack_ids.add(self.extruderIds[str(global_stack.getProperty("support_bottom_extruder_nr", "value"))])
if support_roof_enabled:
used_extruder_stack_ids.add(self.extruderIds[str(global_stack.getProperty("support_roof_extruder_nr", "value"))])
#The platform adhesion extruder. Not used if using none.
if global_stack.getProperty("adhesion_type", "value") != "none":
@ -444,6 +496,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
@ -141,6 +149,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)
@ -156,7 +165,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
# 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

@ -13,9 +13,9 @@ from UM.Resources import Resources
from UM.Settings.Validator import ValidatorState #To find if a setting is in an error state. We can't slice then.
from UM.Platform import Platform
from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator
from UM.Qt.Duration import DurationFormat
from PyQt5.QtCore import QObject, pyqtSlot
from cura.Settings.ExtruderManager import ExtruderManager
from . import ProcessSlicedLayersJob
from . import StartSliceJob
@ -442,6 +442,15 @@ class CuraEngineBackend(QObject, Backend):
self.backendStateChange.emit(BackendState.Done)
self.processingProgress.emit(1.0)
for line in self._scene.gcode_list:
replaced = line.replace("{print_time}", str(Application.getInstance().getPrintInformation().currentPrintTime.getDisplayString(DurationFormat.Format.ISO8601)))
replaced = replaced.replace("{filament_amount}", str(Application.getInstance().getPrintInformation().materialLengths))
replaced = replaced.replace("{filament_weight}", str(Application.getInstance().getPrintInformation().materialWeights))
replaced = replaced.replace("{filament_cost}", str(Application.getInstance().getPrintInformation().materialCosts))
replaced = replaced.replace("{jobname}", str(Application.getInstance().getPrintInformation().jobName))
self._scene.gcode_list[self._scene.gcode_list.index(line)] = replaced
self._slicing = False
self._need_slicing = False
Logger.log("d", "Slicing took %s seconds", time() - self._slice_start_time )

View file

@ -4,6 +4,7 @@
import numpy
from string import Formatter
from enum import IntEnum
import time
from UM.Job import Job
from UM.Application import Application
@ -247,8 +248,18 @@ class StartSliceJob(Job):
Job.yieldThread()
start_gcode = settings["machine_start_gcode"]
settings["material_bed_temp_prepend"] = "{material_bed_temperature}" not in start_gcode #Pre-compute material material_bed_temp_prepend and material_print_temp_prepend
settings["material_print_temp_prepend"] = "{material_print_temperature}" not in start_gcode
#Pre-compute material material_bed_temp_prepend and material_print_temp_prepend
bed_temperature_settings = {"material_bed_temperature", "material_bed_temperature_layer_0"}
settings["material_bed_temp_prepend"] = all(("{" + setting + "}" not in start_gcode for setting in bed_temperature_settings))
print_temperature_settings = {"material_print_temperature", "material_print_temperature_layer_0", "default_material_print_temperature", "material_initial_print_temperature", "material_final_print_temperature", "material_standby_temperature"}
settings["material_print_temp_prepend"] = all(("{" + setting + "}" not in start_gcode for setting in print_temperature_settings))
settings["print_bed_temperature"] = settings["material_bed_temperature"]
settings["print_temperature"] = settings["material_print_temperature"]
settings["time"] = time.strftime('%H:%M:%S')
settings["date"] = time.strftime('%d-%m-%Y')
settings["day"] = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'][int(time.strftime('%w'))]
for key, value in settings.items(): #Add all submessages for each individual setting.
setting_message = self._slice_message.getMessage("global_settings").addRepeatedMessage("settings")

185
plugins/LayerView/LayerView.qml Normal file → Executable file
View file

@ -7,6 +7,7 @@ import QtQuick.Layouts 1.1
import QtQuick.Controls.Styles 1.1
import UM 1.0 as UM
import Cura 1.0 as Cura
Item
{
@ -58,6 +59,7 @@ Item
anchors.left: parent.left
text: catalog.i18nc("@label","View Mode: Layers")
font.bold: true
color: UM.Theme.getColor("text")
}
Label
@ -75,6 +77,7 @@ Item
text: catalog.i18nc("@label","Color scheme")
visible: !UM.LayerView.compatibilityMode
Layout.fillWidth: true
color: UM.Theme.getColor("text")
}
ListModel // matches LayerView.py
@ -102,6 +105,7 @@ Item
Layout.preferredWidth: UM.Theme.getSize("layerview_row").width
model: layerViewTypes
visible: !UM.LayerView.compatibilityMode
style: UM.Theme.styles.combobox
property int layer_view_type: UM.Preferences.getValue("layerview/layer_view_type")
currentIndex: layer_view_type // index matches type_id
@ -161,106 +165,88 @@ Item
}
Repeater {
model: UM.LayerView.extruderCount
model: Cura.ExtrudersModel{}
CheckBox {
checked: view_settings.extruder_opacities[index] > 0.5 || view_settings.extruder_opacities[index] == undefined || view_settings.extruder_opacities[index] == ""
onClicked: {
view_settings.extruder_opacities[index] = checked ? 1.0 : 0.0
UM.Preferences.setValue("layerview/extruder_opacities", view_settings.extruder_opacities.join("|"));
}
text: catalog.i18nc("@label", "Extruder %1").arg(index + 1)
text: model.name
visible: !UM.LayerView.compatibilityMode
enabled: index + 1 <= 4
Rectangle {
anchors.verticalCenter: parent.verticalCenter
anchors.right: parent.right
width: UM.Theme.getSize("layerview_legend_size").width
height: UM.Theme.getSize("layerview_legend_size").height
color: model.color
border.width: UM.Theme.getSize("default_lining").width
border.color: UM.Theme.getColor("lining")
visible: !view_settings.show_legend
}
Layout.fillWidth: true
Layout.preferredHeight: UM.Theme.getSize("layerview_row").height
Layout.preferredHeight: UM.Theme.getSize("layerview_row").height + UM.Theme.getSize("default_lining").height
Layout.preferredWidth: UM.Theme.getSize("layerview_row").width
style: UM.Theme.styles.checkbox
}
}
Repeater {
model: ListModel {
id: typesLegenModel
Component.onCompleted:
{
typesLegenModel.append({
label: catalog.i18nc("@label", "Show Travels"),
initialValue: view_settings.show_travel_moves,
preference: "layerview/show_travel_moves",
colorId: "layerview_move_combing"
});
typesLegenModel.append({
label: catalog.i18nc("@label", "Show Helpers"),
initialValue: view_settings.show_helpers,
preference: "layerview/show_helpers",
colorId: "layerview_support"
});
typesLegenModel.append({
label: catalog.i18nc("@label", "Show Shell"),
initialValue: view_settings.show_skin,
preference: "layerview/show_skin",
colorId: "layerview_inset_0"
});
typesLegenModel.append({
label: catalog.i18nc("@label", "Show Infill"),
initialValue: view_settings.show_infill,
preference: "layerview/show_infill",
colorId: "layerview_infill"
});
}
}
CheckBox {
checked: view_settings.show_travel_moves
checked: model.initialValue
onClicked: {
UM.Preferences.setValue("layerview/show_travel_moves", checked);
UM.Preferences.setValue(model.preference, checked);
}
text: catalog.i18nc("@label", "Show Travels")
text: label
Rectangle {
anchors.top: parent.top
anchors.topMargin: 2
anchors.verticalCenter: parent.verticalCenter
anchors.right: parent.right
width: UM.Theme.getSize("layerview_legend_size").width
height: UM.Theme.getSize("layerview_legend_size").height
color: UM.Theme.getColor("layerview_move_combing")
color: UM.Theme.getColor(model.colorId)
border.width: UM.Theme.getSize("default_lining").width
border.color: UM.Theme.getColor("lining")
visible: view_settings.show_legend
}
Layout.fillWidth: true
Layout.preferredHeight: UM.Theme.getSize("layerview_row").height
Layout.preferredHeight: UM.Theme.getSize("layerview_row").height + UM.Theme.getSize("default_lining").height
Layout.preferredWidth: UM.Theme.getSize("layerview_row").width
style: UM.Theme.styles.checkbox
}
CheckBox {
checked: view_settings.show_helpers
onClicked: {
UM.Preferences.setValue("layerview/show_helpers", checked);
}
text: catalog.i18nc("@label", "Show Helpers")
Rectangle {
anchors.top: parent.top
anchors.topMargin: 2
anchors.right: parent.right
width: UM.Theme.getSize("layerview_legend_size").width
height: UM.Theme.getSize("layerview_legend_size").height
color: UM.Theme.getColor("layerview_support")
border.width: UM.Theme.getSize("default_lining").width
border.color: UM.Theme.getColor("lining")
visible: view_settings.show_legend
}
Layout.fillWidth: true
Layout.preferredHeight: UM.Theme.getSize("layerview_row").height
Layout.preferredWidth: UM.Theme.getSize("layerview_row").width
}
CheckBox {
checked: view_settings.show_skin
onClicked: {
UM.Preferences.setValue("layerview/show_skin", checked);
}
text: catalog.i18nc("@label", "Show Shell")
Rectangle {
anchors.top: parent.top
anchors.topMargin: 2
anchors.right: parent.right
width: UM.Theme.getSize("layerview_legend_size").width
height: UM.Theme.getSize("layerview_legend_size").height
color: UM.Theme.getColor("layerview_inset_0")
border.width: UM.Theme.getSize("default_lining").width
border.color: UM.Theme.getColor("lining")
visible: view_settings.show_legend
}
Layout.fillWidth: true
Layout.preferredHeight: UM.Theme.getSize("layerview_row").height
Layout.preferredWidth: UM.Theme.getSize("layerview_row").width
}
CheckBox {
checked: view_settings.show_infill
onClicked: {
UM.Preferences.setValue("layerview/show_infill", checked);
}
text: catalog.i18nc("@label", "Show Infill")
Rectangle {
anchors.top: parent.top
anchors.topMargin: 2
anchors.right: parent.right
width: UM.Theme.getSize("layerview_legend_size").width
height: UM.Theme.getSize("layerview_legend_size").height
color: UM.Theme.getColor("layerview_infill")
border.width: UM.Theme.getSize("default_lining").width
border.color: UM.Theme.getColor("lining")
visible: view_settings.show_legend
}
Layout.fillWidth: true
Layout.preferredHeight: UM.Theme.getSize("layerview_row").height
Layout.preferredWidth: UM.Theme.getSize("layerview_row").width
}
CheckBox {
checked: view_settings.only_show_top_layers
onClicked: {
@ -268,6 +254,7 @@ Item
}
text: catalog.i18nc("@label", "Only Show Top Layers")
visible: UM.LayerView.compatibilityMode
style: UM.Theme.styles.checkbox
}
CheckBox {
checked: view_settings.top_layer_count == 5
@ -276,51 +263,43 @@ Item
}
text: catalog.i18nc("@label", "Show 5 Detailed Layers On Top")
visible: UM.LayerView.compatibilityMode
style: UM.Theme.styles.checkbox
}
Label
Repeater {
model: ListModel {
id: typesLegenModelNoCheck
Component.onCompleted:
{
id: topBottomLabel
anchors.left: parent.left
text: catalog.i18nc("@label","Top / Bottom")
typesLegenModelNoCheck.append({
label: catalog.i18nc("@label", "Top / Bottom"),
colorId: "layerview_skin"
});
typesLegenModelNoCheck.append({
label: catalog.i18nc("@label", "Inner Wall"),
colorId: "layerview_inset_x"
});
}
}
Label {
text: label
Rectangle {
anchors.top: parent.top
anchors.topMargin: 2
anchors.verticalCenter: parent.verticalCenter
anchors.right: parent.right
width: UM.Theme.getSize("layerview_legend_size").width
height: UM.Theme.getSize("layerview_legend_size").height
color: UM.Theme.getColor("layerview_skin")
border.width: UM.Theme.getSize("default_lining").width
border.color: UM.Theme.getColor("lining")
}
Layout.fillWidth: true
Layout.preferredHeight: UM.Theme.getSize("layerview_row").height
Layout.preferredWidth: UM.Theme.getSize("layerview_row").width
visible: view_settings.show_legend
}
Label
{
id: innerWallLabel
anchors.left: parent.left
text: catalog.i18nc("@label","Inner Wall")
Rectangle {
anchors.top: parent.top
anchors.topMargin: 2
anchors.right: parent.right
width: UM.Theme.getSize("layerview_legend_size").width
height: UM.Theme.getSize("layerview_legend_size").height
color: UM.Theme.getColor("layerview_inset_x")
color: UM.Theme.getColor(model.colorId)
border.width: UM.Theme.getSize("default_lining").width
border.color: UM.Theme.getColor("lining")
visible: view_settings.show_legend
}
Layout.fillWidth: true
Layout.preferredHeight: UM.Theme.getSize("layerview_row").height
Layout.preferredHeight: UM.Theme.getSize("layerview_row").height + UM.Theme.getSize("default_lining").height
Layout.preferredWidth: UM.Theme.getSize("layerview_row").width
visible: view_settings.show_legend
color: UM.Theme.getColor("text")
}
}
}
Item

View file

@ -26,129 +26,6 @@ Item {
spacing: UM.Theme.getSize("default_margin").height
Row
{
spacing: UM.Theme.getSize("default_margin").width
Label
{
text: catalog.i18nc("@label Followed by extruder selection drop-down.", "Print model with")
anchors.verticalCenter: extruderSelector.verticalCenter
color: UM.Theme.getColor("setting_control_text")
font: UM.Theme.getFont("default")
visible: extruderSelector.visible
}
ComboBox
{
id: extruderSelector
model: Cura.ExtrudersModel
{
id: extrudersModel
onModelChanged: extruderSelector.color = extrudersModel.getItem(extruderSelector.currentIndex).color
}
property string color: extrudersModel.getItem(extruderSelector.currentIndex).color
visible: machineExtruderCount.properties.value > 1
textRole: "name"
width: UM.Theme.getSize("setting_control").width
height: UM.Theme.getSize("section").height
MouseArea
{
anchors.fill: parent
acceptedButtons: Qt.NoButton
onWheel: wheel.accepted = true;
}
style: ComboBoxStyle
{
background: Rectangle
{
color:
{
if(extruderSelector.hovered || base.activeFocus)
{
return UM.Theme.getColor("setting_control_highlight");
}
else
{
return UM.Theme.getColor("setting_control");
}
}
border.width: UM.Theme.getSize("default_lining").width
border.color: UM.Theme.getColor("setting_control_border")
}
label: Item
{
Rectangle
{
id: swatch
height: UM.Theme.getSize("setting_control").height / 2
width: height
anchors.left: parent.left
anchors.leftMargin: UM.Theme.getSize("default_lining").width
anchors.verticalCenter: parent.verticalCenter
color: extruderSelector.color
border.width: UM.Theme.getSize("default_lining").width
border.color: !enabled ? UM.Theme.getColor("setting_control_disabled_border") : UM.Theme.getColor("setting_control_border")
}
Label
{
anchors.left: swatch.right
anchors.leftMargin: UM.Theme.getSize("default_lining").width
anchors.right: downArrow.left
anchors.rightMargin: UM.Theme.getSize("default_lining").width
anchors.verticalCenter: parent.verticalCenter
text: extruderSelector.currentText
font: UM.Theme.getFont("default")
color: !enabled ? UM.Theme.getColor("setting_control_disabled_text") : UM.Theme.getColor("setting_control_text")
elide: Text.ElideRight
verticalAlignment: Text.AlignVCenter
}
UM.RecolorImage
{
id: downArrow
anchors.right: parent.right
anchors.rightMargin: UM.Theme.getSize("default_lining").width * 2
anchors.verticalCenter: parent.verticalCenter
source: UM.Theme.getIcon("arrow_bottom")
width: UM.Theme.getSize("standard_arrow").width
height: UM.Theme.getSize("standard_arrow").height
sourceSize.width: width + 5
sourceSize.height: width + 5
color: UM.Theme.getColor("setting_control_text")
}
}
}
onActivated:
{
UM.ActiveTool.setProperty("SelectedActiveExtruder", extrudersModel.getItem(index).id);
extruderSelector.color = extrudersModel.getItem(index).color;
}
onModelChanged: updateCurrentIndex();
function updateCurrentIndex()
{
for(var i = 0; i < extrudersModel.rowCount(); ++i)
{
if(extrudersModel.getItem(i).id == UM.ActiveTool.properties.getValue("SelectedActiveExtruder"))
{
extruderSelector.currentIndex = i;
extruderSelector.color = extrudersModel.getItem(i).color;
return;
}
}
extruderSelector.currentIndex = -1;
}
}
}
Column
{
// This is to ensure that the panel is first increasing in size up to 200 and then shows a scrollbar.

View file

@ -112,4 +112,4 @@ class PerObjectSettingsTool(Tool):
self._single_model_selected = False # Group is selected, so tool needs to be disabled
else:
self._single_model_selected = True
Application.getInstance().getController().toolEnabledChanged.emit(self._plugin_id, (self._advanced_mode or self._multi_extrusion) and self._single_model_selected)
Application.getInstance().getController().toolEnabledChanged.emit(self._plugin_id, self._advanced_mode and self._single_model_selected)

View file

@ -10,6 +10,10 @@ _removed_settings = { #Settings that were removed in 2.5.
"start_layers_at_same_position"
}
_split_settings = { #These settings should be copied to all settings it was split into.
"support_interface_line_distance": {"support_roof_line_distance", "support_bottom_line_distance"}
}
## A collection of functions that convert the configuration of the user in Cura
# 2.4 to a configuration for Cura 2.5.
#
@ -42,8 +46,16 @@ class VersionUpgrade24to25(VersionUpgrade):
#Remove settings from the visible_settings.
if parser.has_section("general") and "visible_settings" in parser["general"]:
visible_settings = parser["general"]["visible_settings"].split(";")
visible_settings = filter(lambda setting: setting not in _removed_settings, visible_settings)
parser["general"]["visible_settings"] = ";".join(visible_settings)
new_visible_settings = []
for setting in visible_settings:
if setting in _removed_settings:
continue #Skip.
if setting in _split_settings:
for replaced_setting in _split_settings[setting]:
new_visible_settings.append(replaced_setting)
continue #Don't add the original.
new_visible_settings.append(setting) #No special handling, so just add the original visible setting back.
parser["general"]["visible_settings"] = ";".join(new_visible_settings)
#Change the version number in the file.
if parser.has_section("general"): #It better have!
@ -66,6 +78,10 @@ class VersionUpgrade24to25(VersionUpgrade):
if parser.has_section("values"):
for removed_setting in (_removed_settings & parser["values"].keys()): #Both in keys that need to be removed and in keys present in the file.
del parser["values"][removed_setting]
for replaced_setting in (_split_settings.keys() & parser["values"].keys()):
for replacement in _split_settings[replaced_setting]:
parser["values"][replacement] = parser["values"][replaced_setting] #Copy to replacement before removing the original!
del replaced_setting
#Change the version number in the file.
if parser.has_section("general"):

View file

@ -746,7 +746,7 @@
"support_interface_line_width":
{
"label": "Support Interface Line Width",
"description": "Width of a single support interface line.",
"description": "Width of a single line of support roof or floor.",
"unit": "mm",
"default_value": 0.4,
"minimum_value": "0.001",
@ -757,8 +757,43 @@
"limit_to_extruder": "support_interface_extruder_nr",
"value": "line_width",
"settable_per_mesh": false,
"settable_per_extruder": true,
"children":
{
"support_roof_line_width":
{
"label": "Support Roof Line Width",
"description": "Width of a single support roof line.",
"unit": "mm",
"default_value": 0.4,
"minimum_value": "0.001",
"minimum_value_warning": "0.4 * machine_nozzle_size",
"maximum_value_warning": "2 * machine_nozzle_size",
"type": "float",
"enabled": "support_enable and support_roof_enable",
"limit_to_extruder": "support_roof_extruder_nr",
"value": "support_interface_line_width",
"settable_per_mesh": false,
"settable_per_extruder": true
},
"support_bottom_line_width":
{
"label": "Support Floor Line Width",
"description": "Width of a single support floor line.",
"unit": "mm",
"default_value": 0.4,
"minimum_value": "0.001",
"minimum_value_warning": "0.4 * machine_nozzle_size",
"maximum_value_warning": "2 * machine_nozzle_size",
"type": "float",
"enabled": "support_enable and support_bottom_enable",
"limit_to_extruder": "support_bottom_extruder_nr",
"value": "support_interface_line_width",
"settable_per_mesh": false,
"settable_per_extruder": true
}
}
},
"prime_tower_line_width":
{
"label": "Prime Tower Line Width",
@ -1923,7 +1958,7 @@
"speed_support_interface":
{
"label": "Support Interface Speed",
"description": "The speed at which the roofs and bottoms of support are printed. Printing the them at lower speeds can improve overhang quality.",
"description": "The speed at which the roofs and floors of support are printed. Printing them at lower speeds can improve overhang quality.",
"unit": "mm/s",
"type": "float",
"default_value": 40,
@ -1934,7 +1969,42 @@
"limit_to_extruder": "support_interface_extruder_nr",
"value": "speed_support / 1.5",
"settable_per_mesh": false,
"settable_per_extruder": true,
"children":
{
"speed_support_roof":
{
"label": "Support Roof Speed",
"description": "The speed at which the roofs of support are printed. Printing them at lower speeds can improve overhang quality.",
"unit": "mm/s",
"type": "float",
"default_value": 40,
"minimum_value": "0.1",
"maximum_value": "math.sqrt(machine_max_feedrate_x ** 2 + machine_max_feedrate_y ** 2)",
"maximum_value_warning": "150",
"enabled": "extruderValue(support_roof_extruder_nr, 'support_roof_enable') and support_enable",
"limit_to_extruder": "support_roof_extruder_nr",
"value": "speed_support_interface",
"settable_per_mesh": false,
"settable_per_extruder": true
},
"speed_support_bottom":
{
"label": "Support Floor Speed",
"description": "The speed at which the floor of support is printed. Printing it at lower speed can improve adhesion of support on top of your model.",
"unit": "mm/s",
"type": "float",
"default_value": 40,
"minimum_value": "0.1",
"maximum_value": "math.sqrt(machine_max_feedrate_x ** 2 + machine_max_feedrate_y ** 2)",
"maximum_value_warning": "150",
"enabled": "extruderValue(support_bottom_extruder_nr, 'support_bottom_enable') and support_enable",
"limit_to_extruder": "support_bottom_extruder_nr",
"value": "speed_support_interface",
"settable_per_mesh": false,
"settable_per_extruder": true
}
}
}
}
},
@ -2209,7 +2279,7 @@
"acceleration_support_interface":
{
"label": "Support Interface Acceleration",
"description": "The acceleration with which the roofs and bottoms of support are printed. Printing them at lower accelerations can improve overhang quality.",
"description": "The acceleration with which the roofs and floors of support are printed. Printing them at lower acceleration can improve overhang quality.",
"unit": "mm/s²",
"type": "float",
"default_value": 3000,
@ -2220,7 +2290,42 @@
"enabled": "resolveOrValue('acceleration_enabled') and extruderValue(support_interface_extruder_nr, 'support_interface_enable') and support_enable",
"limit_to_extruder": "support_interface_extruder_nr",
"settable_per_mesh": false,
"settable_per_extruder": true,
"children":
{
"acceleration_support_roof":
{
"label": "Support Roof Acceleration",
"description": "The acceleration with which the roofs of support are printed. Printing them at lower acceleration can improve overhang quality.",
"unit": "mm/s²",
"type": "float",
"default_value": 3000,
"value": "acceleration_support_interface",
"minimum_value": "0.1",
"minimum_value_warning": "100",
"maximum_value_warning": "10000",
"enabled": "resolveOrValue('acceleration_enabled') and extruderValue(support_roof_extruder_nr, 'support_roof_enable') and support_enable",
"limit_to_extruder": "support_roof_extruder_nr",
"settable_per_mesh": false,
"settable_per_extruder": true
},
"acceleration_support_bottom":
{
"label": "Support Floor Acceleration",
"description": "The acceleration with which the floors of support are printed. Printing them at lower acceleration can improve adhesion of support on top of your model.",
"unit": "mm/s²",
"type": "float",
"default_value": 3000,
"value": "acceleration_support_interface",
"minimum_value": "0.1",
"minimum_value_warning": "100",
"maximum_value_warning": "10000",
"enabled": "resolveOrValue('acceleration_enabled') and extruderValue(support_bottom_extruder_nr, 'support_bottom_enable') and support_enable",
"limit_to_extruder": "support_bottom_extruder_nr",
"settable_per_mesh": false,
"settable_per_extruder": true
}
}
}
}
},
@ -2440,7 +2545,7 @@
"jerk_support_interface":
{
"label": "Support Interface Jerk",
"description": "The maximum instantaneous velocity change with which the roofs and bottoms of support are printed.",
"description": "The maximum instantaneous velocity change with which the roofs and floors of support are printed.",
"unit": "mm/s",
"type": "float",
"default_value": 20,
@ -2450,7 +2555,42 @@
"enabled": "resolveOrValue('jerk_enabled') and extruderValue(support_interface_extruder_nr, 'support_interface_enable') and support_enable",
"limit_to_extruder": "support_interface_extruder_nr",
"settable_per_mesh": false,
"settable_per_extruder": true,
"children":
{
"jerk_support_roof":
{
"label": "Support Roof Jerk",
"description": "The maximum instantaneous velocity change with which the roofs of support are printed.",
"unit": "mm/s",
"type": "float",
"default_value": 20,
"value": "jerk_support_interface",
"minimum_value": "0.1",
"minimum_value_warning": "5",
"maximum_value_warning": "50",
"enabled": "resolveOrValue('jerk_enabled') and extruderValue(support_roof_extruder_nr, 'support_roof_enable') and support_enable",
"limit_to_extruder": "support_roof_extruder_nr",
"settable_per_mesh": false,
"settable_per_extruder": true
},
"jerk_support_bottom":
{
"label": "Support Floor Jerk",
"description": "The maximum instantaneous velocity change with which the floors of support are printed.",
"unit": "mm/s",
"type": "float",
"default_value": 20,
"value": "jerk_support_interface",
"minimum_value": "0.1",
"minimum_value_warning": "5",
"maximum_value_warning": "50",
"enabled": "resolveOrValue('jerk_enabled') and extruderValue(support_bottom_extruder_nr, 'support_bottom_enable') and support_enable",
"limit_to_extruder": "support_bottom_extruder_nr",
"settable_per_mesh": false,
"settable_per_extruder": true
}
}
}
}
},
@ -2878,13 +3018,38 @@
"support_interface_extruder_nr":
{
"label": "Support Interface Extruder",
"description": "The extruder train to use for printing the roofs and bottoms of the support. This is used in multi-extrusion.",
"description": "The extruder train to use for printing the roofs and floors of the support. This is used in multi-extrusion.",
"type": "extruder",
"default_value": "0",
"value": "support_extruder_nr",
"enabled": "support_enable and machine_extruder_count > 1",
"settable_per_mesh": false,
"settable_per_extruder": false,
"children":
{
"support_roof_extruder_nr":
{
"label": "Support Roof Extruder",
"description": "The extruder train to use for printing the roofs of the support. This is used in multi-extrusion.",
"type": "extruder",
"default_value": "0",
"value": "support_interface_extruder_nr",
"enabled": "support_enable and machine_extruder_count > 1",
"settable_per_mesh": false,
"settable_per_extruder": false
},
"support_bottom_extruder_nr":
{
"label": "Support Floor Extruder",
"description": "The extruder train to use for printing the floors of the support. This is used in multi-extrusion.",
"type": "extruder",
"default_value": "0",
"value": "support_interface_extruder_nr",
"enabled": "support_enable and machine_extruder_count > 1",
"settable_per_mesh": false,
"settable_per_extruder": false
}
}
}
}
},
@ -2914,7 +3079,7 @@
"maximum_value": "90",
"maximum_value_warning": "80",
"default_value": 50,
"limit_to_extruder": "support_interface_extruder_nr if support_interface_enable else support_infill_extruder_nr",
"limit_to_extruder": "support_roof_extruder_nr if support_roof_enable else support_infill_extruder_nr",
"enabled": "support_enable",
"settable_per_mesh": true
},
@ -3006,7 +3171,7 @@
"type": "float",
"enabled": "support_enable",
"value": "extruderValue(support_extruder_nr, 'support_z_distance')",
"limit_to_extruder": "support_interface_extruder_nr if support_interface_enable else support_infill_extruder_nr",
"limit_to_extruder": "support_roof_extruder_nr if support_roof_enable else support_infill_extruder_nr",
"settable_per_mesh": true
},
"support_bottom_distance":
@ -3018,7 +3183,7 @@
"maximum_value_warning": "machine_nozzle_size",
"default_value": 0.1,
"value": "extruderValue(support_extruder_nr, 'support_z_distance') if resolveOrValue('support_type') == 'everywhere' else 0",
"limit_to_extruder": "support_interface_extruder_nr if support_interface_enable else support_infill_extruder_nr",
"limit_to_extruder": "support_bottom_extruder_nr if support_bottom_enable else support_infill_extruder_nr",
"type": "float",
"enabled": "support_enable and resolveOrValue('support_type') == 'everywhere'",
"settable_per_mesh": true
@ -3070,16 +3235,29 @@
"support_bottom_stair_step_height":
{
"label": "Support Stair Step Height",
"description": "The height of the steps of the stair-like bottom of support resting on the model. A low value makes the support harder to remove, but too high values can lead to unstable support structures.",
"description": "The height of the steps of the stair-like bottom of support resting on the model. A low value makes the support harder to remove, but too high values can lead to unstable support structures. Set to zero to turn off the stair-like behaviour.",
"unit": "mm",
"type": "float",
"default_value": 0.3,
"limit_to_extruder": "support_interface_extruder_nr if support_interface_enable else support_infill_extruder_nr",
"limit_to_extruder": "support_bottom_extruder_nr if support_bottom_enable else support_infill_extruder_nr",
"minimum_value": "0",
"maximum_value_warning": "1.0",
"enabled": "support_enable",
"settable_per_mesh": true
},
"support_bottom_stair_step_width":
{
"label": "Support Stair Step Maximum Width",
"description": "The maximum width of the steps of the stair-like bottom of support resting on the model. A low value makes the support harder to remove, but too high values can lead to unstable support structures.",
"unit": "mm",
"type": "float",
"default_value": 5.0,
"limit_to_extruder": "support_interface_extruder_nr if support_interface_enable else support_infill_extruder_nr",
"minimum_value": "0",
"maximum_value_warning": "10.0",
"enabled": "support_enable",
"settable_per_mesh": true
},
"support_join_distance":
{
"label": "Support Join Distance",
@ -3114,8 +3292,33 @@
"default_value": false,
"limit_to_extruder": "support_interface_extruder_nr",
"enabled": "support_enable",
"settable_per_mesh": true,
"children":
{
"support_roof_enable":
{
"label": "Enable Support Roof",
"description": "Generate a dense slab of material between the top of support and the model. This will create a skin between the model and support.",
"type": "bool",
"default_value": false,
"value": "support_interface_enable",
"limit_to_extruder": "support_roof_extruder_nr",
"enabled": "support_enable",
"settable_per_mesh": true
},
"support_bottom_enable":
{
"label": "Enable Support Floor",
"description": "Generate a dense slab of material between the bottom of the support and the model. This will create a skin between the model and support.",
"type": "bool",
"default_value": false,
"value": "support_interface_enable",
"limit_to_extruder": "support_bottom_extruder_nr",
"enabled": "support_enable",
"settable_per_mesh": true
}
}
},
"support_interface_height":
{
"label": "Support Interface Thickness",
@ -3141,32 +3344,31 @@
"minimum_value": "0",
"minimum_value_warning": "0.2 + resolveOrValue('layer_height')",
"maximum_value_warning": "10",
"value": "extruderValue(support_interface_extruder_nr, 'support_interface_height')",
"limit_to_extruder": "support_interface_extruder_nr",
"enabled": "extruderValue(support_interface_extruder_nr, 'support_interface_enable') and support_enable",
"value": "extruderValue(support_roof_extruder_nr, 'support_interface_height')",
"limit_to_extruder": "support_roof_extruder_nr",
"enabled": "extruderValue(support_roof_extruder_nr, 'support_roof_enable') and support_enable",
"settable_per_mesh": true
},
"support_bottom_height":
{
"label": "Support Bottom Thickness",
"description": "The thickness of the support bottoms. This controls the number of dense layers are printed on top of places of a model on which support rests.",
"label": "Support Floor Thickness",
"description": "The thickness of the support floors. This controls the number of dense layers that are printed on top of places of a model on which support rests.",
"unit": "mm",
"type": "float",
"default_value": 1,
"value": "extruderValue(support_interface_extruder_nr, 'support_interface_height')",
"value": "extruderValue(support_bottom_extruder_nr, 'support_interface_height')",
"minimum_value": "0",
"minimum_value_warning": "min(0.2 + resolveOrValue('layer_height'), extruderValue(support_interface_extruder_nr, 'support_bottom_stair_step_height'))",
"minimum_value_warning": "min(0.2 + resolveOrValue('layer_height'), extruderValue(support_bottom_extruder_nr, 'support_bottom_stair_step_height'))",
"maximum_value_warning": "10",
"limit_to_extruder": "support_interface_extruder_nr",
"enabled": "extruderValue(support_interface_extruder_nr, 'support_interface_enable') and support_enable",
"limit_to_extruder": "support_bottom_extruder_nr",
"enabled": "extruderValue(support_bottom_extruder_nr, 'support_bottom_enable') and support_enable",
"settable_per_mesh": true
}
}
},
"support_interface_skip_height":
{
"support_interface_skip_height": {
"label": "Support Interface Resolution",
"description": "When checking where there's model above the support, take steps of the given height. Lower values will slice slower, while higher values may cause normal support to be printed in some places where there should have been support interface.",
"description": "When checking where there's model above and below the support, take steps of the given height. Lower values will slice slower, while higher values may cause normal support to be printed in some places where there should have been support interface.",
"unit": "mm",
"type": "float",
"default_value": 0.3,
@ -3179,7 +3381,7 @@
"support_interface_density":
{
"label": "Support Interface Density",
"description": "Adjusts the density of the roofs and bottoms of the support structure. A higher value results in better overhangs, but the supports are harder to remove.",
"description": "Adjusts the density of the roofs and floors of the support structure. A higher value results in better overhangs, but the supports are harder to remove.",
"unit": "%",
"type": "float",
"default_value": 100,
@ -3191,23 +3393,72 @@
"settable_per_extruder": true,
"children":
{
"support_interface_line_distance":
"support_roof_density":
{
"label": "Support Interface Line Distance",
"description": "Distance between the printed support interface lines. This setting is calculated by the Support Interface Density, but can be adjusted separately.",
"label": "Support Roof Density",
"description": "The density of the roofs of the support structure. A higher value results in better overhangs, but the supports are harder to remove.",
"unit": "%",
"type": "float",
"default_value": 100,
"minimum_value": "0",
"maximum_value": "100",
"limit_to_extruder": "support_roof_extruder_nr",
"enabled": "extruderValue(support_roof_extruder_nr, 'support_roof_enable') and support_enable",
"settable_per_mesh": false,
"settable_per_extruder": true,
"children":
{
"support_roof_line_distance":
{
"label": "Support Roof Line Distance",
"description": "Distance between the printed support roof lines. This setting is calculated by the Support Roof Density, but can be adjusted separately.",
"unit": "mm",
"type": "float",
"default_value": 0.4,
"minimum_value": "0",
"minimum_value_warning": "support_interface_line_width - 0.0001",
"value": "0 if support_interface_density == 0 else (support_interface_line_width * 100) / support_interface_density * (2 if support_interface_pattern == 'grid' else (3 if support_interface_pattern == 'triangles' else 1))",
"limit_to_extruder": "support_interface_extruder_nr",
"enabled": "extruderValue(support_interface_extruder_nr, 'support_interface_enable') and support_enable",
"minimum_value_warning": "support_roof_line_width - 0.0001",
"value": "0 if support_roof_density == 0 else (support_roof_line_width * 100) / support_roof_density * (2 if support_roof_pattern == 'grid' else (3 if support_roof_pattern == 'triangles' else 1))",
"limit_to_extruder": "support_roof_extruder_nr",
"enabled": "extruderValue(support_roof_extruder_nr, 'support_roof_enable') and support_enable",
"settable_per_mesh": false,
"settable_per_extruder": true
}
}
},
"support_bottom_density":
{
"label": "Support Floor Density",
"description": "The density of the floors of the support structure. A higher value results in better adhesion of the support on top of the model.",
"unit": "%",
"type": "float",
"default_value": 100,
"minimum_value": "0",
"maximum_value": "100",
"limit_to_extruder": "support_bottom_extruder_nr",
"enabled": "extruderValue(support_bottom_extruder_nr, 'support_bottom_enable') and support_enable",
"settable_per_mesh": false,
"settable_per_extruder": true,
"children":
{
"support_bottom_line_distance":
{
"label": "Support Floor Line Distance",
"description": "Distance between the printed support floor lines. This setting is calculated by the Support Floor Density, but can be adjusted separately.",
"unit": "mm",
"type": "float",
"default_value": 0.4,
"minimum_value": "0",
"minimum_value_warning": "support_bottom_line_width - 0.0001",
"value": "0 if support_bottom_density == 0 else (support_bottom_line_width * 100) / support_bottom_density * (2 if support_bottom_pattern == 'grid' else (3 if support_bottom_pattern == 'triangles' else 1))",
"limit_to_extruder": "support_bottom_extruder_nr",
"enabled": "extruderValue(support_bottom_extruder_nr, 'support_bottom_enable') and support_enable",
"settable_per_mesh": false,
"settable_per_extruder": true
}
}
}
}
},
"support_interface_pattern":
{
"label": "Support Interface Pattern",
@ -3226,8 +3477,53 @@
"limit_to_extruder": "support_interface_extruder_nr",
"enabled": "extruderValue(support_interface_extruder_nr, 'support_interface_enable') and support_enable",
"settable_per_mesh": false,
"settable_per_extruder": true,
"children":
{
"support_roof_pattern":
{
"label": "Support Roof Pattern",
"description": "The pattern with which the roofs of the support are printed.",
"type": "enum",
"options":
{
"lines": "Lines",
"grid": "Grid",
"triangles": "Triangles",
"concentric": "Concentric",
"concentric_3d": "Concentric 3D",
"zigzag": "Zig Zag"
},
"default_value": "concentric",
"value": "support_interface_pattern",
"limit_to_extruder": "support_roof_extruder_nr",
"enabled": "extruderValue(support_roof_extruder_nr, 'support_roof_enable') and support_enable",
"settable_per_mesh": false,
"settable_per_extruder": true
},
"support_bottom_pattern":
{
"label": "Support Floor Pattern",
"description": "The pattern with which the floors of the support are printed.",
"type": "enum",
"options":
{
"lines": "Lines",
"grid": "Grid",
"triangles": "Triangles",
"concentric": "Concentric",
"concentric_3d": "Concentric 3D",
"zigzag": "Zig Zag"
},
"default_value": "concentric",
"value": "support_interface_pattern",
"limit_to_extruder": "support_bottom_extruder_nr",
"enabled": "extruderValue(support_bottom_extruder_nr, 'support_bottom_enable') and support_enable",
"settable_per_mesh": false,
"settable_per_extruder": true
}
}
},
"support_use_towers":
{
"label": "Use Towers",

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
Text
Label
{
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

@ -0,0 +1,80 @@
// Copyright (c) 2017 Ultimaker B.V.
// Cura is released under the terms of the AGPLv3 or higher.
import QtQuick 2.2
import QtQuick.Controls 1.1
import UM 1.2 as UM
import Cura 1.0 as Cura
Button
{
id: base
property var extruder;
text: catalog.i18ncp("@label", "Print Selected Model with %1", "Print Selected Models With %1", UM.Selection.selectionCount).arg(extruder.name)
style: UM.Theme.styles.tool_button;
iconSource: checked ? UM.Theme.getIcon("material_selected") : UM.Theme.getIcon("material_not_selected");
checked: ExtruderManager.selectedObjectExtruders.indexOf(extruder.id) != -1
enabled: UM.Selection.hasSelection
property color customColor: base.hovered ? UM.Theme.getColor("button_hover") : UM.Theme.getColor("button");
Rectangle
{
anchors.fill: parent
anchors.margins: UM.Theme.getSize("default_lining").width;
color: "transparent"
border.width: base.checked ? UM.Theme.getSize("default_lining").width : 0;
border.color: UM.Theme.getColor("button_text")
}
Item
{
anchors
{
right: parent.right;
top: parent.top;
margins: UM.Theme.getSize("default_lining").width * 3
}
width: UM.Theme.getSize("default_margin").width
height: UM.Theme.getSize("default_margin").height
Text
{
anchors.centerIn: parent;
text: index + 1;
color: parent.enabled ? UM.Theme.getColor("button_text") : UM.Theme.getColor("button_disabled_text")
font: UM.Theme.getFont("default_bold");
}
}
Rectangle
{
anchors
{
left: parent.left;
top: parent.top;
margins: UM.Theme.getSize("default_lining").width * 3
}
color: model.color
width: UM.Theme.getSize("default_margin").width
height: UM.Theme.getSize("default_margin").height
border.width: UM.Theme.getSize("default_lining").width
border.color: UM.Theme.getColor("lining");
}
onClicked:
{
forceActiveFocus() //First grab focus, so all the text fields are updated
CuraActions.setExtruderForSelection(extruder.id);
}
}

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(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

@ -25,6 +25,17 @@ UM.PreferencesPage
}
}
function setDefaultTheme(defaultThemeCode)
{
for(var i = 0; i < themeList.count; i++)
{
if (themeComboBox.model.get(i).code == defaultThemeCode)
{
themeComboBox.currentIndex = i
}
}
}
function setDefaultDiscardOrKeepProfile(code)
{
for (var i = 0; i < choiceOnProfileOverrideDropDownButton.model.count; i++)
@ -55,6 +66,10 @@ UM.PreferencesPage
var defaultLanguage = UM.Preferences.getValue("general/language")
setDefaultLanguage(defaultLanguage)
UM.Preferences.resetPreference("general/theme")
var defaultTheme = UM.Preferences.getValue("general/theme")
setDefaultTheme(defaultTheme)
UM.Preferences.resetPreference("physics/automatic_push_free")
pushFreeCheckbox.checked = boolCheck(UM.Preferences.getValue("physics/automatic_push_free"))
UM.Preferences.resetPreference("physics/automatic_drop_down")
@ -95,6 +110,8 @@ UM.PreferencesPage
width: parent.width
height: parent.height
flickableItem.flickableDirection: Flickable.VerticalFlick;
Column
{
//: Model used to check if a plugin exists
@ -109,9 +126,11 @@ UM.PreferencesPage
text: catalog.i18nc("@label","Interface")
}
Row
GridLayout
{
spacing: UM.Theme.getSize("default_margin").width
id: interfaceGrid
columns: 4
Label
{
id: languageLabel
@ -172,22 +191,75 @@ UM.PreferencesPage
{
id: currencyLabel
text: catalog.i18nc("@label","Currency:")
anchors.verticalCenter: languageComboBox.verticalCenter
anchors.verticalCenter: currencyField.verticalCenter
}
TextField
{
id: currencyField
text: UM.Preferences.getValue("cura/currency")
onTextChanged: UM.Preferences.setValue("cura/currency", text)
}
Label
{
id: themeLabel
text: catalog.i18nc("@label","Theme:")
anchors.verticalCenter: themeComboBox.verticalCenter
}
ComboBox
{
id: themeComboBox
model: ListModel
{
id: themeList
Component.onCompleted: {
append({ text: catalog.i18nc("@item:inlistbox", "Ultimaker"), code: "cura" })
}
}
currentIndex:
{
var code = UM.Preferences.getValue("general/theme");
for(var i = 0; i < themeList.count; ++i)
{
if(model.get(i).code == code)
{
return i
}
}
}
onActivated: UM.Preferences.setValue("general/theme", model.get(index).code)
Component.onCompleted:
{
// Because ListModel is stupid and does not allow using qsTr() for values.
for(var i = 0; i < themeList.count; ++i)
{
themeList.setProperty(i, "text", catalog.i18n(themeList.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
//: Language change warning
text: catalog.i18nc("@label", "You will need to restart the application for language changes to have effect.")
text: catalog.i18nc("@label", "You will need to restart the application for these changes to have effect.")
wrapMode: Text.WordWrap
font.italic: true
}
@ -209,7 +281,6 @@ UM.PreferencesPage
CheckBox
{
id: autoSliceCheckbox
checked: boolCheck(UM.Preferences.getValue("general/auto_slice"))
onClicked: UM.Preferences.setValue("general/auto_slice", checked)

View file

@ -408,18 +408,34 @@ Rectangle
}
ExclusiveGroup { id: modeMenuGroup; }
Text
Label
{
id: toggleLeftText
anchors.right: modeToggleSwitch.left
anchors.rightMargin: UM.Theme.getSize("toggle_button_text_anchoring_margin").width
anchors.rightMargin: UM.Theme.getSize("default_margin").width
anchors.verticalCenter: parent.verticalCenter
text: ""
color: UM.Theme.getColor("toggle_active_text")
color:
{
if(toggleLeftTextMouseArea.containsMouse)
{
return UM.Theme.getColor("mode_switch_text_hover");
}
else if(!modeToggleSwitch.checked)
{
return UM.Theme.getColor("mode_switch_text_checked");
}
else
{
return UM.Theme.getColor("mode_switch_text");
}
}
font: UM.Theme.getFont("default")
MouseArea
{
id: toggleLeftTextMouseArea
hoverEnabled: true
anchors.fill: parent
onClicked:
{
@ -438,9 +454,19 @@ Rectangle
id: modeToggleSwitch
checked: false
anchors.right: toggleRightText.left
anchors.rightMargin: UM.Theme.getSize("toggle_button_text_anchoring_margin").width
anchors.rightMargin: UM.Theme.getSize("default_margin").width
anchors.verticalCenter: parent.verticalCenter
property bool _hovered: modeToggleSwitchMouseArea.containsMouse || toggleLeftTextMouseArea.containsMouse || toggleRightTextMouseArea.containsMouse
MouseArea
{
id: modeToggleSwitchMouseArea
anchors.fill: parent
hoverEnabled: true
acceptedButtons: Qt.NoButton
}
onClicked:
{
var index = 0;
@ -457,20 +483,36 @@ Rectangle
UM.Preferences.setValue("cura/active_mode", index);
}
style: UM.Theme.styles.toggle_button
style: UM.Theme.styles.mode_switch
}
Text
Label
{
id: toggleRightText
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
text: ""
color: UM.Theme.getColor("toggle_active_text")
color:
{
if(toggleRightTextMouseArea.containsMouse)
{
return UM.Theme.getColor("mode_switch_text_hover");
}
else if(modeToggleSwitch.checked)
{
return UM.Theme.getColor("mode_switch_text_checked");
}
else
{
return UM.Theme.getColor("mode_switch_text");
}
}
font: UM.Theme.getFont("default")
MouseArea
{
id: toggleRightTextMouseArea
hoverEnabled: true
anchors.fill: parent
onClicked:
{

View file

@ -240,6 +240,8 @@ Item
CheckBox
{
id: enableSupportCheckBox
property alias _hovered: enableSupportMouseArea.containsMouse
anchors.top: parent.top
anchors.left: enableSupportLabel.right
anchors.leftMargin: UM.Theme.getSize("default_margin").width

View file

@ -6,28 +6,33 @@ import QtQuick.Controls 1.1
import QtQuick.Controls.Styles 1.1
import QtQuick.Layouts 1.1
import UM 1.0 as UM
import UM 1.2 as UM
import Cura 1.0 as Cura
Item {
Item
{
id: base;
width: buttons.width;
height: buttons.height
property int activeY
ColumnLayout {
Column
{
id: buttons;
anchors.bottom: parent.bottom;
anchors.left: parent.left;
spacing: UM.Theme.getSize("button_lining").width
Repeater {
Repeater
{
id: repeat
model: UM.ToolModel { }
Button {
Button
{
text: model.name
iconSource: UM.Theme.getIcon(model.icon);
@ -45,9 +50,11 @@ Item {
}
//Workaround since using ToolButton"s onClicked would break the binding of the checked property, instead
//just catch the click so we do not trigger that behaviour.
MouseArea {
MouseArea
{
anchors.fill: parent;
onClicked: {
onClicked:
{
forceActiveFocus() //First grab focus, so all the text fields are updated
if(parent.checked)
{
@ -61,9 +68,19 @@ Item {
}
}
}
Item { height: UM.Theme.getSize("default_margin").height; width: 1; visible: extruders.count > 0 }
Repeater
{
id: extruders
model: Cura.ExtrudersModel { id: extrudersModel }
ExtruderButton { extruder: model }
}
}
UM.PointingRectangle {
UM.PointingRectangle
{
id: panelBorder;
anchors.left: parent.right;
@ -75,7 +92,8 @@ Item {
target: Qt.point(parent.right, base.activeY + UM.Theme.getSize("button").height/2)
arrowSize: UM.Theme.getSize("default_arrow").width
width: {
width:
{
if (panel.item && panel.width > 0){
return Math.max(panel.width + 2 * UM.Theme.getSize("default_margin").width)
}
@ -90,7 +108,8 @@ Item {
color: UM.Theme.getColor("lining");
UM.PointingRectangle {
UM.PointingRectangle
{
id: panelBackground;
color: UM.Theme.getColor("tool_panel_background");
@ -105,7 +124,8 @@ Item {
}
}
Loader {
Loader
{
id: panel
x: UM.Theme.getSize("default_margin").width;
@ -116,6 +136,8 @@ Item {
}
}
// This rectangle displays the information about the current angle etc. when
// dragging a tool handle.
Rectangle
{
x: -base.x + base.mouseX + UM.Theme.getSize("default_margin").width

View file

@ -0,0 +1,77 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="30"
height="30"
viewBox="0 0 30 30"
version="1.1"
id="svg4668"
sodipodi:docname="material_not_selected.svg"
inkscape:version="0.92.1 r">
<metadata
id="metadata4672">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title>Artboard 3</dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1266"
inkscape:window-height="1411"
id="namedview4670"
showgrid="false"
inkscape:pagecheckerboard="true"
inkscape:zoom="9.0769231"
inkscape:cx="-5.7118644"
inkscape:cy="13"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="0"
inkscape:current-layer="svg4668" />
<!-- Generator: Sketch 43.1 (39012) - http://www.bohemiancoding.com/sketch -->
<title
id="title4657">Artboard 3</title>
<desc
id="desc4659">Created with Sketch.</desc>
<defs
id="defs4661" />
<g
id="Feature-apply-material-to-model"
style="fill:none;fill-rule:evenodd;stroke:none;stroke-width:1"
transform="translate(0,2)">
<g
id="Artboard-3"
style="fill:#ffffff">
<g
id="Group-19">
<path
d="m 13,26 h 1.000227 C 22.844516,26 30,18.836556 30,10 h -1 c 0,8.284271 -6.717306,15 -14.999491,15 H 13 Z"
id="Combined-Shape-Copy-64"
inkscape:connector-curvature="0" />
<path
d="M 0,13 C 0,5.8202982 5.8187196,0 13,0 20.179702,0 26,5.8187196 26,13 26,20.179702 20.18128,26 13,26 5.8202982,26 0,20.18128 0,13 Z m 1.2380952,0 C 1.2380952,19.497349 6.5040794,24.761905 13,24.761905 19.497349,24.761905 24.761905,19.495921 24.761905,13 24.761905,6.5026511 19.495921,1.2380952 13,1.2380952 6.5026511,1.2380952 1.2380952,6.5040794 1.2380952,13 Z M 1.8,12.866667 C 1.8,12.384683 2.1844415,12 2.6586742,12 H 6.1413258 C 6.6091548,12 7,12.38802 7,12.866667 7,13.348651 6.6155584,13.733333 6.1413258,13.733333 H 2.6586742 C 2.1908452,13.733333 1.8,13.345313 1.8,12.866667 Z m 17,0 C 18.8,12.384683 19.184442,12 19.658674,12 h 3.482652 C 23.609155,12 24,12.38802 24,12.866667 c 0,0.481984 -0.384442,0.866666 -0.858674,0.866666 H 19.658674 C 19.190845,13.733333 18.8,13.345313 18.8,12.866667 Z m 1.943614,8.064088 c -0.338454,0.338455 -0.889195,0.336457 -1.22,0.0057 L 17.061008,18.4738 c -0.335334,-0.335333 -0.335163,-0.879186 0.0057,-1.22 0.338454,-0.338455 0.889195,-0.336457 1.22,-0.0057 l 2.462607,2.462607 c 0.335333,0.335333 0.335162,0.879186 -0.0057,1.22 z M 7.5236141,8.9364067 5.0610076,6.4738002 C 4.7256744,6.138467 4.7258451,5.594614 5.0666591,5.2537999 5.4051135,4.9153455 5.9558542,4.9173433 6.2866593,5.2481484 L 8.7492659,7.7107549 C 9.084599,8.0460881 9.0844284,8.5899412 8.7436144,8.9307552 8.40516,9.2692096 7.8544192,9.2672118 7.5236141,8.9364067 Z M 5.0666591,20.930755 c -0.340814,-0.340814 -0.3409847,-0.884667 -0.00565,-1.22 l 2.4626065,-2.462607 c 0.3308051,-0.330805 0.8815459,-0.332803 1.2200003,0.0057 0.340814,0.340814 0.3409846,0.884667 0.00565,1.22 L 6.2866593,20.936407 C 5.9558542,21.267212 5.4051135,21.26921 5.0666591,20.930755 Z M 17.066659,8.9307552 c -0.340814,-0.340814 -0.340985,-0.8846671 -0.0057,-1.2200003 l 2.462606,-2.4626065 c 0.330805,-0.3308051 0.881546,-0.3328029 1.22,0.00565 0.340814,0.3408141 0.340985,0.8846671 0.0057,1.2200003 l -2.462607,2.4626065 c -0.330805,0.3308051 -0.881546,0.3328029 -1.219999,-0.00565 z M 13.133333,2 C 13.615317,2 14,2.3844416 14,2.8586742 V 6.3413258 C 14,6.8091548 13.61198,7.2 13.133333,7.2 12.65135,7.2 12.266667,6.8155584 12.266667,6.3413258 V 2.8586742 C 12.266667,2.3908452 12.654687,2 13.133333,2 Z m 0,17 C 13.615317,19 14,19.384442 14,19.858674 v 3.482652 C 14,23.809155 13.61198,24.2 13.133333,24.2 12.65135,24.2 12.266667,23.815558 12.266667,23.341326 V 19.858674 C 12.266667,19.390845 12.654687,19 13.133333,19 Z M 8.6666667,13 c 0,-2.393234 1.9449693,-4.3333333 4.3333333,-4.3333333 2.393234,0 4.333333,1.9449693 4.333333,4.3333333 0,2.393234 -1.944969,4.333333 -4.333333,4.333333 -2.393234,0 -4.3333333,-1.944969 -4.3333333,-4.333333 z m 1.2380952,0 c 0,1.705974 1.3857851,3.095238 3.0952381,3.095238 1.705974,0 3.095238,-1.385785 3.095238,-3.095238 0,-1.705974 -1.385785,-3.0952381 -3.095238,-3.0952381 -1.705974,0 -3.0952381,1.3857851 -3.0952381,3.0952381 z"
id="Combined-Shape-Copy-60"
inkscape:connector-curvature="0" />
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.1 KiB

View file

@ -0,0 +1,78 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="30"
height="30"
viewBox="0 0 30 30"
version="1.1"
id="svg4595"
sodipodi:docname="material_selected.svg"
inkscape:version="0.92.1 r">
<metadata
id="metadata4599">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title>Artboard 3 Copy</dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="2502"
inkscape:window-height="1411"
id="namedview4597"
showgrid="false"
inkscape:pagecheckerboard="true"
inkscape:zoom="23.442308"
inkscape:cx="18.780195"
inkscape:cy="17.941232"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="0"
inkscape:current-layer="svg4595" />
<!-- Generator: Sketch 43.1 (39012) - http://www.bohemiancoding.com/sketch -->
<title
id="title4584">Artboard 3 Copy</title>
<desc
id="desc4586">Created with Sketch.</desc>
<defs
id="defs4588" />
<g
id="Feature-apply-material-to-model"
style="fill:none;fill-rule:evenodd;stroke:none;stroke-width:1"
transform="translate(0,2)">
<g
id="Artboard-3-Copy"
style="fill:#ffffff">
<g
id="Group-20-Copy">
<path
d="M 13,26 C 5.8202982,26 0,20.179702 0,13 0,5.8202982 5.8202982,0 13,0 c 7.179702,0 13,5.8202982 13,13 0,7.179702 -5.820298,13 -13,13 z m 0,-8.666667 c 2.393234,0 4.333333,-1.940099 4.333333,-4.333333 0,-2.393234 -1.940099,-4.3333333 -4.333333,-4.3333333 -2.393234,0 -4.3333333,1.9400993 -4.3333333,4.3333333 0,2.393234 1.9400993,4.333333 4.3333333,4.333333 z m 0,1.733334 c -0.481984,0 -0.866667,0.384441 -0.866667,0.858674 v 3.482651 c 0,0.467829 0.38802,0.858675 0.866667,0.858675 0.481984,0 0.866667,-0.384442 0.866667,-0.858675 v -3.482651 c 0,-0.467829 -0.38802,-0.858674 -0.866667,-0.858674 z M 13,1.7333333 c -0.481984,0 -0.866667,0.3844416 -0.866667,0.8586743 v 3.4826515 c 0,0.4678291 0.38802,0.8586742 0.866667,0.8586742 0.481984,0 0.866667,-0.3844415 0.866667,-0.8586742 V 2.5920076 C 13.866667,2.1241785 13.478647,1.7333333 13,1.7333333 Z M 8.6231145,8.6231145 C 8.9639285,8.2823004 8.9640991,7.7384474 8.628766,7.4031142 L 6.1661595,4.9405077 C 5.8353543,4.6097026 5.2846136,4.6077048 4.9461592,4.9461592 4.6053452,5.2869732 4.6051746,5.8308263 4.9405077,6.1661595 L 7.4031142,8.628766 C 7.7339193,8.9595711 8.2846601,8.9615689 8.6231145,8.623116 Z M 20.756448,20.756448 c 0.340814,-0.340814 0.340984,-0.884667 0.0057,-1.22 l -2.462606,-2.462607 c -0.330805,-0.330805 -0.881546,-0.332803 -1.220001,0.0057 -0.340814,0.340815 -0.340984,0.884668 -0.0057,1.220001 l 2.462607,2.462606 c 0.330805,0.330805 0.881545,0.332803 1.22,-0.0057 z M 18.299493,8.628766 20.762099,6.1661595 c 0.335333,-0.3353332 0.335163,-0.8791863 -0.0057,-1.2200003 -0.338455,-0.3384544 -0.889195,-0.3364566 -1.22,-0.00565 l -2.462607,2.4626065 c -0.335333,0.3353332 -0.335163,0.8791862 0.0057,1.2200003 0.338455,0.3384544 0.889196,0.3364566 1.220001,0.00565 z M 4.9461592,20.756448 c 0.3384544,0.338454 0.8891951,0.336456 1.2200003,0.0057 L 8.628766,18.299493 C 8.9640991,17.96416 8.9639285,17.420307 8.6231145,17.079492 8.2846601,16.741038 7.7339193,16.743036 7.4031142,17.073841 l -2.4626065,2.462607 c -0.3353331,0.335333 -0.3351625,0.879186 0.00565,1.22 z M 6.9333333,13 c 0,-0.481984 -0.3844415,-0.866667 -0.8586742,-0.866667 H 2.5920076 c -0.4678291,0 -0.8586743,0.38802 -0.8586743,0.866667 0,0.481984 0.3844416,0.866667 0.8586743,0.866667 h 3.4826515 c 0.4678291,0 0.8586742,-0.38802 0.8586742,-0.866667 z m 17.3333337,0 c 0,-0.481984 -0.384442,-0.866667 -0.858675,-0.866667 h -3.482651 c -0.467829,0 -0.858674,0.38802 -0.858674,0.866667 0,0.481984 0.384441,0.866667 0.858674,0.866667 h 3.482651 c 0.467829,0 0.858675,-0.38802 0.858675,-0.866667 z"
id="Combined-Shape-Copy-58"
transform="rotate(-90,13,13)"
inkscape:connector-curvature="0" />
<path
d="m 13,26 h 1.000227 C 22.844516,26 30,18.836556 30,10 h -1 c 0,8.284271 -6.717306,15 -14.999491,15 H 13 Z"
id="Combined-Shape-Copy-59"
inkscape:connector-curvature="0" />
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.8 KiB

36
resources/themes/cura/styles.qml Normal file → Executable file
View file

@ -8,19 +8,25 @@ import QtQuick.Controls.Styles 1.1
import UM 1.1 as UM
QtObject {
property Component toggle_button: Component {
property Component mode_switch: 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");
implicitWidth: UM.Theme.getSize("mode_switch").width
implicitHeight: UM.Theme.getSize("mode_switch").height
radius: implicitHeight / 2
color: {
if(control.hovered || control._hovered) {
return UM.Theme.getColor("mode_switch_hover");
} else {
return UM.Theme.getColor("sidebar_header_bar");
return UM.Theme.getColor("mode_switch");
}
}
Behavior on color { ColorAnimation { duration: 50; } }
border.color: {
if(control.hovered || control._hovered) {
return UM.Theme.getColor("mode_switch_border_hover");
} else {
return UM.Theme.getColor("mode_switch_border");
}
}
Behavior on border.color { ColorAnimation { duration: 50; } }
@ -28,9 +34,9 @@ QtObject {
}
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
implicitWidth: implicitHeight
implicitHeight: UM.Theme.getSize("mode_switch").height
radius: implicitHeight / 2
color: {
if (control.pressed || (control.checkable && control.checked)) {
@ -206,7 +212,9 @@ QtObject {
property bool down: control.pressed || (control.checkable && control.checked);
color: {
if(control.checkable && control.checked && control.hovered) {
if(control.customColor !== undefined && control.customColor !== null) {
return control.customColor
} else if(control.checkable && control.checked && control.hovered) {
return Theme.getColor("button_active_hover");
} else if(control.pressed || (control.checkable && control.checked)) {
return Theme.getColor("button_active");

View file

@ -175,6 +175,15 @@
"checkbox_mark": [24, 41, 77, 255],
"checkbox_text": [24, 41, 77, 255],
"mode_switch": [255, 255, 255, 255],
"mode_switch_hover": [255, 255, 255, 255],
"mode_switch_border": [127, 127, 127, 255],
"mode_switch_border_hover": [12, 169, 227, 255],
"mode_switch_handle": [24, 41, 77, 255],
"mode_switch_text": [24, 41, 77, 255],
"mode_switch_text_hover": [24, 41, 77, 255],
"mode_switch_text_checked": [12, 169, 227, 255],
"tooltip": [12, 169, 227, 255],
"tooltip_text": [255, 255, 255, 255],
@ -238,7 +247,7 @@
},
"sizes": {
"window_minimum_size": [70, 54],
"window_minimum_size": [70, 50],
"window_margin": [1.0, 1.0],
"default_margin": [1.0, 1.0],
"default_lining": [0.08, 0.08],
@ -301,6 +310,7 @@
"layerview_row_spacing": [0.0, 0.5],
"checkbox": [2.0, 2.0],
"mode_switch": [2.0, 1.0],
"tooltip": [20.0, 10.0],
"tooltip_margins": [1.0, 1.0],
@ -319,11 +329,6 @@
"infill_button_margin": [0.5, 0.5],
"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]
"jobspecs_line": [2.0, 2.0]
}
}