Merge branch 'master' into cura_containerstack

This commit is contained in:
Ghostkeeper 2017-05-03 15:21:01 +02:00
commit c42d092b0f
No known key found for this signature in database
GPG key ID: C5F96EE2BC0F7E75
24 changed files with 1157 additions and 472 deletions

View file

@ -108,6 +108,7 @@ class CuraApplication(QtApplication):
UserInstanceContainer = Resources.UserType + 6 UserInstanceContainer = Resources.UserType + 6
MachineStack = Resources.UserType + 7 MachineStack = Resources.UserType + 7
ExtruderStack = Resources.UserType + 8 ExtruderStack = Resources.UserType + 8
DefinitionChangesContainer = Resources.UserType + 9
Q_ENUMS(ResourceTypes) Q_ENUMS(ResourceTypes)
@ -153,6 +154,7 @@ class CuraApplication(QtApplication):
Resources.addStorageType(self.ResourceTypes.UserInstanceContainer, "user") Resources.addStorageType(self.ResourceTypes.UserInstanceContainer, "user")
Resources.addStorageType(self.ResourceTypes.ExtruderStack, "extruders") Resources.addStorageType(self.ResourceTypes.ExtruderStack, "extruders")
Resources.addStorageType(self.ResourceTypes.MachineStack, "machine_instances") Resources.addStorageType(self.ResourceTypes.MachineStack, "machine_instances")
Resources.addStorageType(self.ResourceTypes.DefinitionChangesContainer, "definition_changes")
ContainerRegistry.getInstance().addResourceType(self.ResourceTypes.QualityInstanceContainer) ContainerRegistry.getInstance().addResourceType(self.ResourceTypes.QualityInstanceContainer)
ContainerRegistry.getInstance().addResourceType(self.ResourceTypes.VariantInstanceContainer) ContainerRegistry.getInstance().addResourceType(self.ResourceTypes.VariantInstanceContainer)
@ -160,6 +162,7 @@ class CuraApplication(QtApplication):
ContainerRegistry.getInstance().addResourceType(self.ResourceTypes.UserInstanceContainer) ContainerRegistry.getInstance().addResourceType(self.ResourceTypes.UserInstanceContainer)
ContainerRegistry.getInstance().addResourceType(self.ResourceTypes.ExtruderStack) ContainerRegistry.getInstance().addResourceType(self.ResourceTypes.ExtruderStack)
ContainerRegistry.getInstance().addResourceType(self.ResourceTypes.MachineStack) ContainerRegistry.getInstance().addResourceType(self.ResourceTypes.MachineStack)
ContainerRegistry.getInstance().addResourceType(self.ResourceTypes.DefinitionChangesContainer)
## Initialise the version upgrade manager with Cura's storage paths. ## Initialise the version upgrade manager with Cura's storage paths.
import UM.VersionUpgradeManager #Needs to be here to prevent circular dependencies. import UM.VersionUpgradeManager #Needs to be here to prevent circular dependencies.
@ -415,7 +418,7 @@ class CuraApplication(QtApplication):
elif instance_type == "variant": elif instance_type == "variant":
path = Resources.getStoragePath(self.ResourceTypes.VariantInstanceContainer, file_name) path = Resources.getStoragePath(self.ResourceTypes.VariantInstanceContainer, file_name)
elif instance_type == "definition_changes": elif instance_type == "definition_changes":
path = Resources.getStoragePath(self.ResourceTypes.MachineStack, file_name) path = Resources.getStoragePath(self.ResourceTypes.DefinitionChangesContainer, file_name)
if path: if path:
instance.setPath(path) instance.setPath(path)

View file

@ -144,6 +144,7 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel):
items.append(item) items.append(item)
changed = True changed = True
machine_extruder_count = global_container_stack.getProperty("machine_extruder_count", "value")
manager = ExtruderManager.getInstance() manager = ExtruderManager.getInstance()
for extruder in manager.getMachineExtruders(global_container_stack.getId()): for extruder in manager.getMachineExtruders(global_container_stack.getId()):
extruder_name = extruder.getName() extruder_name = extruder.getName()
@ -154,6 +155,9 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel):
position = int(position) position = int(position)
except ValueError: #Not a proper int. except ValueError: #Not a proper int.
position = -1 position = -1
if position >= machine_extruder_count:
continue
default_color = self.defaultColors[position] if position >= 0 and position < len(self.defaultColors) else self.defaultColors[0] default_color = self.defaultColors[position] if position >= 0 and position < len(self.defaultColors) else self.defaultColors[0]
color = material.getMetaDataEntry("color_code", default = default_color) if material else default_color color = material.getMetaDataEntry("color_code", default = default_color) if material else default_color
item = { #Construct an item with only the relevant information. item = { #Construct an item with only the relevant information.

View file

@ -495,6 +495,17 @@ class MachineManager(QObject):
return result return result
@pyqtProperty("QVariantList", notify = activeVariantChanged)
def activeMaterialIds(self):
result = []
if ExtruderManager.getInstance().getActiveGlobalAndExtruderStacks() is not None:
for stack in ExtruderManager.getInstance().getActiveGlobalAndExtruderStacks():
variant_container = stack.findContainer({"type": "variant"})
if variant_container and variant_container != self._empty_variant_container:
result.append(variant_container.getId())
return result
@pyqtProperty("QVariantList", notify = activeMaterialChanged) @pyqtProperty("QVariantList", notify = activeMaterialChanged)
def activeMaterialNames(self): def activeMaterialNames(self):
result = [] result = []

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.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.Platform import Platform
from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator
from UM.Qt.Duration import DurationFormat
from PyQt5.QtCore import QObject, pyqtSlot from PyQt5.QtCore import QObject, pyqtSlot
from cura.Settings.ExtruderManager import ExtruderManager from cura.Settings.ExtruderManager import ExtruderManager
from . import ProcessSlicedLayersJob from . import ProcessSlicedLayersJob
from . import StartSliceJob from . import StartSliceJob
@ -442,6 +442,15 @@ class CuraEngineBackend(QObject, Backend):
self.backendStateChange.emit(BackendState.Done) self.backendStateChange.emit(BackendState.Done)
self.processingProgress.emit(1.0) 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._slicing = False
self._need_slicing = False self._need_slicing = False
Logger.log("d", "Slicing took %s seconds", time() - self._slice_start_time ) Logger.log("d", "Slicing took %s seconds", time() - self._slice_start_time )

View file

@ -4,6 +4,7 @@
import numpy import numpy
from string import Formatter from string import Formatter
from enum import IntEnum from enum import IntEnum
import time
from UM.Job import Job from UM.Job import Job
from UM.Application import Application from UM.Application import Application
@ -240,6 +241,13 @@ class StartSliceJob(Job):
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"} 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["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. for key, value in settings.items(): #Add all submessages for each individual setting.
setting_message = self._slice_message.getMessage("global_settings").addRepeatedMessage("settings") setting_message = self._slice_message.getMessage("global_settings").addRepeatedMessage("settings")
setting_message.name = key setting_message.name = key

223
plugins/MachineSettingsAction/MachineSettingsAction.py Normal file → Executable file
View file

@ -7,12 +7,15 @@ from UM.FlameProfiler import pyqtSlot
from cura.MachineAction import MachineAction from cura.MachineAction import MachineAction
from UM.Application import Application from UM.Application import Application
from UM.Preferences import Preferences
from UM.Settings.InstanceContainer import InstanceContainer from UM.Settings.InstanceContainer import InstanceContainer
from UM.Settings.ContainerRegistry import ContainerRegistry from UM.Settings.ContainerRegistry import ContainerRegistry
from UM.Settings.DefinitionContainer import DefinitionContainer from UM.Settings.DefinitionContainer import DefinitionContainer
from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator
from UM.Logger import Logger from UM.Logger import Logger
from cura.Settings.CuraContainerRegistry import CuraContainerRegistry from cura.Settings.CuraContainerRegistry import CuraContainerRegistry
from cura.Settings.ExtruderManager import ExtruderManager
import UM.i18n import UM.i18n
catalog = UM.i18n.i18nCatalog("cura") catalog = UM.i18n.i18nCatalog("cura")
@ -25,36 +28,81 @@ class MachineSettingsAction(MachineAction):
super().__init__("MachineSettingsAction", catalog.i18nc("@action", "Machine Settings")) super().__init__("MachineSettingsAction", catalog.i18nc("@action", "Machine Settings"))
self._qml_url = "MachineSettingsAction.qml" self._qml_url = "MachineSettingsAction.qml"
self._global_container_stack = None
self._container_index = 0 self._container_index = 0
self._extruder_container_index = 0
self._container_registry = ContainerRegistry.getInstance() self._container_registry = ContainerRegistry.getInstance()
self._container_registry.containerAdded.connect(self._onContainerAdded) self._container_registry.containerAdded.connect(self._onContainerAdded)
self._container_registry.containerRemoved.connect(self._onContainerRemoved)
Application.getInstance().globalContainerStackChanged.connect(self._onGlobalContainerChanged)
ExtruderManager.getInstance().activeExtruderChanged.connect(self._onActiveExtruderStackChanged)
self._backend = Application.getInstance().getBackend()
def _onContainerAdded(self, container):
# Add this action as a supported action to all machine definitions
if isinstance(container, DefinitionContainer) and container.getMetaDataEntry("type") == "machine":
Application.getInstance().getMachineActionManager().addSupportedAction(container.getId(), self.getKey())
def _onContainerRemoved(self, container):
# Remove definition_changes containers when a stack is removed
if container.getMetaDataEntry("type") in ["machine", "extruder_train"]:
definition_changes_container = container.findContainer({"type": "definition_changes"})
if not definition_changes_container:
return
self._container_registry.removeContainer(definition_changes_container.getId())
def _reset(self): def _reset(self):
global_container_stack = Application.getInstance().getGlobalContainerStack() if not self._global_container_stack:
if not global_container_stack:
return return
# Make sure there is a definition_changes container to store the machine settings # Make sure there is a definition_changes container to store the machine settings
definition_changes_container = global_container_stack.findContainer({"type": "definition_changes"}) definition_changes_container = self._global_container_stack.findContainer({"type": "definition_changes"})
if not definition_changes_container: if not definition_changes_container:
definition_changes_container = self._createDefinitionChangesContainer(global_container_stack) definition_changes_container = self._createDefinitionChangesContainer(self._global_container_stack, self._global_container_stack.getName() + "_settings")
# Notify the UI in which container to store the machine settings data # Notify the UI in which container to store the machine settings data
container_index = global_container_stack.getContainerIndex(definition_changes_container) container_index = self._global_container_stack.getContainerIndex(definition_changes_container)
if container_index != self._container_index: if container_index != self._container_index:
self._container_index = container_index self._container_index = container_index
self.containerIndexChanged.emit() self.containerIndexChanged.emit()
def _createDefinitionChangesContainer(self, global_container_stack, container_index = None): # Disable autoslicing while the machineaction is showing
definition_changes_container = InstanceContainer(global_container_stack.getName() + "_settings") self._backend.disableTimer()
definition = global_container_stack.getBottom()
@pyqtSlot()
def onFinishAction(self):
# Restore autoslicing when the machineaction is dismissed
if self._backend.determineAutoSlicing():
self._backend.tickle()
def _onActiveExtruderStackChanged(self):
extruder_container_stack = ExtruderManager.getInstance().getActiveExtruderStack()
if not self._global_container_stack or not extruder_container_stack:
return
# Make sure there is a definition_changes container to store the machine settings
definition_changes_container = extruder_container_stack.findContainer({"type": "definition_changes"})
if not definition_changes_container:
definition_changes_container = self._createDefinitionChangesContainer(extruder_container_stack, extruder_container_stack.getId() + "_settings")
# Notify the UI in which container to store the machine settings data
container_index = extruder_container_stack.getContainerIndex(definition_changes_container)
if container_index != self._extruder_container_index:
self._extruder_container_index = container_index
self.extruderContainerIndexChanged.emit()
def _createDefinitionChangesContainer(self, container_stack, container_name, container_index = None):
definition_changes_container = InstanceContainer(container_name)
definition = container_stack.getBottom()
definition_changes_container.setDefinition(definition) definition_changes_container.setDefinition(definition)
definition_changes_container.addMetaDataEntry("type", "definition_changes") definition_changes_container.addMetaDataEntry("type", "definition_changes")
self._container_registry.addContainer(definition_changes_container) self._container_registry.addContainer(definition_changes_container)
# Insert definition_changes between the definition and the variant # Insert definition_changes between the definition and the variant
global_container_stack.insertContainer(-1, definition_changes_container) container_stack.insertContainer(-1, definition_changes_container)
return definition_changes_container return definition_changes_container
@ -64,15 +112,129 @@ class MachineSettingsAction(MachineAction):
def containerIndex(self): def containerIndex(self):
return self._container_index return self._container_index
def _onContainerAdded(self, container): extruderContainerIndexChanged = pyqtSignal()
# Add this action as a supported action to all machine definitions
if isinstance(container, DefinitionContainer) and container.getMetaDataEntry("type") == "machine": @pyqtProperty(int, notify = extruderContainerIndexChanged)
if container.getProperty("machine_extruder_count", "value") > 1: def extruderContainerIndex(self):
# Multiextruder printers are not currently supported return self._extruder_container_index
Logger.log("d", "Not attaching MachineSettingsAction to %s; Multi-extrusion printers are not supported", container.getId())
def _onGlobalContainerChanged(self):
self._global_container_stack = Application.getInstance().getGlobalContainerStack()
# This additional emit is needed because we cannot connect a UM.Signal directly to a pyqtSignal
self.globalContainerChanged.emit()
globalContainerChanged = pyqtSignal()
@pyqtProperty(int, notify = globalContainerChanged)
def definedExtruderCount(self):
if not self._global_container_stack:
return 0
return len(self._global_container_stack.getMetaDataEntry("machine_extruder_trains"))
@pyqtSlot(int)
def setMachineExtruderCount(self, extruder_count):
machine_manager = Application.getInstance().getMachineManager()
extruder_manager = ExtruderManager.getInstance()
definition_changes_container = self._global_container_stack.findContainer({"type": "definition_changes"})
if not self._global_container_stack or not definition_changes_container:
return return
Application.getInstance().getMachineActionManager().addSupportedAction(container.getId(), self.getKey()) previous_extruder_count = self._global_container_stack.getProperty("machine_extruder_count", "value")
if extruder_count == previous_extruder_count:
return
extruder_material_id = None
extruder_variant_id = None
if extruder_count == 1:
# Get the material and variant of the first extruder before setting the number extruders to 1
if machine_manager.hasMaterials:
extruder_material_id = machine_manager.allActiveMaterialIds[extruder_manager.extruderIds["0"]]
if machine_manager.hasVariants:
extruder_variant_id = machine_manager.activeVariantIds[0]
# Copy any settable_per_extruder setting value from the extruders to the global stack
extruder_stacks = ExtruderManager.getInstance().getActiveExtruderStacks()
extruder_stacks.reverse() # make sure the first extruder is done last, so its settings override any higher extruder settings
global_user_container = self._global_container_stack.getTop()
for extruder_stack in extruder_stacks:
extruder_index = extruder_stack.getMetaDataEntry("position")
extruder_user_container = extruder_stack.getTop()
for setting_instance in extruder_user_container.findInstances():
setting_key = setting_instance.definition.key
settable_per_extruder = self._global_container_stack.getProperty(setting_key, "settable_per_extruder")
if settable_per_extruder:
limit_to_extruder = self._global_container_stack.getProperty(setting_key, "limit_to_extruder")
if limit_to_extruder == "-1" or limit_to_extruder == extruder_index:
global_user_container.setProperty(setting_key, "value", extruder_user_container.getProperty(setting_key, "value"))
extruder_user_container.removeInstance(setting_key)
# Check to see if any features are set to print with an extruder that will no longer exist
for setting_key in ["adhesion_extruder_nr", "support_extruder_nr", "support_extruder_nr_layer_0", "support_infill_extruder_nr", "support_interface_extruder_nr"]:
if int(self._global_container_stack.getProperty(setting_key, "value")) > extruder_count -1:
Logger.log("i", "Lowering %s setting to match number of extruders", setting_key)
self._global_container_stack.getTop().setProperty(setting_key, "value", extruder_count -1)
# Check to see if any objects are set to print with an extruder that will no longer exist
root_node = Application.getInstance().getController().getScene().getRoot()
for node in DepthFirstIterator(root_node):
if node.getMeshData():
extruder_nr = node.callDecoration("getActiveExtruderPosition")
if extruder_nr is not None and int(extruder_nr) > extruder_count - 1:
node.callDecoration("setActiveExtruder", extruder_manager.getExtruderStack(extruder_count - 1).getId())
definition_changes_container.setProperty("machine_extruder_count", "value", extruder_count)
self.forceUpdate()
if extruder_count > 1:
# Multiextrusion
# Make sure one of the extruder stacks is active
if extruder_manager.activeExtruderIndex == -1:
extruder_manager.setActiveExtruderIndex(0)
# Move settable_per_extruder values out of the global container
if previous_extruder_count == 1:
extruder_stacks = ExtruderManager.getInstance().getActiveExtruderStacks()
global_user_container = self._global_container_stack.getTop()
for setting_instance in global_user_container.findInstances():
setting_key = setting_instance.definition.key
settable_per_extruder = self._global_container_stack.getProperty(setting_key, "settable_per_extruder")
if settable_per_extruder:
limit_to_extruder = int(self._global_container_stack.getProperty(setting_key, "limit_to_extruder"))
extruder_stack = extruder_stacks[max(0, limit_to_extruder)]
extruder_stack.getTop().setProperty(setting_key, "value", global_user_container.getProperty(setting_key, "value"))
global_user_container.removeInstance(setting_key)
else:
# Single extrusion
# Make sure the machine stack is active
if extruder_manager.activeExtruderIndex > -1:
extruder_manager.setActiveExtruderIndex(-1);
# Restore material and variant on global stack
# MachineManager._onGlobalContainerChanged removes the global material and variant of multiextruder machines
if extruder_material_id or extruder_variant_id:
# Prevent the DiscardOrKeepProfileChangesDialog from popping up (twice) if there are user changes
# The dialog is not relevant here, since we're restoring the previous situation as good as possible
preferences = Preferences.getInstance()
choice_on_profile_override = preferences.getValue("cura/choice_on_profile_override")
preferences.setValue("cura/choice_on_profile_override", "always_keep")
if extruder_material_id:
machine_manager.setActiveMaterial(extruder_material_id);
if extruder_variant_id:
machine_manager.setActiveVariant(extruder_variant_id);
preferences.setValue("cura/choice_on_profile_override", choice_on_profile_override)
@pyqtSlot() @pyqtSlot()
def forceUpdate(self): def forceUpdate(self):
@ -83,34 +245,35 @@ class MachineSettingsAction(MachineAction):
@pyqtSlot() @pyqtSlot()
def updateHasMaterialsMetadata(self): def updateHasMaterialsMetadata(self):
# Updates the has_materials metadata flag after switching gcode flavor # Updates the has_materials metadata flag after switching gcode flavor
global_container_stack = Application.getInstance().getGlobalContainerStack() if not self._global_container_stack:
if global_container_stack: return
definition = global_container_stack.getBottom()
if definition.getProperty("machine_gcode_flavor", "value") == "UltiGCode" and not definition.getMetaDataEntry("has_materials", False):
has_materials = global_container_stack.getProperty("machine_gcode_flavor", "value") != "UltiGCode"
material_container = global_container_stack.findContainer({"type": "material"}) definition = self._global_container_stack.getBottom()
material_index = global_container_stack.getContainerIndex(material_container) if definition.getProperty("machine_gcode_flavor", "value") == "UltiGCode" and not definition.getMetaDataEntry("has_materials", False):
has_materials = self._global_container_stack.getProperty("machine_gcode_flavor", "value") != "UltiGCode"
material_container = self._global_container_stack.findContainer({"type": "material"})
material_index = self._global_container_stack.getContainerIndex(material_container)
if has_materials: if has_materials:
if "has_materials" in global_container_stack.getMetaData(): if "has_materials" in self._global_container_stack.getMetaData():
global_container_stack.setMetaDataEntry("has_materials", True) self._global_container_stack.setMetaDataEntry("has_materials", True)
else: else:
global_container_stack.addMetaDataEntry("has_materials", True) self._global_container_stack.addMetaDataEntry("has_materials", True)
# Set the material container to a sane default # Set the material container to a sane default
if material_container.getId() == "empty_material": if material_container.getId() == "empty_material":
search_criteria = { "type": "material", "definition": "fdmprinter", "id": "*pla*" } search_criteria = { "type": "material", "definition": "fdmprinter", "id": "*pla*" }
containers = self._container_registry.findInstanceContainers(**search_criteria) containers = self._container_registry.findInstanceContainers(**search_criteria)
if containers: if containers:
global_container_stack.replaceContainer(material_index, containers[0]) self._global_container_stack.replaceContainer(material_index, containers[0])
else: else:
# The metadata entry is stored in an ini, and ini files are parsed as strings only. # The metadata entry is stored in an ini, and ini files are parsed as strings only.
# Because any non-empty string evaluates to a boolean True, we have to remove the entry to make it False. # Because any non-empty string evaluates to a boolean True, we have to remove the entry to make it False.
if "has_materials" in global_container_stack.getMetaData(): if "has_materials" in self._global_container_stack.getMetaData():
global_container_stack.removeMetaDataEntry("has_materials") self._global_container_stack.removeMetaDataEntry("has_materials")
empty_material = self._container_registry.findInstanceContainers(id = "empty_material")[0] empty_material = self._container_registry.findInstanceContainers(id = "empty_material")[0]
global_container_stack.replaceContainer(material_index, empty_material) self._global_container_stack.replaceContainer(material_index, empty_material)
Application.getInstance().globalContainerStackChanged.emit() Application.getInstance().globalContainerStackChanged.emit()

View file

@ -12,6 +12,38 @@ import Cura 1.0 as Cura
Cura.MachineAction Cura.MachineAction
{ {
id: base
property var extrudersModel: Cura.ExtrudersModel{}
property int extruderTabsCount: 0
Component.onCompleted:
{
// Populate extruder tabs after a short delay, because otherwise the tabs that are added when
// the dialog is created are stuck.
extruderTabsCountDelay.start();
}
Timer
{
id: extruderTabsCountDelay
repeat: false
interval: 1
onTriggered: base.extruderTabsCount = (machineExtruderCountProvider.properties.value > 1) ? parseInt(machineExtruderCountProvider.properties.value) : 0
}
Connections
{
target: dialog ? dialog : null
ignoreUnknownSignals: true
// Any which way this action dialog is dismissed, make sure it is properly finished
onNextClicked: manager.onFinishAction()
onBackClicked: manager.onFinishAction()
onAccepted: manager.onFinishAction()
onRejected: manager.onFinishAction()
onClosing: manager.onFinishAction()
}
anchors.fill: parent; anchors.fill: parent;
Item Item
{ {
@ -28,26 +60,27 @@ Cura.MachineAction
wrapMode: Text.WordWrap wrapMode: Text.WordWrap
font.pointSize: 18; font.pointSize: 18;
} }
Label
TabView
{ {
id: pageDescription id: settingsTabs
height: parent.height - y
width: parent.width
anchors.left: parent.left
anchors.top: pageTitle.bottom anchors.top: pageTitle.bottom
anchors.topMargin: UM.Theme.getSize("default_margin").height anchors.topMargin: UM.Theme.getSize("default_margin").height
width: parent.width
wrapMode: Text.WordWrap property real columnWidth: Math.floor((width - 3 * UM.Theme.getSize("default_margin").width) / 2)
text: catalog.i18nc("@label", "Please enter the correct settings for your printer below:")
} Tab
{
title: catalog.i18nc("@title:tab", "Printer");
anchors.margins: UM.Theme.getSize("default_margin").width
Column Column
{ {
height: parent.height - y
width: parent.width - UM.Theme.getSize("default_margin").width
spacing: UM.Theme.getSize("default_margin").height spacing: UM.Theme.getSize("default_margin").height
anchors.left: parent.left
anchors.top: pageDescription.bottom
anchors.topMargin: UM.Theme.getSize("default_margin").height
Row Row
{ {
width: parent.width width: parent.width
@ -55,7 +88,7 @@ Cura.MachineAction
Column Column
{ {
width: parent.width / 2 width: settingsTabs.columnWidth
spacing: UM.Theme.getSize("default_margin").height spacing: UM.Theme.getSize("default_margin").height
Label Label
@ -66,55 +99,47 @@ Cura.MachineAction
Grid Grid
{ {
columns: 3 columns: 2
columnSpacing: UM.Theme.getSize("default_margin").width columnSpacing: UM.Theme.getSize("default_margin").width
rowSpacing: UM.Theme.getSize("default_lining").width
Label Label
{ {
text: catalog.i18nc("@label", "X (Width)") text: catalog.i18nc("@label", "X (Width)")
} }
TextField Loader
{ {
id: buildAreaWidthField id: buildAreaWidthField
text: machineWidthProvider.properties.value sourceComponent: numericTextFieldWithUnit
validator: RegExpValidator { regExp: /[0-9\.]{0,6}/ } property var propertyProvider: machineWidthProvider
onEditingFinished: { machineWidthProvider.setPropertyValue("value", text); manager.forceUpdate() } property string unit: catalog.i18nc("@label", "mm")
} property bool forceUpdateOnChange: true
Label
{
text: catalog.i18nc("@label", "mm")
} }
Label Label
{ {
text: catalog.i18nc("@label", "Y (Depth)") text: catalog.i18nc("@label", "Y (Depth)")
} }
TextField Loader
{ {
id: buildAreaDepthField id: buildAreaDepthField
text: machineDepthProvider.properties.value sourceComponent: numericTextFieldWithUnit
validator: RegExpValidator { regExp: /[0-9\.]{0,6}/ } property var propertyProvider: machineDepthProvider
onEditingFinished: { machineDepthProvider.setPropertyValue("value", text); manager.forceUpdate() } property string unit: catalog.i18nc("@label", "mm")
} property bool forceUpdateOnChange: true
Label
{
text: catalog.i18nc("@label", "mm")
} }
Label Label
{ {
text: catalog.i18nc("@label", "Z (Height)") text: catalog.i18nc("@label", "Z (Height)")
} }
TextField Loader
{ {
id: buildAreaHeightField id: buildAreaHeightField
text: machineHeightProvider.properties.value sourceComponent: numericTextFieldWithUnit
validator: RegExpValidator { regExp: /[0-9\.]{0,6}/ } property var propertyProvider: machineHeightProvider
onEditingFinished: { machineHeightProvider.setPropertyValue("value", text); manager.forceUpdate() } property string unit: catalog.i18nc("@label", "mm")
} property bool forceUpdateOnChange: true
Label
{
text: catalog.i18nc("@label", "mm")
} }
} }
@ -164,12 +189,15 @@ Cura.MachineAction
return index return index
} }
onActivated: onActivated:
{
if(machineShapeProvider.properties.value != shapesModel.get(index).value)
{ {
machineShapeProvider.setPropertyValue("value", shapesModel.get(index).value); machineShapeProvider.setPropertyValue("value", shapesModel.get(index).value);
manager.forceUpdate(); manager.forceUpdate();
} }
} }
} }
}
CheckBox CheckBox
{ {
id: centerIsZeroCheckBox id: centerIsZeroCheckBox
@ -243,7 +271,7 @@ Cura.MachineAction
Column Column
{ {
width: parent.width / 2 width: settingsTabs.columnWidth
spacing: UM.Theme.getSize("default_margin").height spacing: UM.Theme.getSize("default_margin").height
Label Label
@ -254,8 +282,9 @@ Cura.MachineAction
Grid Grid
{ {
columns: 3 columns: 2
columnSpacing: UM.Theme.getSize("default_margin").width columnSpacing: UM.Theme.getSize("default_margin").width
rowSpacing: UM.Theme.getSize("default_lining").width
Label Label
{ {
@ -268,10 +297,6 @@ Cura.MachineAction
validator: RegExpValidator { regExp: /[0-9\.]{0,6}/ } validator: RegExpValidator { regExp: /[0-9\.]{0,6}/ }
onEditingFinished: setHeadPolygon() onEditingFinished: setHeadPolygon()
} }
Label
{
text: catalog.i18nc("@label", "mm")
}
Label Label
{ {
@ -284,10 +309,6 @@ Cura.MachineAction
validator: RegExpValidator { regExp: /[0-9\.]{0,6}/ } validator: RegExpValidator { regExp: /[0-9\.]{0,6}/ }
onEditingFinished: setHeadPolygon() onEditingFinished: setHeadPolygon()
} }
Label
{
text: catalog.i18nc("@label", "mm")
}
Label Label
{ {
@ -300,10 +321,6 @@ Cura.MachineAction
validator: RegExpValidator { regExp: /[0-9\.]{0,6}/ } validator: RegExpValidator { regExp: /[0-9\.]{0,6}/ }
onEditingFinished: setHeadPolygon() onEditingFinished: setHeadPolygon()
} }
Label
{
text: catalog.i18nc("@label", "mm")
}
Label Label
{ {
@ -316,12 +333,7 @@ Cura.MachineAction
validator: RegExpValidator { regExp: /[0-9\.]{0,6}/ } validator: RegExpValidator { regExp: /[0-9\.]{0,6}/ }
onEditingFinished: setHeadPolygon() onEditingFinished: setHeadPolygon()
} }
Label
{
text: catalog.i18nc("@label", "mm")
}
Item { width: UM.Theme.getSize("default_margin").width; height: UM.Theme.getSize("default_margin").height }
Item { width: UM.Theme.getSize("default_margin").width; height: UM.Theme.getSize("default_margin").height } Item { width: UM.Theme.getSize("default_margin").width; height: UM.Theme.getSize("default_margin").height }
Item { width: UM.Theme.getSize("default_margin").width; height: UM.Theme.getSize("default_margin").height } Item { width: UM.Theme.getSize("default_margin").width; height: UM.Theme.getSize("default_margin").height }
@ -329,39 +341,72 @@ Cura.MachineAction
{ {
text: catalog.i18nc("@label", "Gantry height") text: catalog.i18nc("@label", "Gantry height")
} }
TextField Loader
{ {
id: gantryHeightField id: gantryHeightField
text: gantryHeightProvider.properties.value sourceComponent: numericTextFieldWithUnit
validator: RegExpValidator { regExp: /[0-9\.]{0,6}/ } property var propertyProvider: gantryHeightProvider
onEditingFinished: { gantryHeightProvider.setPropertyValue("value", text) } property string unit: catalog.i18nc("@label", "mm")
property bool forceUpdateOnChange: false
} }
Item { width: UM.Theme.getSize("default_margin").width; height: UM.Theme.getSize("default_margin").height }
Item { width: UM.Theme.getSize("default_margin").width; height: UM.Theme.getSize("default_margin").height }
Label Label
{ {
text: catalog.i18nc("@label", "mm") text: catalog.i18nc("@label", "Number of Extruders")
visible: extruderCountComboBox.visible
} }
Item { width: UM.Theme.getSize("default_margin").width; height: UM.Theme.getSize("default_margin").height } ComboBox
Item { width: UM.Theme.getSize("default_margin").width; height: UM.Theme.getSize("default_margin").height } {
Item { width: UM.Theme.getSize("default_margin").width; height: UM.Theme.getSize("default_margin").height } id: extruderCountComboBox
visible: manager.definedExtruderCount > 1
model: ListModel
{
id: extruderCountModel
Component.onCompleted:
{
for(var i = 0; i < manager.definedExtruderCount; i++)
{
extruderCountModel.append({text: String(i + 1), value: i});
}
}
}
currentIndex: machineExtruderCountProvider.properties.value - 1
onActivated:
{
manager.setMachineExtruderCount(index + 1);
base.extruderTabsCount = (index > 0) ? index + 1 : 0;
}
}
Label
{
text: catalog.i18nc("@label", "Material Diameter")
}
Loader
{
id: materialDiameterField
sourceComponent: numericTextFieldWithUnit
property var propertyProvider: materialDiameterProvider
property string unit: catalog.i18nc("@label", "mm")
property bool forceUpdateOnChange: false
}
Label Label
{ {
text: catalog.i18nc("@label", "Nozzle size") text: catalog.i18nc("@label", "Nozzle size")
visible: !Cura.MachineManager.hasVariants visible: nozzleSizeField.visible
} }
TextField Loader
{ {
id: nozzleSizeField id: nozzleSizeField
text: machineNozzleSizeProvider.properties.value visible: !Cura.MachineManager.hasVariants && machineExtruderCountProvider.properties.value == 1
visible: !Cura.MachineManager.hasVariants sourceComponent: numericTextFieldWithUnit
validator: RegExpValidator { regExp: /[0-9\.]{0,6}/ } property var propertyProvider: machineNozzleSizeProvider
onEditingFinished: { machineNozzleSizeProvider.setPropertyValue("value", text) } property string unit: catalog.i18nc("@label", "mm")
} property bool forceUpdateOnChange: false
Label
{
text: catalog.i18nc("@label", "mm")
visible: !Cura.MachineManager.hasVariants
} }
} }
} }
@ -376,10 +421,11 @@ Cura.MachineAction
Column Column
{ {
height: parent.height height: parent.height
width: parent.width / 2 width: settingsTabs.columnWidth
Label Label
{ {
text: catalog.i18nc("@label", "Start Gcode") text: catalog.i18nc("@label", "Start Gcode")
font.bold: true
} }
TextArea TextArea
{ {
@ -387,7 +433,6 @@ Cura.MachineAction
width: parent.width width: parent.width
height: parent.height - y height: parent.height - y
font: UM.Theme.getFont("fixed") font: UM.Theme.getFont("fixed")
wrapMode: TextEdit.NoWrap
text: machineStartGcodeProvider.properties.value text: machineStartGcodeProvider.properties.value
onActiveFocusChanged: onActiveFocusChanged:
{ {
@ -396,14 +441,20 @@ Cura.MachineAction
machineStartGcodeProvider.setPropertyValue("value", machineStartGcodeField.text) machineStartGcodeProvider.setPropertyValue("value", machineStartGcodeField.text)
} }
} }
Component.onCompleted:
{
wrapMode = TextEdit.NoWrap;
} }
} }
}
Column { Column {
height: parent.height height: parent.height
width: parent.width / 2 width: settingsTabs.columnWidth
Label Label
{ {
text: catalog.i18nc("@label", "End Gcode") text: catalog.i18nc("@label", "End Gcode")
font.bold: true
} }
TextArea TextArea
{ {
@ -411,7 +462,6 @@ Cura.MachineAction
width: parent.width width: parent.width
height: parent.height - y height: parent.height - y
font: UM.Theme.getFont("fixed") font: UM.Theme.getFont("fixed")
wrapMode: TextEdit.NoWrap
text: machineEndGcodeProvider.properties.value text: machineEndGcodeProvider.properties.value
onActiveFocusChanged: onActiveFocusChanged:
{ {
@ -420,7 +470,9 @@ Cura.MachineAction
machineEndGcodeProvider.setPropertyValue("value", machineEndGcodeField.text) machineEndGcodeProvider.setPropertyValue("value", machineEndGcodeField.text)
} }
} }
} Component.onCompleted:
{
wrapMode = TextEdit.NoWrap;
} }
} }
} }
@ -448,9 +500,200 @@ Cura.MachineAction
polygon.push([-parseFloat(printheadXMinField.text),-parseFloat(printheadYMinField.text)]); polygon.push([-parseFloat(printheadXMinField.text),-parseFloat(printheadYMinField.text)]);
polygon.push([ parseFloat(printheadXMaxField.text), parseFloat(printheadYMaxField.text)]); polygon.push([ parseFloat(printheadXMaxField.text), parseFloat(printheadYMaxField.text)]);
polygon.push([ parseFloat(printheadXMaxField.text),-parseFloat(printheadYMinField.text)]); polygon.push([ parseFloat(printheadXMaxField.text),-parseFloat(printheadYMinField.text)]);
machineHeadPolygonProvider.setPropertyValue("value", JSON.stringify(polygon)); var polygon_string = JSON.stringify(polygon);
if(polygon != machineHeadPolygonProvider.properties.value)
{
machineHeadPolygonProvider.setPropertyValue("value", polygon_string);
manager.forceUpdate(); manager.forceUpdate();
} }
}
}
}
onCurrentIndexChanged:
{
if(currentIndex > 0)
{
contentItem.forceActiveFocus();
ExtruderManager.setActiveExtruderIndex(currentIndex - 1);
}
}
Repeater
{
id: extruderTabsRepeater
model: base.extruderTabsCount
Tab
{
title: base.extrudersModel.getItem(index).name
anchors.margins: UM.Theme.getSize("default_margin").width
Column
{
spacing: UM.Theme.getSize("default_margin").width
Label
{
text: catalog.i18nc("@label", "Nozzle Settings")
font.bold: true
}
Grid
{
columns: 2
columnSpacing: UM.Theme.getSize("default_margin").width
rowSpacing: UM.Theme.getSize("default_lining").width
Label
{
text: catalog.i18nc("@label", "Nozzle size")
visible: extruderNozzleSizeField.visible
}
Loader
{
id: extruderNozzleSizeField
visible: !Cura.MachineManager.hasVariants
sourceComponent: numericTextFieldWithUnit
property var propertyProvider: extruderNozzleSizeProvider
property string unit: catalog.i18nc("@label", "mm")
property bool forceUpdateOnChange: false
}
Label
{
text: catalog.i18nc("@label", "Nozzle offset X")
}
Loader
{
id: extruderOffsetXField
sourceComponent: numericTextFieldWithUnit
property var propertyProvider: extruderOffsetXProvider
property string unit: catalog.i18nc("@label", "mm")
property bool forceUpdateOnChange: true
}
Label
{
text: catalog.i18nc("@label", "Nozzle offset Y")
}
Loader
{
id: extruderOffsetYField
sourceComponent: numericTextFieldWithUnit
property var propertyProvider: extruderOffsetYProvider
property string unit: catalog.i18nc("@label", "mm")
property bool forceUpdateOnChange: true
}
}
Row
{
spacing: UM.Theme.getSize("default_margin").width
anchors.left: parent.left
anchors.right: parent.right
height: parent.height - y
Column
{
height: parent.height
width: settingsTabs.columnWidth
Label
{
text: catalog.i18nc("@label", "Extruder Start Gcode")
font.bold: true
}
TextArea
{
id: extruderStartGcodeField
width: parent.width
height: parent.height - y
font: UM.Theme.getFont("fixed")
text: (extruderStartGcodeProvider.properties.value) ? extruderStartGcodeProvider.properties.value : ""
onActiveFocusChanged:
{
if(!activeFocus)
{
extruderStartGcodeProvider.setPropertyValue("value", extruderStartGcodeField.text)
}
}
Component.onCompleted:
{
wrapMode = TextEdit.NoWrap;
}
}
}
Column {
height: parent.height
width: settingsTabs.columnWidth
Label
{
text: catalog.i18nc("@label", "Extruder End Gcode")
font.bold: true
}
TextArea
{
id: extruderEndGcodeField
width: parent.width
height: parent.height - y
font: UM.Theme.getFont("fixed")
text: (extruderEndGcodeProvider.properties.value) ? extruderEndGcodeProvider.properties.value : ""
onActiveFocusChanged:
{
if(!activeFocus)
{
extruderEndGcodeProvider.setPropertyValue("value", extruderEndGcodeField.text)
}
}
Component.onCompleted:
{
wrapMode = TextEdit.NoWrap;
}
}
}
}
}
}
}
}
}
Component
{
id: numericTextFieldWithUnit
Item {
height: textField.height
width: textField.width
TextField
{
id: textField
text: (propertyProvider.properties.value) ? propertyProvider.properties.value : ""
validator: RegExpValidator { regExp: /[0-9\.]{0,6}/ }
onEditingFinished:
{
if (propertyProvider && text != propertyProvider.properties.value)
{
propertyProvider.setPropertyValue("value", text);
if(forceUpdateOnChange)
{
var extruderIndex = ExtruderManager.activeExtruderIndex;
manager.forceUpdate();
if(ExtruderManager.activeExtruderIndex != extruderIndex)
{
ExtruderManager.setActiveExtruderIndex(extruderIndex)
}
}
}
}
}
Label
{
text: unit
anchors.right: textField.right
anchors.rightMargin: y - textField.y
anchors.verticalCenter: textField.verticalCenter
}
}
}
UM.SettingPropertyProvider UM.SettingPropertyProvider
{ {
@ -522,6 +765,16 @@ Cura.MachineAction
storeIndex: manager.containerIndex storeIndex: manager.containerIndex
} }
UM.SettingPropertyProvider
{
id: materialDiameterProvider
containerStackId: Cura.MachineManager.activeMachineId
key: "material_diameter"
watchedProperties: [ "value" ]
storeIndex: manager.containerIndex
}
UM.SettingPropertyProvider UM.SettingPropertyProvider
{ {
id: machineNozzleSizeProvider id: machineNozzleSizeProvider
@ -532,6 +785,16 @@ Cura.MachineAction
storeIndex: manager.containerIndex storeIndex: manager.containerIndex
} }
UM.SettingPropertyProvider
{
id: machineExtruderCountProvider
containerStackId: Cura.MachineManager.activeMachineId
key: "machine_extruder_count"
watchedProperties: [ "value" ]
storeIndex: manager.containerIndex
}
UM.SettingPropertyProvider UM.SettingPropertyProvider
{ {
id: gantryHeightProvider id: gantryHeightProvider
@ -573,4 +836,53 @@ Cura.MachineAction
storeIndex: manager.containerIndex storeIndex: manager.containerIndex
} }
UM.SettingPropertyProvider
{
id: extruderNozzleSizeProvider
containerStackId: settingsTabs.currentIndex > 0 ? Cura.MachineManager.activeStackId : ""
key: "machine_nozzle_size"
watchedProperties: [ "value" ]
storeIndex: manager.containerIndex
}
UM.SettingPropertyProvider
{
id: extruderOffsetXProvider
containerStackId: settingsTabs.currentIndex > 0 ? Cura.MachineManager.activeStackId : ""
key: "machine_nozzle_offset_x"
watchedProperties: [ "value" ]
storeIndex: manager.containerIndex
}
UM.SettingPropertyProvider
{
id: extruderOffsetYProvider
containerStackId: settingsTabs.currentIndex > 0 ? Cura.MachineManager.activeStackId : ""
key: "machine_nozzle_offset_y"
watchedProperties: [ "value" ]
storeIndex: manager.containerIndex
}
UM.SettingPropertyProvider
{
id: extruderStartGcodeProvider
containerStackId: settingsTabs.currentIndex > 0 ? Cura.MachineManager.activeStackId : ""
key: "machine_extruder_start_code"
watchedProperties: [ "value" ]
storeIndex: manager.containerIndex
}
UM.SettingPropertyProvider
{
id: extruderEndGcodeProvider
containerStackId: settingsTabs.currentIndex > 0 ? Cura.MachineManager.activeStackId : ""
key: "machine_extruder_end_code"
watchedProperties: [ "value" ]
storeIndex: manager.containerIndex
}
} }

View file

@ -10,6 +10,10 @@ _removed_settings = { #Settings that were removed in 2.5.
"start_layers_at_same_position" "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 ## A collection of functions that convert the configuration of the user in Cura
# 2.4 to a configuration for Cura 2.5. # 2.4 to a configuration for Cura 2.5.
# #
@ -42,8 +46,16 @@ class VersionUpgrade24to25(VersionUpgrade):
#Remove settings from the visible_settings. #Remove settings from the visible_settings.
if parser.has_section("general") and "visible_settings" in parser["general"]: if parser.has_section("general") and "visible_settings" in parser["general"]:
visible_settings = parser["general"]["visible_settings"].split(";") visible_settings = parser["general"]["visible_settings"].split(";")
visible_settings = filter(lambda setting: setting not in _removed_settings, visible_settings) new_visible_settings = []
parser["general"]["visible_settings"] = ";".join(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. #Change the version number in the file.
if parser.has_section("general"): #It better have! if parser.has_section("general"): #It better have!
@ -66,6 +78,10 @@ class VersionUpgrade24to25(VersionUpgrade):
if parser.has_section("values"): 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. 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] 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. #Change the version number in the file.
if parser.has_section("general"): if parser.has_section("general"):

View file

@ -10,6 +10,17 @@
"category": "Custom", "category": "Custom",
"file_formats": "text/x-gcode", "file_formats": "text/x-gcode",
"has_materials": true, "has_materials": true,
"machine_extruder_trains":
{
"0": "custom_extruder_1",
"1": "custom_extruder_2",
"2": "custom_extruder_3",
"3": "custom_extruder_4",
"4": "custom_extruder_5",
"5": "custom_extruder_6",
"6": "custom_extruder_7",
"7": "custom_extruder_8"
},
"first_start_actions": ["MachineSettingsAction"] "first_start_actions": ["MachineSettingsAction"]
} }
} }

View file

@ -29,6 +29,18 @@
"settable_per_meshgroup": false, "settable_per_meshgroup": false,
"settable_globally": false "settable_globally": false
}, },
"machine_nozzle_size":
{
"label": "Nozzle Diameter",
"description": "The inner diameter of the nozzle. Change this setting when using a non-standard nozzle size.",
"unit": "mm",
"type": "float",
"default_value": 0.4,
"minimum_value": "0.001",
"maximum_value_warning": "10",
"settable_per_mesh": false,
"settable_per_extruder": true
},
"machine_nozzle_offset_x": "machine_nozzle_offset_x":
{ {
"label": "Nozzle X Offset", "label": "Nozzle X Offset",

View file

@ -3235,7 +3235,7 @@
"support_bottom_stair_step_height": "support_bottom_stair_step_height":
{ {
"label": "Support 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", "unit": "mm",
"type": "float", "type": "float",
"default_value": 0.3, "default_value": 0.3,
@ -3245,6 +3245,19 @@
"enabled": "support_enable", "enabled": "support_enable",
"settable_per_mesh": true "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": "support_join_distance":
{ {
"label": "Support Join Distance", "label": "Support Join Distance",

View file

@ -0,0 +1,17 @@
{
"id": "custom_extruder_1",
"version": 2,
"name": "Extruder 1",
"inherits": "fdmextruder",
"metadata": {
"machine": "custom",
"position": "0"
},
"overrides": {
"extruder_nr": {
"default_value": 0,
"maximum_value": "7"
}
}
}

View file

@ -0,0 +1,17 @@
{
"id": "custom_extruder_2",
"version": 2,
"name": "Extruder 2",
"inherits": "fdmextruder",
"metadata": {
"machine": "custom",
"position": "1"
},
"overrides": {
"extruder_nr": {
"default_value": 1,
"maximum_value": "7"
}
}
}

View file

@ -0,0 +1,17 @@
{
"id": "custom_extruder_3",
"version": 2,
"name": "Extruder 3",
"inherits": "fdmextruder",
"metadata": {
"machine": "custom",
"position": "2"
},
"overrides": {
"extruder_nr": {
"default_value": 2,
"maximum_value": "7"
}
}
}

View file

@ -0,0 +1,17 @@
{
"id": "custom_extruder_4",
"version": 2,
"name": "Extruder 4",
"inherits": "fdmextruder",
"metadata": {
"machine": "custom",
"position": "3"
},
"overrides": {
"extruder_nr": {
"default_value": 3,
"maximum_value": "7"
}
}
}

View file

@ -0,0 +1,17 @@
{
"id": "custom_extruder_5",
"version": 2,
"name": "Extruder 5",
"inherits": "fdmextruder",
"metadata": {
"machine": "custom",
"position": "4"
},
"overrides": {
"extruder_nr": {
"default_value": 4,
"maximum_value": "7"
}
}
}

View file

@ -0,0 +1,17 @@
{
"id": "custom_extruder_6",
"version": 2,
"name": "Extruder 6",
"inherits": "fdmextruder",
"metadata": {
"machine": "custom",
"position": "5"
},
"overrides": {
"extruder_nr": {
"default_value": 5,
"maximum_value": "7"
}
}
}

View file

@ -0,0 +1,17 @@
{
"id": "custom_extruder_7",
"version": 2,
"name": "Extruder 7",
"inherits": "fdmextruder",
"metadata": {
"machine": "custom",
"position": "6"
},
"overrides": {
"extruder_nr": {
"default_value": 6,
"maximum_value": "7"
}
}
}

View file

@ -0,0 +1,17 @@
{
"id": "custom_extruder_8",
"version": 2,
"name": "Extruder 8",
"inherits": "fdmextruder",
"metadata": {
"machine": "custom",
"position": "7"
},
"overrides": {
"extruder_nr": {
"default_value": 7,
"maximum_value": "7"
}
}
}

View file

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

View file

@ -126,9 +126,11 @@ UM.PreferencesPage
text: catalog.i18nc("@label","Interface") text: catalog.i18nc("@label","Interface")
} }
Row GridLayout
{ {
spacing: UM.Theme.getSize("default_margin").width id: interfaceGrid
columns: 4
Label Label
{ {
id: languageLabel id: languageLabel
@ -189,36 +191,16 @@ UM.PreferencesPage
{ {
id: currencyLabel id: currencyLabel
text: catalog.i18nc("@label","Currency:") text: catalog.i18nc("@label","Currency:")
anchors.verticalCenter: languageComboBox.verticalCenter anchors.verticalCenter: currencyField.verticalCenter
} }
TextField TextField
{ {
id: currencyField id: currencyField
text: UM.Preferences.getValue("cura/currency") text: UM.Preferences.getValue("cura/currency")
onTextChanged: UM.Preferences.setValue("cura/currency", text) onTextChanged: UM.Preferences.setValue("cura/currency", text)
} }
}
Label
{
id: languageCaption
//: Language change warning
text: catalog.i18nc("@label", "You will need to restart the application for language changes to have effect.")
wrapMode: Text.WordWrap
font.italic: true
}
Item
{
//: Spacer
height: UM.Theme.getSize("default_margin").height
width: UM.Theme.getSize("default_margin").width
}
Row
{
spacing: UM.Theme.getSize("default_margin").width
Label Label
{ {
id: themeLabel id: themeLabel
@ -229,6 +211,7 @@ UM.PreferencesPage
ComboBox ComboBox
{ {
id: themeComboBox id: themeComboBox
model: ListModel model: ListModel
{ {
id: themeList id: themeList
@ -264,15 +247,19 @@ UM.PreferencesPage
currentIndex += 1; currentIndex += 1;
currentIndex -= 1; currentIndex -= 1;
} }
} }
} }
Label Label
{ {
id: themeCaption id: languageCaption
//: Theme change warning //: Language change warning
text: catalog.i18nc("@label", "You will need to restart the application for theme changes to have effect.") text: catalog.i18nc("@label", "You will need to restart the application for these changes to have effect.")
wrapMode: Text.WordWrap wrapMode: Text.WordWrap
font.italic: true font.italic: true
} }

View file

@ -179,7 +179,7 @@ Item
Behavior on opacity { NumberAnimation { duration: 100 } } Behavior on opacity { NumberAnimation { duration: 100 } }
enabled: enabled:
{ {
if(!ExtruderManager.activeExtruderStackId && ExtruderManager.extruderCount > 0) if(!ExtruderManager.activeExtruderStackId && machineExtruderCount.properties.value > 1)
{ {
// disable all controls on the global tab, except categories // disable all controls on the global tab, except categories
return model.type == "category" return model.type == "category"

View file

@ -19,7 +19,7 @@ Item
property Action configureSettings; property Action configureSettings;
property variant minimumPrintTime: PrintInformation.minimumPrintTime; property variant minimumPrintTime: PrintInformation.minimumPrintTime;
property variant maximumPrintTime: PrintInformation.maximumPrintTime; property variant maximumPrintTime: PrintInformation.maximumPrintTime;
property bool settingsEnabled: ExtruderManager.activeExtruderStackId || ExtruderManager.extruderCount == 0 property bool settingsEnabled: ExtruderManager.activeExtruderStackId || machineExtruderCount.properties.value == 1
Component.onCompleted: PrintInformation.enabled = true Component.onCompleted: PrintInformation.enabled = true
Component.onDestruction: PrintInformation.enabled = false Component.onDestruction: PrintInformation.enabled = false

View file

@ -247,7 +247,7 @@
}, },
"sizes": { "sizes": {
"window_minimum_size": [70, 54], "window_minimum_size": [70, 50],
"window_margin": [1.0, 1.0], "window_margin": [1.0, 1.0],
"default_margin": [1.0, 1.0], "default_margin": [1.0, 1.0],
"default_lining": [0.08, 0.08], "default_lining": [0.08, 0.08],