diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 53d509b71c..337cac8ef0 100644 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -28,6 +28,7 @@ from cura.SetParentOperation import SetParentOperation from UM.Settings.SettingDefinition import SettingDefinition, DefinitionPropertyType from UM.Settings.ContainerRegistry import ContainerRegistry +from UM.Settings.SettingFunction import SettingFunction from UM.i18n import i18nCatalog @@ -71,7 +72,6 @@ except ImportError: CuraVersion = "master" # [CodeStyle: Reflecting imported value] CuraBuildType = "" - class CuraApplication(QtApplication): class ResourceTypes: QmlFiles = Resources.UserType + 1 @@ -100,6 +100,9 @@ class CuraApplication(QtApplication): SettingDefinition.addSupportedProperty("global_inherits_stack", DefinitionPropertyType.Function, default = "-1") SettingDefinition.addSettingType("extruder", None, str, Validator) + SettingFunction.registerOperator("extruderValues", cura.Settings.ExtruderManager.getExtruderValues) + SettingFunction.registerOperator("extruderValue", cura.Settings.ExtruderManager.getExtruderValue) + ## Add the 4 types of profiles to storage. Resources.addStorageType(self.ResourceTypes.QualityInstanceContainer, "quality") Resources.addStorageType(self.ResourceTypes.VariantInstanceContainer, "variants") @@ -235,7 +238,7 @@ class CuraApplication(QtApplication): support support_enable support_type - support_roof_density + support_interface_density platform_adhesion adhesion_type brim_width diff --git a/cura/MachineAction.py b/cura/MachineAction.py index 6a4df0fce1..b9ff938303 100644 --- a/cura/MachineAction.py +++ b/cura/MachineAction.py @@ -44,6 +44,7 @@ class MachineAction(QObject, PluginObject): # /sa _reset @pyqtSlot() def reset(self): + self._component = None self._finished = False self._reset() diff --git a/cura/PrinterOutputDevice.py b/cura/PrinterOutputDevice.py index 212ed86ab3..153e5f7c42 100644 --- a/cura/PrinterOutputDevice.py +++ b/cura/PrinterOutputDevice.py @@ -35,6 +35,8 @@ class PrinterOutputDevice(QObject, OutputDevice): self._time_total = 0 self._job_state = "" self._job_name = "" + self._error_text = "" + self._accepts_commands = True def requestWrite(self, node, file_name = None, filter_by_machine = False): raise NotImplementedError("requestWrite needs to be implemented") @@ -77,6 +79,10 @@ class PrinterOutputDevice(QObject, OutputDevice): jobNameChanged = pyqtSignal() + errorTextChanged = pyqtSignal() + + acceptsCommandsChanged = pyqtSignal() + @pyqtProperty(str, notify = jobStateChanged) def jobState(self): return self._job_state @@ -102,6 +108,26 @@ class PrinterOutputDevice(QObject, OutputDevice): self._job_name = name self.jobNameChanged.emit() + @pyqtProperty(str, notify = errorTextChanged) + def errorText(self): + return self._error_text + + ## Set the error-text that is shown in the print monitor in case of an error + def setErrorText(self, error_text): + if self._error_text != error_text: + self._error_text = error_text + self.errorTextChanged.emit() + + @pyqtProperty(bool, notify = acceptsCommandsChanged) + def acceptsCommands(self): + return self._accepts_commands + + ## Set a flag to signal the UI that the printer is not (yet) ready to receive commands + def setAcceptsCommands(self, accepts_commands): + if self._accepts_commands != accepts_commands: + self._accepts_commands = accepts_commands + self.acceptsCommandsChanged.emit() + ## Get the bed temperature of the bed (if any) # This function is "final" (do not re-implement) # /sa _getBedTemperature implementation function diff --git a/cura/Settings/ExtruderManager.py b/cura/Settings/ExtruderManager.py index 47359a5e97..0cb9322fd9 100644 --- a/cura/Settings/ExtruderManager.py +++ b/cura/Settings/ExtruderManager.py @@ -6,6 +6,7 @@ from PyQt5.QtCore import pyqtSignal, pyqtProperty, pyqtSlot, QObject, QVariant # import UM.Application #To get the global container stack to find the current machine. import UM.Logger import UM.Settings.ContainerRegistry #Finding containers by ID. +import UM.Settings.SettingFunction ## Manages all existing extruder stacks. @@ -92,6 +93,15 @@ class ExtruderManager(QObject): return self._extruder_trains[global_container_stack.getId()][str(self._active_extruder_index)] return None + ## Get an extruder stack by index + def getExtruderStack(self, index): + global_container_stack = UM.Application.getInstance().getGlobalContainerStack() + if global_container_stack: + if global_container_stack.getId() in self._extruder_trains: + if str(index) in self._extruder_trains[global_container_stack.getId()]: + return self._extruder_trains[global_container_stack.getId()][str(index)] + return None + ## Adds all extruders of a specific machine definition to the extruder # manager. # @@ -273,3 +283,54 @@ class ExtruderManager(QObject): global_stack = UM.Application.getInstance().getGlobalContainerStack() if global_stack and global_stack.getBottom(): self.addMachineExtruders(global_stack.getBottom(), global_stack.getId()) + + ## Get all extruder values for a certain setting. + # + # This is exposed to SettingFunction so it can be used in value functions. + # + # \param key The key of the setting to retieve values for. + # + # \return A list of values for all extruders. If an extruder does not have a value, it will not be in the list. + # If no extruder has the value, the list will contain the global value. + @staticmethod + def getExtruderValues(key): + global_stack = UM.Application.getInstance().getGlobalContainerStack() + + result = [] + for extruder in ExtruderManager.getInstance().getMachineExtruders(global_stack.getId()): + value = extruder.getRawProperty(key, "value") + + if not value: + continue + + if isinstance(value, UM.Settings.SettingFunction): + value = value(extruder) + + result.append(value) + + if not result: + result.append(global_stack.getProperty(key, "value")) + + return result + + ## Get the value for a setting from a specific extruder. + # + # This is exposed to SettingFunction to use in value functions. + # + # \param extruder_index The index of the extruder to get the value from. + # \param key The key of the setting to get the value of. + # + # \return The value of the setting for the specified extruder or None if not found. + @staticmethod + def getExtruderValue(extruder_index, key): + extruder = ExtruderManager.getInstance().getExtruderStack(extruder_index) + value = None + + if extruder: + value = extruder.getRawProperty(key, "value") + if isinstance(value, UM.Settings.SettingFunction): + value = value(extruder) + else: #Just a value from global. + value = UM.Application.getInstance().getGlobalContainerStack().getProperty(key, "value") + + return value diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 9e09ad83be..6a180593c5 100644 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -553,7 +553,7 @@ class MachineManager(QObject): return "" @pyqtSlot(str, str) - def renameQualityContainer(self, container_id, nbalew_name): + def renameQualityContainer(self, container_id, new_name): containers = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(id = container_id, type = "quality") if containers: new_name = self._createUniqueName("quality", containers[0].getName(), new_name, @@ -744,10 +744,7 @@ class MachineManager(QObject): # If the machine that is being removed is the currently active machine, set another machine as the active machine. activate_new_machine = (self._global_container_stack and self._global_container_stack.getId() == machine_id) - stacks = UM.Settings.ContainerRegistry.getInstance().findContainerStacks(id = machine_id) - if not stacks: - return - ExtruderManager.getInstance().removeMachineExtruders(stacks[0].getBottom().getId()) + ExtruderManager.getInstance().removeMachineExtruders(machine_id) containers = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(type = "user", machine = machine_id) for container in containers: diff --git a/cura/Settings/SettingOverrideDecorator.py b/cura/Settings/SettingOverrideDecorator.py index f1e34a939a..f547d283a4 100644 --- a/cura/Settings/SettingOverrideDecorator.py +++ b/cura/Settings/SettingOverrideDecorator.py @@ -10,6 +10,8 @@ from UM.Settings.InstanceContainer import InstanceContainer from UM.Settings.ContainerRegistry import ContainerRegistry import UM.Logger +import cura.Settings + from UM.Application import Application ## A decorator that adds a container stack to a Node. This stack should be queried for all settings regarding @@ -26,7 +28,11 @@ class SettingOverrideDecorator(SceneNodeDecorator): self._stack.setDirty(False) # This stack does not need to be saved. self._instance = InstanceContainer(container_id = "SettingOverrideInstanceContainer") self._stack.addContainer(self._instance) - self._extruder_stack = None #Stack upon which our stack is based. + + if cura.Settings.ExtruderManager.getInstance().extruderCount > 1: + self._extruder_stack = cura.Settings.ExtruderManager.getInstance().activeExtruderStackId + else: + self._extruder_stack = None self._stack.propertyChanged.connect(self._onSettingChanged) @@ -41,6 +47,10 @@ class SettingOverrideDecorator(SceneNodeDecorator): deep_copy = SettingOverrideDecorator() ## Copy the instance deep_copy._instance = copy.deepcopy(self._instance, memo) + + # Properly set the right extruder on the copy + deep_copy.setActiveExtruder(self._extruder_stack) + ## Set the copied instance as the first (and only) instance container of the stack. deep_copy._stack.replaceContainer(0, deep_copy._instance) return deep_copy @@ -61,7 +71,11 @@ class SettingOverrideDecorator(SceneNodeDecorator): if self._extruder_stack: extruder_stack = ContainerRegistry.getInstance().findContainerStacks(id = self._extruder_stack) if extruder_stack: - old_extruder_stack_id = self._stack.getNextStack().getId() + if self._stack.getNextStack(): + old_extruder_stack_id = self._stack.getNextStack().getId() + else: + old_extruder_stack_id = "" + self._stack.setNextStack(extruder_stack[0]) if self._stack.getNextStack().getId() != old_extruder_stack_id: #Only reslice if the extruder changed. Application.getInstance().getBackend().forceSlice() diff --git a/plugins/CuraEngineBackend/CuraEngineBackend.py b/plugins/CuraEngineBackend/CuraEngineBackend.py index a822512218..910705df42 100644 --- a/plugins/CuraEngineBackend/CuraEngineBackend.py +++ b/plugins/CuraEngineBackend/CuraEngineBackend.py @@ -181,6 +181,11 @@ class CuraEngineBackend(Backend): self.slicingCancelled.emit() self.processingProgress.emit(0) Logger.log("d", "Attempting to kill the engine process") + + if Application.getInstance().getCommandLineOption("external-backend", False): + self._createSocket() + return + if self._process is not None: Logger.log("d", "Killing engine process") try: diff --git a/plugins/CuraEngineBackend/StartSliceJob.py b/plugins/CuraEngineBackend/StartSliceJob.py index 5b948c90ab..fc9fd05b44 100644 --- a/plugins/CuraEngineBackend/StartSliceJob.py +++ b/plugins/CuraEngineBackend/StartSliceJob.py @@ -227,7 +227,7 @@ class StartSliceJob(Job): # global_inherits_stack property. def _buildGlobalInheritsStackMessage(self, stack): for key in stack.getAllKeys(): - extruder = int(stack.getProperty(key, "global_inherits_stack")) + extruder = int(round(float(stack.getProperty(key, "global_inherits_stack")))) if extruder >= 0: #Set to a specific extruder. setting_extruder = self._slice_message.addRepeatedMessage("global_inherits_stack") setting_extruder.name = key diff --git a/plugins/GCodeWriter/GCodeWriter.py b/plugins/GCodeWriter/GCodeWriter.py index 8e3be15ffe..c2a932b68c 100644 --- a/plugins/GCodeWriter/GCodeWriter.py +++ b/plugins/GCodeWriter/GCodeWriter.py @@ -90,12 +90,20 @@ class GCodeWriter(MeshWriter): prefix_length = len(prefix) container_with_profile = stack.findContainer({"type": "quality"}) + if not container_with_profile: + Logger.log("e", "No valid quality profile found, not writing settings to GCode!") + return "" + flat_global_container = self._createFlattenedContainerInstance(stack.getTop(),container_with_profile) serialized = flat_global_container.serialize() data = {"global_quality": serialized} for extruder in ExtruderManager.getInstance().getMachineExtruders(stack.getId()): extruder_quality = extruder.findContainer({"type": "quality"}) + if not extruder_quality: + Logger.log("w", "No extruder quality profile found, not writing quality for extruder %s to file!", extruder.getId()) + continue + flat_extruder_quality = self._createFlattenedContainerInstance(extruder.getTop(), extruder_quality) extruder_serialized = flat_extruder_quality.serialize() diff --git a/plugins/PerObjectSettingsTool/PerObjectSettingVisibilityHandler.py b/plugins/PerObjectSettingsTool/PerObjectSettingVisibilityHandler.py index 181c3dea18..e7295c3f97 100644 --- a/plugins/PerObjectSettingsTool/PerObjectSettingVisibilityHandler.py +++ b/plugins/PerObjectSettingsTool/PerObjectSettingVisibilityHandler.py @@ -1,14 +1,18 @@ +# Copyright (c) 2016 Ultimaker B.V. +# Cura is released under the terms of the AGPLv3 or higher. + from PyQt5.QtCore import QObject, pyqtProperty, pyqtSignal + from UM.Application import Application from UM.Settings.SettingInstance import SettingInstance from UM.Logger import Logger - import UM.Settings.Models +from cura.Settings.ExtruderManager import ExtruderManager #To get global-inherits-stack setting values from different extruders. from cura.Settings.SettingOverrideDecorator import SettingOverrideDecorator -## The per object setting visibility handler ensures that only setting defintions that have a matching instance Container -# are returned as visible. +## The per object setting visibility handler ensures that only setting +# definitions that have a matching instance Container are returned as visible. class PerObjectSettingVisibilityHandler(UM.Settings.Models.SettingVisibilityHandler): def __init__(self, parent = None, *args, **kwargs): super().__init__(parent = parent, *args, **kwargs) @@ -54,10 +58,22 @@ class PerObjectSettingVisibilityHandler(UM.Settings.Models.SettingVisibilityHand if not settings.getInstance(item): definition = self._stack.getSettingDefinition(item) if definition: - settings.addInstance(SettingInstance(definition, settings)) + new_instance = SettingInstance(definition, settings) + stack_nr = -1 + if definition.global_inherits_stack and self._stack.getProperty("machine_extruder_count", "value") > 1: + #Obtain the value from the correct container stack. Only once, upon adding the setting. + stack_nr = str(int(round(float(self._stack.getProperty(item, "global_inherits_stack"))))) #Stack to get the setting from. Round it and remove the fractional part. + if stack_nr not in ExtruderManager.getInstance().extruderIds and self._stack.getProperty("extruder_nr", "value"): #Property not defined, but we have an extruder number. + stack_nr = str(int(round(float(self._stack.getProperty("extruder_nr", "value"))))) + if stack_nr in ExtruderManager.getInstance().extruderIds: #We have either a global_inherits_stack or an extruder_nr. + stack = UM.Settings.ContainerRegistry.getInstance().findContainerStacks(id = ExtruderManager.getInstance().extruderIds[stack_nr])[0] + else: + stack = UM.Application.getInstance().getGlobalContainerStack() + new_instance.setProperty("value", stack.getProperty(item, "value")) + settings.addInstance(new_instance) visibility_changed = True else: - Logger.log("w", "Unable to add instance (%s) to perobject visibility because we couldn't find the matching definition", item) + Logger.log("w", "Unable to add instance (%s) to per-object visibility because we couldn't find the matching definition", item) if visibility_changed: self.visibilityChanged.emit() diff --git a/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml b/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml index 482fb73b0f..75cf522c14 100644 --- a/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml +++ b/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml @@ -127,11 +127,7 @@ Item { } } } - Component.onCompleted: - { - // Ensure primary extruder is set as active - UM.ActiveTool.setProperty("SelectedActiveExtruder", extruders_model.getItem(0).id) - } + onActivated: UM.ActiveTool.setProperty("SelectedActiveExtruder", extruders_model.getItem(index).id); onModelChanged: updateCurrentIndex(); diff --git a/plugins/SolidView/SolidView.py b/plugins/SolidView/SolidView.py index 0329fb53e2..d80f077416 100644 --- a/plugins/SolidView/SolidView.py +++ b/plugins/SolidView/SolidView.py @@ -8,6 +8,7 @@ from UM.Resources import Resources from UM.Application import Application from UM.Preferences import Preferences from UM.View.Renderer import Renderer +from UM.Settings.Validator import ValidatorState from UM.View.GL.OpenGL import OpenGL @@ -43,7 +44,7 @@ class SolidView(View): if Application.getInstance().getGlobalContainerStack(): if Preferences.getInstance().getValue("view/show_overhang"): angle = Application.getInstance().getGlobalContainerStack().getProperty("support_angle", "value") - if angle is not None: + if angle is not None and Application.getInstance().getGlobalContainerStack().getProperty("support_angle", "validationState") == ValidatorState.Valid: self._enabled_shader.setUniformValue("u_overhangAngle", math.cos(math.radians(90 - angle))) else: self._enabled_shader.setUniformValue("u_overhangAngle", math.cos(math.radians(0))) #Overhang angle of 0 causes no area at all to be marked as overhang. diff --git a/plugins/VersionUpgrade/VersionUpgrade21to22/VersionUpgrade21to22.py b/plugins/VersionUpgrade/VersionUpgrade21to22/VersionUpgrade21to22.py index 64ea1ac665..a871f969a5 100644 --- a/plugins/VersionUpgrade/VersionUpgrade21to22/VersionUpgrade21to22.py +++ b/plugins/VersionUpgrade/VersionUpgrade21to22/VersionUpgrade21to22.py @@ -34,7 +34,14 @@ _setting_name_translations = { "skirt_line_width": "skirt_brim_line_width", "skirt_minimal_length": "skirt_brim_minimal_length", "skirt_speed": "skirt_brim_speed", - "speed_support_lines": "speed_support_infill" + "speed_support_lines": "speed_support_infill", + "speed_support_roof": "speed_support_interface", + "support_roof_density": "support_interface_density", + "support_roof_enable": "support_interface_enable", + "support_roof_extruder_nr": "support_interface_extruder_nr", + "support_roof_line_distance": "support_interface_line_distance", + "support_roof_line_width": "support_interface_line_width", + "support_roof_pattern": "support_interface_pattern" } ## How to translate variants of specific machines from the old version to the @@ -146,32 +153,11 @@ class VersionUpgrade21to22(VersionUpgrade): for key, value in settings.items(): if key == "fill_perimeter_gaps": #Setting is removed. del settings[key] - elif key == "remove_overlapping_walls_0_enabled": #Setting is functionally replaced. - del settings[key] - settings["travel_compensate_overlapping_walls_0_enabled"] = value - elif key == "remove_overlapping_walls_enabled": #Setting is functionally replaced. - del settings[key] - settings["travel_compensate_overlapping_walls_enabled"] = value - elif key == "remove_overlapping_walls_x_enabled": #Setting is functionally replaced. - del settings[key] - settings["travel_compensate_overlapping_walls_x_enabled"] = value elif key == "retraction_combing": #Combing was made into an enum instead of a boolean. settings[key] = "off" if (value == "False") else "all" - elif key == "retraction_hop": #Setting key was changed. + elif key in _setting_name_translations: del settings[key] - settings["retraction_hop_enabled"] = value - elif key == "skirt_minimal_length": #Setting key was changed. - del settings[key] - settings["skirt_brim_minimal_length"] = value - elif key == "skirt_line_width": #Setting key was changed. - del settings[key] - settings["skirt_brim_line_width"] = value - elif key == "skirt_speed": #Setting key was changed. - del settings[key] - settings["skirt_brim_speed"] = value - elif key == "speed_support_lines": #Setting key was changed. - del settings[key] - settings["speed_support_infill"] = value + settings[_setting_name_translations[key]] = value return settings ## Translates a setting name for the change from Cura 2.1 to 2.2. diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index e7445b6061..7662ed4a6d 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -506,7 +506,7 @@ "default_value": 0.1, "minimum_value": "0.001", "minimum_value_warning": "0.04", - "maximum_value_warning": "0.8 * machine_nozzle_size", + "maximum_value_warning": "0.8 * min(extruderValues('machine_nozzle_size'))", "settable_per_mesh": false, "settable_per_extruder": false }, @@ -519,7 +519,7 @@ "default_value": 0.3, "minimum_value": "0.001", "minimum_value_warning": "0.04", - "maximum_value_warning": "0.8 * machine_nozzle_size", + "maximum_value_warning": "0.8 * min(extruderValues('machine_nozzle_size'))", "settable_per_mesh": false, "settable_per_extruder": false }, @@ -635,16 +635,16 @@ "settable_per_mesh": false, "settable_per_extruder": true }, - "support_roof_line_width": + "support_interface_line_width": { - "label": "Support Roof Line Width", - "description": "Width of a single support roof line.", + "label": "Support Interface Line Width", + "description": "Width of a single support interface line.", "unit": "mm", "default_value": 0.4, "minimum_value": "0.0001", "maximum_value_warning": "machine_nozzle_size * 2", "type": "float", - "enabled": "support_roof_enable", + "enabled": "extruderValue(support_extruder_nr, 'support_interface_enable')", "value": "line_width", "settable_per_mesh": false, "settable_per_extruder": true @@ -1053,7 +1053,7 @@ "unit": "°C", "type": "float", "default_value": 210, - "minimum_value": "0", + "minimum_value": "-273.15", "maximum_value_warning": "260", "enabled": "not (material_flow_dependent_temperature)", "settable_per_mesh": false, @@ -1066,6 +1066,7 @@ "unit": "[[mm³,°C]]", "type": "str", "default_value": "[[3.5,200],[7.0,240]]", + "enabled": "False", "comments": "old enabled function: material_flow_dependent_temperature", "settable_per_mesh": false, "settable_per_extruder": true @@ -1089,7 +1090,7 @@ "unit": "°C", "type": "float", "default_value": 60, - "minimum_value": "0", + "minimum_value": "-273.15", "maximum_value_warning": "260", "enabled": "machine_heated_bed", "settable_per_mesh": false, @@ -1268,7 +1269,7 @@ "type": "float", "unit": "°C", "default_value": 150, - "minimum_value": "0", + "minimum_value": "-273.15", "maximum_value_warning": "260", "settable_per_mesh": false, "settable_per_extruder": true @@ -1462,17 +1463,17 @@ "settable_per_mesh": false, "settable_per_extruder": true }, - "speed_support_roof": + "speed_support_interface": { - "label": "Support Roof Speed", - "description": "The speed at which the roofs of support are printed. Printing the support roof at lower speeds can improve overhang quality.", + "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.", "unit": "mm/s", "type": "float", "default_value": 40, "minimum_value": "0.1", "maximum_value": "299792458000", "maximum_value_warning": "150", - "enabled": "support_roof_enable and support_enable", + "enabled": "extruderValue(support_extruder_nr, 'support_interface_enable') and support_enable", "value": "speed_support / 1.5", "settable_per_mesh": false, "settable_per_extruder": true @@ -1545,8 +1546,8 @@ "minimum_value": "0.1", "maximum_value": "299792458000", "maximum_value_warning": "300", - "settable_per_mesh": true, - "settable_per_extruder": true + "settable_per_extruder": true, + "settable_per_mesh": false } } }, @@ -1693,9 +1694,9 @@ "settable_per_mesh": false, "settable_per_extruder": true }, - "acceleration_support_roof": { - "label": "Support Roof Acceleration", - "description": "The acceleration with which the roofs of support are printed. Printing the support roof at lower accelerations can improve overhang quality.", + "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.", "unit": "mm/s²", "type": "float", "default_value": 3000, @@ -1703,7 +1704,7 @@ "minimum_value": "0.1", "minimum_value_warning": "100", "maximum_value_warning": "10000", - "enabled": "acceleration_enabled and support_roof_enable and support_enable", + "enabled": "acceleration_enabled and extruderValue(support_extruder_nr, 'support_interface_enable') and support_enable", "settable_per_mesh": false, "settable_per_extruder": true } @@ -1748,7 +1749,38 @@ "minimum_value_warning": "100", "maximum_value_warning": "10000", "enabled": "acceleration_enabled", - "settable_per_mesh": true + "settable_per_mesh": true, + "children": { + "acceleration_print_layer_0": + { + "label": "Initial Layer Print Acceleration", + "description": "The acceleration during the printing of the initial layer.", + "unit": "mm/s", + "type": "float", + "default_value": 3000, + "value": "acceleration_layer_0", + "minimum_value": "0.1", + "minimum_value_warning": "100", + "maximum_value_warning": "10000", + "enabled": "acceleration_enabled", + "settable_per_mesh": true + }, + "acceleration_travel_layer_0": + { + "label": "Initial Layer Travel Acceleration", + "description": "The acceleration for travel moves in the initial layer.", + "unit": "mm/s", + "type": "float", + "default_value": 3000, + "value": "acceleration_layer_0 * acceleration_travel / acceleration_print", + "minimum_value": "0.1", + "minimum_value_warning": "100", + "maximum_value_warning": "10000", + "enabled": "acceleration_enabled", + "settable_per_extruder": true, + "settable_per_mesh": false + } + } }, "acceleration_skirt_brim": { "label": "Skirt/Brim Acceleration", @@ -1881,9 +1913,9 @@ "settable_per_mesh": false, "settable_per_extruder": true }, - "jerk_support_roof": { - "label": "Support Roof Jerk", - "description": "The maximum instantaneous velocity change with which the roofs of support are printed.", + "jerk_support_interface": { + "label": "Support Interface Jerk", + "description": "The maximum instantaneous velocity change with which the roofs and bottoms of support are printed.", "unit": "mm/s", "type": "float", "default_value": 20, @@ -1891,7 +1923,7 @@ "minimum_value": "0.1", "minimum_value_warning": "5", "maximum_value_warning": "50", - "enabled": "jerk_enabled and support_roof_enable and support_enable", + "enabled": "jerk_enabled and extruderValue(support_extruder_nr, 'support_interface_enable') and support_enable", "settable_per_mesh": false, "settable_per_extruder": true } @@ -1936,7 +1968,38 @@ "minimum_value_warning": "5", "maximum_value_warning": "50", "enabled": "jerk_enabled", - "settable_per_mesh": true + "settable_per_mesh": true, + "children": { + "jerk_print_layer_0": + { + "label": "Initial Layer Print Jerk", + "description": "The maximum instantaneous velocity change during the printing of the initial layer.", + "unit": "mm/s", + "type": "float", + "default_value": 20, + "value": "jerk_layer_0", + "minimum_value": "0.1", + "minimum_value_warning": "5", + "maximum_value_warning": "50", + "enabled": "jerk_enabled", + "settable_per_mesh": true + }, + "jerk_travel_layer_0": + { + "label": "Initial Layer Travel Jerk", + "description": "The acceleration for travel moves in the initial layer.", + "unit": "mm/s", + "type": "float", + "default_value": 20, + "value": "jerk_layer_0 * jerk_travel / jerk_print", + "minimum_value": "0.1", + "minimum_value_warning": "5", + "maximum_value_warning": "50", + "enabled": "jerk_enabled", + "settable_per_extruder": true, + "settable_per_mesh": false + } + } }, "jerk_skirt_brim": { "label": "Skirt/Brim Jerk", @@ -2207,7 +2270,7 @@ "description": "Connect the ZigZags. This will increase the strength of the zig zag support structure.", "type": "bool", "default_value": true, - "enabled": "support_enable and (support_pattern == \"zigzag\")", + "enabled": "support_enable and (support_pattern == 'zigzag')", "settable_per_mesh": false, "settable_per_extruder": true }, @@ -2263,7 +2326,7 @@ "default_value": 0.15, "type": "float", "enabled": "support_enable", - "value": "support_z_distance", + "value": "extruderValue(support_extruder_nr, 'support_z_distance')", "global_inherits_stack": "support_extruder_nr", "settable_per_mesh": true }, @@ -2319,7 +2382,7 @@ "default_value": 0.2, "value": "machine_nozzle_size / 2", "global_inherits_stack": "support_extruder_nr", - "enabled": "support_enable and support_xy_overrides_z=='z_overrides_xy'", + "enabled": "support_enable and extruderValue(support_extruder_nr, 'support_xy_overrides_z') == 'z_overrides_xy'", "settable_per_mesh": true }, "support_bottom_stair_step_height": @@ -2374,62 +2437,96 @@ "enabled": "support_enable", "settable_per_mesh": true }, - "support_roof_enable": + "support_interface_enable": { - "label": "Enable Support Roof", - "description": "Generate a dense top skin at the top of the support on which the model is printed.", + "label": "Enable Support Interface", + "description": "Generate a dense interface between the model and the support. This will create a skin at the top of the support on which the model is printed and at the bottom of the support, where it rests on the model.", "type": "bool", "default_value": false, "global_inherits_stack": "support_extruder_nr", "enabled": "support_enable", "settable_per_mesh": true }, - "support_roof_height": + "support_interface_height": { - "label": "Support Roof Thickness", - "description": "The thickness of the support roofs.", + "label": "Support Interface Thickness", + "description": "The thickness of the interface of the support where it touches with the model on the bottom or the top.", "unit": "mm", "type": "float", "default_value": 1, "minimum_value": "0", "global_inherits_stack": "support_extruder_nr", "maximum_value_warning": "10", - "enabled": "support_roof_enable and support_enable", - "settable_per_mesh": true + "enabled": "extruderValue(support_extruder_nr, 'support_interface_enable') and support_enable", + "settable_per_mesh": true, + "children": + { + "support_roof_height": + { + "label": "Support Roof Thickness", + "description": "The thickness of the support roofs. This controls the amount of dense layers at the top of the support on which the model rests.", + "unit": "mm", + "type": "float", + "default_value": 1, + "value": "extruderValue(support_extruder_nr, 'support_interface_height')", + "minimum_value": "0", + "global_inherits_stack": "support_extruder_nr", + "maximum_value_warning": "10", + "enabled": "extruderValue(support_extruder_nr, 'support_interface_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.", + "unit": "mm", + "type": "float", + "default_value": 1, + "value": "extruderValue(support_extruder_nr, 'support_interface_height')", + "minimum_value": "0", + "minimum_value_warning": "extruderValue(support_extruder_nr, 'support_bottom_stair_step_height')", + "global_inherits_stack": "support_extruder_nr", + "maximum_value_warning": "10", + "enabled": "extruderValue(support_extruder_nr, 'support_interface_enable') and support_enable", + "settable_per_mesh": true + } + } }, - "support_roof_density": + "support_interface_density": { - "label": "Support Roof Density", - "description": "Adjusts the density of the roof of the support structure. A higher value results in better overhangs, but the supports are harder to remove.", + "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.", "unit": "%", "type": "float", "default_value": 100, "minimum_value": "0", "maximum_value_warning": "100", - "enabled":"support_roof_enable and support_enable", + "global_inherits_stack": "support_extruder_nr", + "enabled": "extruderValue(support_extruder_nr, 'support_interface_enable') and support_enable", "settable_per_mesh": false, "settable_per_extruder": true, "children": { - "support_roof_line_distance": + "support_interface_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.", + "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.", "unit": "mm", "type": "float", "default_value": 0.4, "minimum_value": "0", - "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))", - "enabled": "support_roof_enable and support_enable", + "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))", + "global_inherits_stack": "support_extruder_nr", + "enabled": "extruderValue(support_extruder_nr, 'support_interface_enable') and support_enable", "settable_per_mesh": false, "settable_per_extruder": true } } }, - "support_roof_pattern": + "support_interface_pattern": { - "label": "Support Roof Pattern", - "description": "The pattern with which the top of the support is printed.", + "label": "Support Interface Pattern", + "description": "The pattern with which the interface of the support with the model is printed.", "type": "enum", "options": { @@ -2440,7 +2537,8 @@ "zigzag": "Zig Zag" }, "default_value": "concentric", - "enabled": "support_roof_enable and support_enable", + "global_inherits_stack": "support_extruder_nr", + "enabled": "extruderValue(support_extruder_nr, 'support_interface_enable') and support_enable", "settable_per_mesh": false, "settable_per_extruder": true }, @@ -2464,7 +2562,7 @@ "global_inherits_stack": "support_extruder_nr", "minimum_value": "0", "maximum_value_warning": "10", - "enabled": "support_enable and support_use_towers", + "enabled": "support_enable and extruderValue(support_extruder_nr, 'support_use_towers')", "settable_per_mesh": true }, "support_minimal_diameter": @@ -2477,8 +2575,8 @@ "global_inherits_stack": "support_extruder_nr", "minimum_value": "0", "maximum_value_warning": "10", - "maximum_value": "support_tower_diameter", - "enabled": "support_enable and support_use_towers", + "maximum_value": "extruderValue(support_extruder_nr, 'support_tower_diameter')", + "enabled": "support_enable and extruderValue(support_extruder_nr, 'support_use_towers')", "settable_per_mesh": true }, "support_tower_roof_angle": @@ -2491,7 +2589,7 @@ "maximum_value": "90", "default_value": 65, "global_inherits_stack": "support_extruder_nr", - "enabled": "support_enable and support_use_towers", + "enabled": "support_enable and extruderValue(support_extruder_nr, 'support_use_towers')", "settable_per_mesh": true } } @@ -3075,14 +3173,14 @@ "settable_per_mesh": false, "settable_per_extruder": false }, - "support_roof_extruder_nr": + "support_interface_extruder_nr": { - "label": "Support Roof Extruder", - "description": "The extruder train to use for printing the roof of the support. This is used in multi-extrusion.", + "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.", "type": "extruder", "default_value": "0", "value": "support_extruder_nr", - "enabled": "support_enable and support_roof_enable", + "enabled": "support_enable and extruderValue(support_extruder_nr, 'support_interface_enable')", "settable_per_mesh": false, "settable_per_extruder": false } diff --git a/resources/definitions/mankati_fullscale_xt_plus.def.json b/resources/definitions/mankati_fullscale_xt_plus.def.json index eb8b99aaf9..72c8ebdd86 100644 --- a/resources/definitions/mankati_fullscale_xt_plus.def.json +++ b/resources/definitions/mankati_fullscale_xt_plus.def.json @@ -54,13 +54,13 @@ "speed_travel": { "default_value": 150 }, "speed_layer_0": { "minimum_value": "0.1", - "default": 15.0 + "default_value": 15.0 }, - "infill_overlap": { "default": 10 }, - "cool_fan_enabled": { "default": false }, - "cool_fan_speed": { "default": 0 }, - "skirt_line_count": { "default": 3 }, - "skirt_gap": { "default": 4 }, - "skirt_brim_minimal_length": { "default": 200 } + "infill_overlap": { "default_value": 10 }, + "cool_fan_enabled": { "default_value": false }, + "cool_fan_speed": { "default_value": 0 }, + "skirt_line_count": { "default_value": 3 }, + "skirt_gap": { "default_value": 4 }, + "skirt_brim_minimal_length": { "default_value": 200 } } } diff --git a/resources/definitions/ultimaker.def.json b/resources/definitions/ultimaker.def.json index 5df38d07cb..dc52b00dcc 100644 --- a/resources/definitions/ultimaker.def.json +++ b/resources/definitions/ultimaker.def.json @@ -7,5 +7,16 @@ "author": "Ultimaker", "manufacturer": "Ultimaker", "visible": false + }, + "overrides": { + "material_print_temperature": { + "minimum_value": "0" + }, + "material_bed_temperature": { + "minimum_value": "0" + }, + "material_standby_temperature": { + "minimum_value": "0" + } } } diff --git a/resources/definitions/ultimaker2.def.json b/resources/definitions/ultimaker2.def.json index d8e73a7e14..9985dea764 100644 --- a/resources/definitions/ultimaker2.def.json +++ b/resources/definitions/ultimaker2.def.json @@ -8,6 +8,7 @@ "author": "Ultimaker", "manufacturer": "Ultimaker", "category": "Ultimaker", + "weight": 3, "file_formats": "text/x-gcode", "icon": "icon_ultimaker2.png", "platform": "ultimaker2_platform.obj", @@ -82,10 +83,10 @@ "default_value": 45 }, "material_print_temperature": { - "enabled": "False" + "enabled": "not (material_flow_dependent_temperature) and machine_gcode_flavor != \"UltiGCode\"" }, "material_bed_temperature": { - "enabled": "False" + "enabled": "machine_heated_bed and machine_gcode_flavor != \"UltiGCode\"" }, "machine_max_feedrate_x": { "default_value": 300 @@ -103,22 +104,22 @@ "default_value": 3000 }, "material_diameter": { - "enabled": "False" + "enabled": "machine_gcode_flavor != \"UltiGCode\"" }, "material_flow": { - "enabled": "False" + "enabled": "machine_gcode_flavor != \"UltiGCode\"" }, "retraction_amount": { - "enabled": "False" + "enabled": "retraction_enable and machine_gcode_flavor != \"UltiGCode\"" }, "retraction_speed": { - "enabled": "False" + "enabled": "retraction_enable and machine_gcode_flavor != \"UltiGCode\"" }, "retraction_retract_speed": { - "enabled": "False" + "enabled": "retraction_enable and machine_gcode_flavor != \"UltiGCode\"" }, "retraction_prime_speed": { - "enabled": "False" + "enabled": "retraction_enable and machine_gcode_flavor != \"UltiGCode\"" } } } diff --git a/resources/definitions/ultimaker2_extended.def.json b/resources/definitions/ultimaker2_extended.def.json index fb443365f2..889046694c 100644 --- a/resources/definitions/ultimaker2_extended.def.json +++ b/resources/definitions/ultimaker2_extended.def.json @@ -7,6 +7,7 @@ "author": "Ultimaker", "manufacturer": "Ultimaker", "category": "Ultimaker", + "weight": 3, "file_formats": "text/x-gcode", "icon": "icon_ultimaker2.png", "platform": "ultimaker2_platform.obj", diff --git a/resources/definitions/ultimaker2_extended_plus.def.json b/resources/definitions/ultimaker2_extended_plus.def.json index f4190be83d..ea97033878 100644 --- a/resources/definitions/ultimaker2_extended_plus.def.json +++ b/resources/definitions/ultimaker2_extended_plus.def.json @@ -7,6 +7,7 @@ "author": "Ultimaker", "manufacturer": "Ultimaker", "category": "Ultimaker", + "weight": 2, "file_formats": "text/x-gcode", "platform": "ultimaker2_platform.obj", "platform_texture": "Ultimaker2ExtendedPlusbackplate.png", diff --git a/resources/definitions/ultimaker2_go.def.json b/resources/definitions/ultimaker2_go.def.json index 27b179eef9..107d413296 100644 --- a/resources/definitions/ultimaker2_go.def.json +++ b/resources/definitions/ultimaker2_go.def.json @@ -7,6 +7,7 @@ "author": "Ultimaker", "manufacturer": "Ultimaker", "category": "Ultimaker", + "weight": 3, "file_formats": "text/x-gcode", "icon": "icon_ultimaker2.png", "platform": "ultimaker2go_platform.obj", diff --git a/resources/definitions/ultimaker2_plus.def.json b/resources/definitions/ultimaker2_plus.def.json index d5a7c9f4f1..4c7279b178 100644 --- a/resources/definitions/ultimaker2_plus.def.json +++ b/resources/definitions/ultimaker2_plus.def.json @@ -7,6 +7,7 @@ "author": "Ultimaker", "manufacturer": "Ultimaker", "category": "Ultimaker", + "weight": 1, "file_formats": "text/x-gcode", "platform": "ultimaker2_platform.obj", "platform_texture": "Ultimaker2Plusbackplate.png", diff --git a/resources/definitions/ultimaker_original.def.json b/resources/definitions/ultimaker_original.def.json index 0815aeee02..3dd4766afa 100644 --- a/resources/definitions/ultimaker_original.def.json +++ b/resources/definitions/ultimaker_original.def.json @@ -8,6 +8,7 @@ "author": "Ultimaker", "manufacturer": "Ultimaker", "category": "Ultimaker", + "weight": 4, "file_formats": "text/x-gcode", "icon": "icon_ultimaker.png", "platform": "ultimaker_platform.stl", diff --git a/resources/definitions/ultimaker_original_plus.def.json b/resources/definitions/ultimaker_original_plus.def.json index 4d39a39a78..2c83070add 100644 --- a/resources/definitions/ultimaker_original_plus.def.json +++ b/resources/definitions/ultimaker_original_plus.def.json @@ -7,11 +7,13 @@ "author": "Ultimaker", "manufacturer": "Ultimaker", "category": "Ultimaker", + "weight": 4, "file_formats": "text/x-gcode", "icon": "icon_ultimaker.png", "platform": "ultimaker2_platform.obj", "platform_texture": "UltimakerPlusbackplate.png", - "supported_actions":["UMOCheckup", "UpgradeFirmware", "BedLevel"] + "first_start_actions": ["UMOCheckup", "BedLevel"], + "supported_actions": ["UMOCheckup", "BedLevel", "UpgradeFirmware"] }, "overrides": { diff --git a/resources/qml/AddMachineDialog.qml b/resources/qml/AddMachineDialog.qml index 350435d1ca..e37629306b 100644 --- a/resources/qml/AddMachineDialog.qml +++ b/resources/qml/AddMachineDialog.qml @@ -16,6 +16,7 @@ UM.Dialog { id: base title: catalog.i18nc("@title:window", "Add Printer") + property bool firstRun: false property string preferredCategory: "Ultimaker" property string activeCategory: preferredCategory @@ -32,7 +33,7 @@ UM.Dialog signal machineAdded(string id) function getMachineName() { - var name = machineList.model.get(machineList.currentIndex).name + var name = machineList.model.getItem(machineList.currentIndex) != undefined ? machineList.model.getItem(machineList.currentIndex).name : "" return name } @@ -52,27 +53,15 @@ UM.Dialog { id: machineList - model: ListModel + model: UM.DefinitionContainersModel { - id: sortedMachineDefinitionsModel - Component.onCompleted: { - // DefinitionContainersModel is sorted alphabetically, but we want the preferred - // category on top so we create a custom-sorted ListModel from it. - var items = []; - for(var i in machineDefinitionsModel.items) { - var item = machineDefinitionsModel.getItem(i); - if (item["category"] == preferredCategory) - sortedMachineDefinitionsModel.append(item); - else - items.push(item); - } - for(var i in items) { - sortedMachineDefinitionsModel.append(items[i]); - } - } + id: machineDefinitionsModel + filter: { "visible": true } + sectionProperty: "category" + preferredSectionValue: preferredCategory } - section.property: "category" + section.property: "section" section.delegate: Button { text: section @@ -111,11 +100,11 @@ UM.Dialog onClicked: { base.activeCategory = section; - if (machineList.model.get(machineList.currentIndex).category != section) { - // Find the first machine from this category + if (machineList.model.getItem(machineList.currentIndex).section != section) { + // Find the first machine from this section for(var i = 0; i < sortedMachineDefinitionsModel.count; i++) { - var item = sortedMachineDefinitionsModel.get(i); - if (item.category == section) { + var item = sortedMachineDefinitionsModel.getItem(i); + if (item.section == section) { machineList.currentIndex = i; break; } @@ -150,7 +139,7 @@ UM.Dialog states: State { name: "collapsed"; - when: base.activeCategory != model.category; + when: base.activeCategory != model.section; PropertyChanges { target: machineButton; opacity: 0; height: 0; } } @@ -194,13 +183,17 @@ UM.Dialog text: catalog.i18nc("@action:button", "Add Printer") anchors.bottom: parent.bottom anchors.right: parent.right - onClicked: - { - base.visible = false - var item = machineList.model.get(machineList.currentIndex); - Cura.MachineManager.addMachine(machineName.text, item.id) - base.machineAdded(item.id) // Emit signal that the user added a machine. - } + onClicked: addMachine() + } + + onAccepted: addMachine() + + function addMachine() + { + base.visible = false + var item = machineList.model.getItem(machineList.currentIndex); + Cura.MachineManager.addMachine(machineName.text, item.id) + base.machineAdded(item.id) // Emit signal that the user added a machine. } Item @@ -210,11 +203,6 @@ UM.Dialog id: catalog; name: "cura"; } - UM.DefinitionContainersModel - { - id: machineDefinitionsModel - filter: { "visible": true } - } SystemPalette { id: palette } ExclusiveGroup { id: printerGroup; } } diff --git a/resources/qml/AddMachineWizard.qml b/resources/qml/AddMachineWizard.qml deleted file mode 100644 index 1c743834de..0000000000 --- a/resources/qml/AddMachineWizard.qml +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) 2015 Ultimaker B.V. -// Cura is released under the terms of the AGPLv3 or higher. - -import QtQuick 2.2 -import QtQuick.Controls 1.1 -import QtQuick.Layouts 1.1 -import QtQuick.Window 2.1 - -import UM 1.1 as UM -import Cura 1.0 as Cura - -import "WizardPages" - -UM.Wizard -{ - id: base; - - title: catalog.i18nc("@title:window", "Add Printer") - - // This part is optional - // This part checks whether there is a printer -> if not: some of the functions (delete for example) are disabled - firstRun: false - - Component.onCompleted: { - base.appendPage(Qt.resolvedUrl("WizardPages/AddMachine.qml"), catalog.i18nc("@title", "Add Printer")); - base.currentPage = 0; - } - - Item { - UM.I18nCatalog { id: catalog; name: "cura"; } - } -} diff --git a/resources/qml/Cura.qml b/resources/qml/Cura.qml index ae72353e0e..5f45a062b8 100644 --- a/resources/qml/Cura.qml +++ b/resources/qml/Cura.qml @@ -677,6 +677,7 @@ UM.MainWindow id: addMachineDialog onMachineAdded: { + machineActionsWizard.firstRun = addMachineDialog.firstRun machineActionsWizard.start(id) } } diff --git a/resources/qml/MachineAction.qml b/resources/qml/MachineAction.qml index 59fb3946a3..2c43f9f96d 100644 --- a/resources/qml/MachineAction.qml +++ b/resources/qml/MachineAction.qml @@ -3,6 +3,10 @@ import QtQuick 2.2 Item { id: contentItem + + // Point to the dialog containing the displayItem + property var dialog + // Connect the finished property change to completed signal. property var finished: manager.finished onFinishedChanged: if(manager.finished) {completed()} diff --git a/resources/qml/MonitorButton.qml b/resources/qml/MonitorButton.qml index 4a33b347d3..8aefe52f9f 100644 --- a/resources/qml/MonitorButton.qml +++ b/resources/qml/MonitorButton.qml @@ -15,25 +15,33 @@ Rectangle UM.I18nCatalog { id: catalog; name:"cura"} property bool printerConnected: Cura.MachineManager.printerOutputDevices.length != 0 - property real progress: printerConnected ? Cura.MachineManager.printerOutputDevices[0].progress : 0; - property int backendState: UM.Backend.state; + property bool printerAcceptsCommands: printerConnected && Cura.MachineManager.printerOutputDevices[0].acceptsCommands + property real progress: printerConnected ? Cura.MachineManager.printerOutputDevices[0].progress : 0 + property int backendState: UM.Backend.state property variant statusColor: { - if(!printerConnected) - return UM.Theme.getColor("status_offline") - else if(Cura.MachineManager.printerOutputDevices[0].jobState == "printing" || Cura.MachineManager.printerOutputDevices[0].jobState == "pre_print" || Cura.MachineManager.printerOutputDevices[0].jobState == "wait_cleanup" ) - return UM.Theme.getColor("status_busy") - else if(Cura.MachineManager.printerOutputDevices[0].jobState == "ready" || Cura.MachineManager.printerOutputDevices[0].jobState == "") - return UM.Theme.getColor("status_ready") - else if(Cura.MachineManager.printerOutputDevices[0].jobState == "paused") - return UM.Theme.getColor("status_paused") - else if (Cura.MachineManager.printerOutputDevices[0].jobState == "error") - return UM.Theme.getColor("status_stopped") - else if (Cura.MachineManager.printerOutputDevices[0].jobState == "offline") - return UM.Theme.getColor("status_offline") - else - return UM.Theme.getColor("text") + if(!printerConnected || !printerAcceptsCommands) + return UM.Theme.getColor("text"); + + switch(Cura.MachineManager.printerOutputDevices[0].jobState) + { + case "printing": + case "pre_print": + case "wait_cleanup": + return UM.Theme.getColor("status_busy"); + case "ready": + case "": + return UM.Theme.getColor("status_ready"); + case "paused": + return UM.Theme.getColor("status_paused"); + case "error": + return UM.Theme.getColor("status_stopped"); + case "offline": + return UM.Theme.getColor("status_offline"); + default: + return UM.Theme.getColor("text"); + } } property bool activity: Printer.getPlatformActivity; @@ -42,31 +50,28 @@ Rectangle property string statusText: { if(!printerConnected) - { - return catalog.i18nc("@label:", "Not connected to a printer") - } else if(Cura.MachineManager.printerOutputDevices[0].jobState == "offline") - { - return catalog.i18nc("@label:", "Lost connection with the printer") - } else if(Cura.MachineManager.printerOutputDevices[0].jobState == "printing") - { - return catalog.i18nc("@label:", "Printing...") - } else if(Cura.MachineManager.printerOutputDevices[0].jobState == "paused") - { - return catalog.i18nc("@label:", "Paused") - } - else if(Cura.MachineManager.printerOutputDevices[0].jobState == "pre_print") - { - return catalog.i18nc("@label:", "Preparing...") - } - else if(Cura.MachineManager.printerOutputDevices[0].jobState == "wait_cleanup") - { - return catalog.i18nc("@label:", "Waiting for cleanup...") - } - else - { - return " " - } + return catalog.i18nc("@label:MonitorStatus", "Not connected to a printer"); + if(!printerAcceptsCommands) + return catalog.i18nc("@label:MonitorStatus", "Printer does not accept commands"); + var printerOutputDevice = Cura.MachineManager.printerOutputDevices[0] + switch(printerOutputDevice.jobState) + { + case "offline": + return catalog.i18nc("@label:MonitorStatus", "Lost connection with the printer"); + case "printing": + return catalog.i18nc("@label:MonitorStatus", "Printing..."); + case "paused": + return catalog.i18nc("@label:MonitorStatus", "Paused"); + case "pre_print": + return catalog.i18nc("@label:MonitorStatus", "Preparing..."); + case "wait_cleanup": + return catalog.i18nc("@label:MonitorStatus", "Please remove the print"); + case "error": + return printerOutputDevice.errorText; + default: + return " "; + } } Label @@ -79,7 +84,7 @@ Rectangle color: base.statusColor font: UM.Theme.getFont("large") - text: statusText; + text: statusText } Label @@ -90,7 +95,7 @@ Rectangle color: base.statusColor font: UM.Theme.getFont("large") - text: Math.round(progress) + "%"; + text: Math.round(progress) + "%" visible: printerConnected } @@ -120,7 +125,8 @@ Rectangle id: abortButton visible: printerConnected - enabled: printerConnected && (Cura.MachineManager.printerOutputDevices[0].jobState == "paused" || Cura.MachineManager.printerOutputDevices[0].jobState == "printing") + enabled: printerConnected && Cura.MachineManager.printerOutputDevices[0].acceptsCommands && + (Cura.MachineManager.printerOutputDevices[0].jobState == "paused" || Cura.MachineManager.printerOutputDevices[0].jobState == "printing") height: UM.Theme.getSize("save_button_save_to_button").height anchors.top: progressBar.bottom @@ -129,7 +135,7 @@ Rectangle anchors.rightMargin: UM.Theme.getSize("default_margin").width text: catalog.i18nc("@label:", "Abort Print") - onClicked: { Cura.MachineManager.printerOutputDevices[0].setJobState("abort") } + onClicked: Cura.MachineManager.printerOutputDevices[0].setJobState("abort") style: ButtonStyle @@ -137,12 +143,28 @@ Rectangle background: Rectangle { border.width: UM.Theme.getSize("default_lining").width - border.color: !control.enabled ? UM.Theme.getColor("action_button_disabled_border") : - control.pressed ? UM.Theme.getColor("action_button_active_border") : - control.hovered ? UM.Theme.getColor("action_button_hovered_border") : UM.Theme.getColor("action_button_border") - color: !control.enabled ? UM.Theme.getColor("action_button_disabled") : - control.pressed ? UM.Theme.getColor("action_button_active") : - control.hovered ? UM.Theme.getColor("action_button_hovered") : UM.Theme.getColor("action_button") + border.color: + { + if(!control.enabled) + return UM.Theme.getColor("action_button_disabled_border"); + else if(control.pressed) + return UM.Theme.getColor("action_button_active_border"); + else if(control.hovered) + return UM.Theme.getColor("action_button_hovered_border"); + else + return UM.Theme.getColor("action_button_border"); + } + color: + { + if(!control.enabled) + return UM.Theme.getColor("action_button_disabled"); + else if(control.pressed) + return UM.Theme.getColor("action_button_active"); + else if(control.hovered) + return UM.Theme.getColor("action_button_hovered"); + else + return UM.Theme.getColor("action_button"); + } Behavior on color { ColorAnimation { duration: 50; } } implicitWidth: actualLabel.contentWidth + (UM.Theme.getSize("default_margin").width * 2) @@ -151,9 +173,17 @@ Rectangle { id: actualLabel anchors.centerIn: parent - color: !control.enabled ? UM.Theme.getColor("action_button_disabled_text") : - control.pressed ? UM.Theme.getColor("action_button_active_text") : - control.hovered ? UM.Theme.getColor("action_button_hovered_text") : UM.Theme.getColor("action_button_text") + color: + { + if(!control.enabled) + return UM.Theme.getColor("action_button_disabled_text"); + else if(control.pressed) + return UM.Theme.getColor("action_button_active_text"); + else if(control.hovered) + return UM.Theme.getColor("action_button_hovered_text"); + else + return UM.Theme.getColor("action_button_text"); + } font: UM.Theme.getFont("action_button") text: control.text; } @@ -164,10 +194,7 @@ Rectangle Button { - id: pauseButton - - visible: printerConnected - enabled: printerConnected && (Cura.MachineManager.printerOutputDevices[0].jobState == "paused" || Cura.MachineManager.printerOutputDevices[0].jobState == "printing") + id: pauseResumeButton height: UM.Theme.getSize("save_button_save_to_button").height anchors.top: progressBar.bottom @@ -175,20 +202,40 @@ Rectangle anchors.right: abortButton.left anchors.rightMargin: UM.Theme.getSize("default_margin").width + visible: printerConnected + enabled: printerConnected && Cura.MachineManager.printerOutputDevices[0].acceptsCommands && + (Cura.MachineManager.printerOutputDevices[0].jobState == "paused" || Cura.MachineManager.printerOutputDevices[0].jobState == "printing") + text: printerConnected ? Cura.MachineManager.printerOutputDevices[0].jobState == "paused" ? catalog.i18nc("@label:", "Resume") : catalog.i18nc("@label:", "Pause") : "" - onClicked: { Cura.MachineManager.printerOutputDevices[0].jobState == "paused" ? Cura.MachineManager.printerOutputDevices[0].setJobState("print") : Cura.MachineManager.printerOutputDevices[0].setJobState("pause") } + onClicked: Cura.MachineManager.printerOutputDevices[0].setJobState(Cura.MachineManager.printerOutputDevices[0].jobState == "paused" ? "print" : "pause") style: ButtonStyle { background: Rectangle { border.width: UM.Theme.getSize("default_lining").width - border.color: !control.enabled ? UM.Theme.getColor("action_button_disabled_border") : - control.pressed ? UM.Theme.getColor("action_button_active_border") : - control.hovered ? UM.Theme.getColor("action_button_hovered_border") : UM.Theme.getColor("action_button_border") - color: !control.enabled ? UM.Theme.getColor("action_button_disabled") : - control.pressed ? UM.Theme.getColor("action_button_active") : - control.hovered ? UM.Theme.getColor("action_button_hovered") : UM.Theme.getColor("action_button") + border.color: + { + if(!control.enabled) + return UM.Theme.getColor("action_button_disabled_border"); + else if(control.pressed) + return UM.Theme.getColor("action_button_active_border"); + else if(control.hovered) + return UM.Theme.getColor("action_button_hovered_border"); + else + return UM.Theme.getColor("action_button_border"); + } + color: + { + if(!control.enabled) + return UM.Theme.getColor("action_button_disabled"); + else if(control.pressed) + return UM.Theme.getColor("action_button_active"); + else if(control.hovered) + return UM.Theme.getColor("action_button_hovered"); + else + return UM.Theme.getColor("action_button"); + } Behavior on color { ColorAnimation { duration: 50; } } implicitWidth: actualLabel.contentWidth + (UM.Theme.getSize("default_margin").width * 2) @@ -197,11 +244,19 @@ Rectangle { id: actualLabel anchors.centerIn: parent - color: !control.enabled ? UM.Theme.getColor("action_button_disabled_text") : - control.pressed ? UM.Theme.getColor("action_button_active_text") : - control.hovered ? UM.Theme.getColor("action_button_hovered_text") : UM.Theme.getColor("action_button_text") + color: + { + if(!control.enabled) + return UM.Theme.getColor("action_button_disabled_text"); + else if(control.pressed) + return UM.Theme.getColor("action_button_active_text"); + else if(control.hovered) + return UM.Theme.getColor("action_button_hovered_text"); + else + return UM.Theme.getColor("action_button_text"); + } font: UM.Theme.getFont("action_button") - text: control.text; + text: control.text } } label: Item { } diff --git a/resources/qml/Preferences/GeneralPage.qml b/resources/qml/Preferences/GeneralPage.qml index 223b7eda85..07a188713f 100644 --- a/resources/qml/Preferences/GeneralPage.qml +++ b/resources/qml/Preferences/GeneralPage.qml @@ -69,6 +69,7 @@ UM.PreferencesPage Row { + spacing: UM.Theme.getSize("default_margin").width Label { id: languageLabel diff --git a/resources/qml/Preferences/MachinesPage.qml b/resources/qml/Preferences/MachinesPage.qml index b057a33d52..ca9184ae6b 100644 --- a/resources/qml/Preferences/MachinesPage.qml +++ b/resources/qml/Preferences/MachinesPage.qml @@ -83,16 +83,17 @@ UM.ManagementPage Repeater { id: machineActionRepeater - model: Cura.MachineActionManager.getSupportedActions(Cura.MachineManager.getDefinitionByMachineId(base.currentItem.id)) + model: base.currentItem ? Cura.MachineActionManager.getSupportedActions(Cura.MachineManager.getDefinitionByMachineId(base.currentItem.id)) : null Button { - text: machineActionRepeater.model[index].label; + text: machineActionRepeater.model[index].label onClicked: { - actionDialog.content = machineActionRepeater.model[index].displayItem - machineActionRepeater.model[index].displayItem.reset() - actionDialog.show() + actionDialog.content = machineActionRepeater.model[index].displayItem; + machineActionRepeater.model[index].displayItem.reset(); + actionDialog.title = machineActionRepeater.model[index].label; + actionDialog.show(); } } } @@ -106,12 +107,13 @@ UM.ManagementPage { contents = content; content.onCompleted.connect(hide) + content.dialog = actionDialog } rightButtons: Button { text: catalog.i18nc("@action:button", "Close") iconName: "dialog-close" - onClicked: actionDialog.accept() + onClicked: actionDialog.reject() } } @@ -124,8 +126,14 @@ UM.ManagementPage spacing: UM.Theme.getSize("default_margin").height - Label { text: catalog.i18nc("@label", "Type") } - Label { text: base.currentItem ? base.currentItem.metadata.definition_name : "" } + Label + { + text: catalog.i18nc("@label", "Type") + visible: base.currentItem && "definition_name" in base.currentItem.metadata + } + Label { + text: (base.currentItem && "definition_name" in base.currentItem.metadata) ? base.currentItem.metadata.definition_name : "" + } } UM.I18nCatalog { id: catalog; name: "uranium"; } diff --git a/resources/qml/Preferences/ProfilesPage.qml b/resources/qml/Preferences/ProfilesPage.qml index 119a16facc..c090a8468d 100644 --- a/resources/qml/Preferences/ProfilesPage.qml +++ b/resources/qml/Preferences/ProfilesPage.qml @@ -75,7 +75,7 @@ UM.ManagementPage onClicked: { var selectedContainer; - if (objectList.currentItem.id == Cura.MachineManager.activeQualityId) { + if (base.currentItem.id == Cura.MachineManager.activeQualityId) { selectedContainer = Cura.MachineManager.newQualityContainerFromQualityAndUser(); } else { selectedContainer = Cura.MachineManager.duplicateContainer(base.currentItem.id); diff --git a/resources/qml/PrintMonitor.qml b/resources/qml/PrintMonitor.qml index ba2f3f822c..434cb50b3a 100644 --- a/resources/qml/PrintMonitor.qml +++ b/resources/qml/PrintMonitor.qml @@ -73,7 +73,7 @@ Column Label { text: label - color: printerConnected ? UM.Theme.getColor("setting_control_text") : UM.Theme.getColor("setting_control_disabled_text") + color: printerConnected && printerAcceptsCommands ? UM.Theme.getColor("setting_control_text") : UM.Theme.getColor("setting_control_disabled_text") font: UM.Theme.getFont("default") width: base.width * 0.4 elide: Text.ElideRight @@ -82,7 +82,7 @@ Column Label { text: value - color: printerConnected ? UM.Theme.getColor("setting_control_text") : UM.Theme.getColor("setting_control_disabled_text") + color: printerConnected && printerAcceptsCommands ? UM.Theme.getColor("setting_control_text") : UM.Theme.getColor("setting_control_disabled_text") font: UM.Theme.getFont("default") anchors.verticalCenter: parent.verticalCenter } diff --git a/resources/qml/Settings/SettingTextField.qml b/resources/qml/Settings/SettingTextField.qml index 18a55c7a50..4d05bef2b9 100644 --- a/resources/qml/Settings/SettingTextField.qml +++ b/resources/qml/Settings/SettingTextField.qml @@ -100,7 +100,7 @@ SettingItem maximumLength: 10; - validator: RegExpValidator { regExp: /[0-9.,-]{0,10}/ } + validator: RegExpValidator { regExp: (type == "int") ? /^-?[0-9]{0,10}/ : /^-?[0-9.,]{0,10}/ } //"type" property from parent loader used to disallow fractional number entry Binding { diff --git a/resources/qml/Settings/SettingView.qml b/resources/qml/Settings/SettingView.qml index 009dbf09a9..978e2dcaed 100644 --- a/resources/qml/Settings/SettingView.qml +++ b/resources/qml/Settings/SettingView.qml @@ -125,7 +125,7 @@ ScrollView { id: provider - containerStackId: delegate.stackId + containerStackId: Cura.MachineManager.activeMachineId key: model.key ? model.key : "" watchedProperties: [ "value", "enabled", "state", "validationState", "settable_per_extruder" ] storeIndex: 0 diff --git a/resources/qml/Sidebar.qml b/resources/qml/Sidebar.qml index 8ab776af6a..aa51fcfefe 100644 --- a/resources/qml/Sidebar.qml +++ b/resources/qml/Sidebar.qml @@ -28,6 +28,7 @@ Rectangle // Is there an output device for this printer? property bool printerConnected: Cura.MachineManager.printerOutputDevices.length != 0 + property bool printerAcceptsCommands: printerConnected && Cura.MachineManager.printerOutputDevices[0].acceptsCommands color: UM.Theme.getColor("sidebar"); UM.I18nCatalog { id: catalog; name:"cura"} @@ -107,19 +108,28 @@ Rectangle onClicked: monitoringPrint = true iconSource: { if(!printerConnected) - return UM.Theme.getIcon("tab_monitor") - else if(Cura.MachineManager.printerOutputDevices[0].jobState == "printing" || Cura.MachineManager.printerOutputDevices[0].jobState == "pre_print" || Cura.MachineManager.printerOutputDevices[0].jobState == "wait_cleanup" ) - return UM.Theme.getIcon("tab_monitor_busy") - else if(Cura.MachineManager.printerOutputDevices[0].jobState == "ready" || Cura.MachineManager.printerOutputDevices[0].jobState == "") - return UM.Theme.getIcon("tab_monitor_connected") - else if(Cura.MachineManager.printerOutputDevices[0].jobState == "paused") - return UM.Theme.getIcon("tab_monitor_paused") - else if (Cura.MachineManager.printerOutputDevices[0].jobState == "error") - return UM.Theme.getIcon("tab_monitor_stopped") - else if (Cura.MachineManager.printerOutputDevices[0].jobState == "offline") - return UM.Theme.getIcon("tab_monitor_offline") - else - return UM.Theme.getIcon("tab_monitor") + return UM.Theme.getIcon("tab_monitor"); + else if(!printerAcceptsCommands) + return UM.Theme.getIcon("tab_monitor_unknown"); + + switch(Cura.MachineManager.printerOutputDevices[0].jobState) + { + case "printing": + case "pre_print": + case "wait_cleanup": + return UM.Theme.getIcon("tab_monitor_busy"); + case "ready": + case "": + return UM.Theme.getIcon("tab_monitor_connected") + case "paused": + return UM.Theme.getIcon("tab_monitor_paused") + case "error": + return UM.Theme.getIcon("tab_monitor_stopped") + case "offline": + return UM.Theme.getIcon("tab_monitor_offline") + default: + return UM.Theme.getIcon("tab_monitor") + } } checkable: true checked: monitoringPrint diff --git a/resources/themes/cura/icons/tab_monitor_unknown.svg b/resources/themes/cura/icons/tab_monitor_unknown.svg new file mode 100644 index 0000000000..cf95b28ab3 --- /dev/null +++ b/resources/themes/cura/icons/tab_monitor_unknown.svg @@ -0,0 +1,97 @@ + + + + + + image/svg+xml + + Fill 1 Copy 3 + + + + + + Fill 1 Copy 3 + Created with Sketch. + + + + + + + + + + +