diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index a97522389a..a6d0a3b827 100644 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -97,7 +97,8 @@ class CuraApplication(QtApplication): SettingDefinition.addSupportedProperty("settable_per_extruder", DefinitionPropertyType.Any, default = True) SettingDefinition.addSupportedProperty("settable_per_meshgroup", DefinitionPropertyType.Any, default = True) SettingDefinition.addSupportedProperty("settable_globally", DefinitionPropertyType.Any, default = True) - SettingDefinition.addSettingType("extruder", None, str, Validator) + SettingDefinition.addSupportedProperty("global_inherits_stack", DefinitionPropertyType.Function, default = "-1") + SettingDefinition.addSettingType("extruder", int, str, Validator) ## Add the 4 types of profiles to storage. Resources.addStorageType(self.ResourceTypes.QualityInstanceContainer, "quality") diff --git a/cura/Settings/ExtruderManager.py b/cura/Settings/ExtruderManager.py index 744a6811c5..47359a5e97 100644 --- a/cura/Settings/ExtruderManager.py +++ b/cura/Settings/ExtruderManager.py @@ -22,7 +22,7 @@ class ExtruderManager(QObject): def __init__(self, parent = None): super().__init__(parent) self._extruder_trains = { } #Per machine, a dictionary of extruder container stack IDs. - self._active_extruder_index = -1 + self._active_extruder_index = 0 UM.Application.getInstance().globalContainerStackChanged.connect(self.__globalContainerStackChanged) self._addCurrentMachineExtruders() @@ -41,6 +41,19 @@ class ExtruderManager(QObject): except KeyError: # Extruder index could be -1 if the global tab is selected, or the entry doesn't exist if the machine definition is wrong. return None + @pyqtProperty(int, notify = extrudersChanged) + def extruderCount(self): + if not UM.Application.getInstance().getGlobalContainerStack(): + return 0 # No active machine, so no extruders. + return len(self._extruder_trains[UM.Application.getInstance().getGlobalContainerStack().getId()]) + + @pyqtProperty("QVariantMap", notify=extrudersChanged) + def extruderIds(self): + map = {} + for position in self._extruder_trains[UM.Application.getInstance().getGlobalContainerStack().getId()]: + map[position] = self._extruder_trains[UM.Application.getInstance().getGlobalContainerStack().getId()][position].getId() + return map + ## The instance of the singleton pattern. # # It's None if the extruder manager hasn't been created yet. @@ -106,8 +119,11 @@ class ExtruderManager(QObject): for extruder_train in extruder_trains: self._extruder_trains[machine_id][extruder_train.getMetaDataEntry("position")] = extruder_train - # Ensure that the extruder train stacks are linked to global stack. - extruder_train.setNextStack(UM.Application.getInstance().getGlobalContainerStack()) + # Make sure the next stack is a stack that contains only the machine definition + if not extruder_train.getNextStack(): + shallowStack = UM.Settings.ContainerStack(machine_id + "_shallow") + shallowStack.addContainer(machine_definition) + extruder_train.setNextStack(shallowStack) changed = True if changed: self.extrudersChanged.emit(machine_id) @@ -220,7 +236,11 @@ class ExtruderManager(QObject): container_registry.addContainer(user_profile) container_stack.addContainer(user_profile) - container_stack.setNextStack(UM.Application.getInstance().getGlobalContainerStack()) + # Make sure the next stack is a stack that contains only the machine definition + if not container_stack.getNextStack(): + shallowStack = UM.Settings.ContainerStack(machine_id + "_shallow") + shallowStack.addContainer(machine_definition) + container_stack.setNextStack(shallowStack) container_registry.addContainer(container_stack) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 0c435ba2b9..9f51591a58 100644 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -50,6 +50,8 @@ class MachineManager(QObject): Preferences.getInstance().addPreference("cura/active_machine", "") + self._global_event_keys = set() + active_machine_id = Preferences.getInstance().getValue("cura/active_machine") self._printer_output_devices = [] @@ -58,7 +60,9 @@ class MachineManager(QObject): if active_machine_id != "": # An active machine was saved, so restore it. self.setActiveMachine(active_machine_id) - pass + if self._global_container_stack and self._global_container_stack.getProperty("machine_extruder_count", "value") > 1: + # Make sure _active_container_stack is properly initiated + ExtruderManager.getInstance().setActiveExtruderIndex(0) self._auto_change_material_hotend_flood_window = 10 # The minimum number of seconds between asking if the material or hotend on the machine should be used self._auto_change_material_hotend_flood_time = 0 # The last timestamp (in seconds) when the user was asked about changing the material or hotend to whatis loaded on the machine @@ -197,7 +201,85 @@ class MachineManager(QObject): def _onGlobalPropertyChanged(self, key, property_name): if property_name == "value": + ## We can get recursion issues. So we store a list of keys that we are still handling to prevent this. + if key in self._global_event_keys: + return + self._global_event_keys.add(key) self.globalValueChanged.emit() + + if self._active_container_stack and self._active_container_stack != self._global_container_stack: + # Make the global current settings mirror the stack values appropriate for this setting + if self._active_container_stack.getProperty("extruder_nr", "value") == int(self._active_container_stack.getProperty(key, "global_inherits_stack")): + + new_value = self._active_container_stack.getProperty(key, "value") + self._global_container_stack.getTop().setProperty(key, "value", new_value) + + # Global-only setting values should be set on all extruders and the global stack + if not self._global_container_stack.getProperty(key, "settable_per_extruder"): + extruder_stacks = list(ExtruderManager.getInstance().getMachineExtruders(self._global_container_stack.getId())) + target_stack_position = int(self._active_container_stack.getProperty(key, "global_inherits_stack")) + if target_stack_position == -1: # Prevent -1 from selecting wrong stack. + target_stack = self._active_container_stack + else: + target_stack = extruder_stacks[target_stack_position] + new_value = target_stack.getProperty(key, "value") + target_stack_has_user_value = target_stack.getTop().getInstance(key) != None + for extruder_stack in extruder_stacks: + if extruder_stack != target_stack: + if target_stack_has_user_value: + extruder_stack.getTop().setProperty(key, "value", new_value) + else: + # Remove from the value from the other stacks as well, unless the + # top value from the other stacklevels is different than the new value + for container in extruder_stack.getContainers(): + if container.__class__ == UM.Settings.InstanceContainer and container.getInstance(key) != None: + if container.getProperty(key, "value") != new_value: + # It could be that the setting needs to be removed instead of updated. + temp = extruder_stack + containers = extruder_stack.getContainers() + # Ensure we have the entire 'chain' + while temp.getNextStack(): + temp = temp.getNextStack() + containers.extend(temp.getContainers()) + instance_needs_removal = False + + if len(containers) > 1: + for index in range(1, len(containers)): + deeper_container = containers[index] + if deeper_container.getProperty(key, "value") is None: + continue # Deeper container does not have the value, so continue. + if deeper_container.getProperty(key, "value") == new_value: + # Removal will result in correct value, so do that. + # We do this to prevent the reset from showing up unneeded. + instance_needs_removal = True + break + else: + # Container has the value, but it's not the same. Stop looking. + break + if instance_needs_removal: + extruder_stack.getTop().removeInstance(key) + else: + extruder_stack.getTop().setProperty(key, "value", new_value) + else: + # Check if we really need to remove something. + if extruder_stack.getProperty(key, "value") != new_value: + extruder_stack.getTop().removeInstance(key) + break + if self._global_container_stack.getProperty(key, "value") != new_value: + self._global_container_stack.getTop().setProperty(key, "value", new_value) + self._global_event_keys.remove(key) + + if property_name == "global_inherits_stack": + if self._active_container_stack and self._active_container_stack != self._global_container_stack: + # Update the global user value when the "global_inherits_stack" function points to a different stack + stack_index = int(self._active_container_stack.getProperty(key, property_name)) + extruder_stacks = [stack for stack in ExtruderManager.getInstance().getMachineExtruders(self._global_container_stack.getId())] + + if len(extruder_stacks) > stack_index: + new_value = extruder_stacks[stack_index].getProperty(key, "value") + if self._global_container_stack.getProperty(key, "value") != new_value: + self._global_container_stack.getTop().setProperty(key, "value", new_value) + if property_name == "validationState": if self._global_stack_valid: changed_validation_state = self._active_container_stack.getProperty(key, property_name) @@ -209,7 +291,6 @@ class MachineManager(QObject): if not has_errors: self._global_stack_valid = True self.globalValidationChanged.emit() - def _onGlobalContainerChanged(self): if self._global_container_stack: self._global_container_stack.nameChanged.disconnect(self._onMachineNameChanged) @@ -254,6 +335,18 @@ class MachineManager(QObject): def _onInstanceContainersChanged(self, container): container_type = container.getMetaDataEntry("type") + + if self._active_container_stack and self._active_container_stack != self._global_container_stack: + if int(self._active_container_stack.getProperty("extruder_nr", "value")) == 0: + global_container = self._global_container_stack.findContainer({"type": container_type}) + if global_container and global_container != container: + container_index = self._global_container_stack.getContainerIndex(global_container) + self._global_container_stack.replaceContainer(container_index, container) + + for key in container.getAllKeys(): + # Make sure the values in this profile are distributed to other stacks if necessary + self._onGlobalPropertyChanged(key, "value") + if container_type == "material": self.activeMaterialChanged.emit() elif container_type == "variant": @@ -269,13 +362,14 @@ class MachineManager(QObject): @pyqtSlot(str, str) def addMachine(self, name, definition_id): - definitions = UM.Settings.ContainerRegistry.getInstance().findDefinitionContainers(id = definition_id) + container_registry = UM.Settings.ContainerRegistry.getInstance() + definitions = container_registry.findDefinitionContainers(id = definition_id) if definitions: definition = definitions[0] name = self._createUniqueName("machine", "", name, definition.getName()) new_global_stack = UM.Settings.ContainerStack(name) new_global_stack.addMetaDataEntry("type", "machine") - UM.Settings.ContainerRegistry.getInstance().addContainer(new_global_stack) + container_registry.addContainer(new_global_stack) variant_instance_container = self._updateVariantContainer(definition) material_instance_container = self._updateMaterialContainer(definition, variant_instance_container) @@ -285,7 +379,7 @@ class MachineManager(QObject): current_settings_instance_container.addMetaDataEntry("machine", name) current_settings_instance_container.addMetaDataEntry("type", "user") current_settings_instance_container.setDefinition(definitions[0]) - UM.Settings.ContainerRegistry.getInstance().addContainer(current_settings_instance_container) + container_registry.addContainer(current_settings_instance_container) # If a definition is found, its a list. Should only have one item. new_global_stack.addContainer(definition) @@ -418,6 +512,19 @@ class MachineManager(QObject): return True return containers[0].isReadOnly() + ## Copy the value of the setting of the current extruder to all other extruders as well as the global container. + @pyqtSlot(str) + def copyValueToExtruders(self, key): + if not self._active_container_stack or self._global_container_stack.getProperty("machine_extruder_count", "value") <= 1: + return + + new_value = self._active_container_stack.getProperty(key, "value") + stacks = [stack for stack in ExtruderManager.getInstance().getMachineExtruders(self._global_container_stack.getId())] + stacks.append(self._global_container_stack) + for extruder_stack in stacks: + if extruder_stack != self._active_container_stack and extruder_stack.getProperty(key, "value") != new_value: + extruder_stack.getTop().setProperty(key, "value", new_value) + @pyqtSlot(result = str) def newQualityContainerFromQualityAndUser(self): new_container_id = self.duplicateContainer(self.activeQualityId) diff --git a/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml b/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml index 546b7086e6..54783f02b0 100644 --- a/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml +++ b/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml @@ -181,6 +181,7 @@ Item { onLoaded: { settingLoader.item.showRevertButton = false settingLoader.item.showInheritButton = false + settingLoader.item.showLinkedSettingIcon = false settingLoader.item.doDepthIndentation = false } diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index 024d679315..a963b1614b 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -630,6 +630,7 @@ "type": "float", "enabled": "support_enable", "value": "line_width", + "global_inherits_stack": "support_extruder_nr", "settable_per_mesh": false, "settable_per_extruder": false }, @@ -644,6 +645,7 @@ "type": "float", "enabled": "support_roof_enable", "value": "line_width", + "global_inherits_stack": "support_extruder_nr", "settable_per_mesh": false, "settable_per_extruder": false }, @@ -1443,6 +1445,7 @@ "maximum_value_warning": "150", "default_value": 60, "value": "speed_print", + "global_inherits_stack": "support_extruder_nr", "enabled": "support_enable", "settable_per_mesh": false, "settable_per_extruder": false, @@ -1459,6 +1462,7 @@ "maximum_value": "299792458000", "maximum_value_warning": "150", "value": "speed_support", + "global_inherits_stack": "support_extruder_nr", "enabled": "support_enable", "settable_per_mesh": false, "settable_per_extruder": false @@ -1475,6 +1479,7 @@ "maximum_value_warning": "150", "enabled": "support_roof_enable and support_enable", "value": "speed_support / 1.5", + "global_inherits_stack": "support_extruder_nr", "settable_per_mesh": false, "settable_per_extruder": false } @@ -1646,6 +1651,7 @@ "maximum_value_warning": "10000", "default_value": 3000, "value": "acceleration_print", + "global_inherits_stack": "support_extruder_nr", "enabled": "acceleration_enabled and support_enable", "settable_per_mesh": false, "settable_per_extruder": false, @@ -1657,6 +1663,7 @@ "type": "float", "default_value": 3000, "value": "acceleration_support", + "global_inherits_stack": "support_extruder_nr", "minimum_value": "0.1", "minimum_value_warning": "100", "maximum_value_warning": "10000", @@ -1671,6 +1678,7 @@ "type": "float", "default_value": 3000, "value": "acceleration_support", + "global_inherits_stack": "support_extruder_nr", "minimum_value": "0.1", "minimum_value_warning": "100", "maximum_value_warning": "10000", @@ -1834,6 +1842,7 @@ "maximum_value_warning": "50", "default_value": 20, "value": "jerk_print", + "global_inherits_stack": "support_extruder_nr", "enabled": "jerk_enabled and support_enable", "settable_per_mesh": false, "settable_per_extruder": false, @@ -1845,6 +1854,7 @@ "type": "float", "default_value": 20, "value": "jerk_support", + "global_inherits_stack": "support_extruder_nr", "minimum_value": "0.1", "minimum_value_warning": "5", "maximum_value_warning": "50", @@ -1859,6 +1869,7 @@ "type": "float", "default_value": 20, "value": "jerk_support", + "global_inherits_stack": "support_extruder_nr", "minimum_value": "0.1", "minimum_value_warning": "5", "maximum_value_warning": "50", @@ -2123,7 +2134,8 @@ "description": "Enable support structures. These structures support parts of the model with severe overhangs.", "type": "bool", "default_value": false, - "settable_per_mesh": true + "settable_per_mesh": true, + "settable_per_extruder": false }, "support_type": { @@ -2149,6 +2161,7 @@ "minimum_value": "0", "maximum_value": "90", "default_value": 50, + "global_inherits_stack": "support_extruder_nr", "enabled": "support_enable", "settable_per_mesh": true }, @@ -2217,6 +2230,7 @@ "minimum_value": "0", "maximum_value_warning": "10", "default_value": 0.15, + "global_inherits_stack": "support_extruder_nr", "enabled": "support_enable", "settable_per_mesh": true, "children": @@ -2232,6 +2246,7 @@ "type": "float", "enabled": "support_enable", "value": "support_z_distance", + "global_inherits_stack": "support_extruder_nr", "settable_per_mesh": true }, "support_bottom_distance": @@ -2243,6 +2258,7 @@ "maximum_value_warning": "10", "default_value": 0.1, "value": "0.1 if support_type == 'everywhere' else 0", + "global_inherits_stack": "support_extruder_nr", "type": "float", "enabled": "support_enable and support_type == 'everywhere'", "settable_per_mesh": true @@ -2258,6 +2274,7 @@ "minimum_value": "0", "maximum_value_warning": "10", "default_value": 0.7, + "global_inherits_stack": "support_extruder_nr", "enabled": "support_enable", "settable_per_mesh": true }, @@ -2270,6 +2287,7 @@ "z_overrides_xy": "Z overrides X/Y" }, "default_value": "z_overrides_xy", + "global_inherits_stack": "support_extruder_nr", "enabled": "support_enable", "settable_per_mesh": true }, @@ -2282,6 +2300,7 @@ "maximum_value_warning": "10", "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'", "settable_per_mesh": true }, @@ -2292,6 +2311,7 @@ "unit": "mm", "type": "float", "default_value": 0.3, + "global_inherits_stack": "support_extruder_nr", "minimum_value": "0", "maximum_value_warning": "1.0", "enabled": "support_enable", @@ -2304,6 +2324,7 @@ "unit": "mm", "type": "float", "default_value": 2.0, + "global_inherits_stack": "support_extruder_nr", "minimum_value_warning": "0", "maximum_value_warning": "10", "enabled": "support_enable", @@ -2316,6 +2337,7 @@ "unit": "mm", "type": "float", "default_value": 0.2, + "global_inherits_stack": "support_extruder_nr", "minimum_value_warning": "-0.5", "maximum_value_warning": "5.0", "enabled": "support_enable", @@ -2328,6 +2350,7 @@ "unit": "mm", "type": "float", "default_value": 0.6, + "global_inherits_stack": "support_extruder_nr", "minimum_value": "0", "maximum_value_warning": "1.0", "enabled": "support_enable", @@ -2339,6 +2362,7 @@ "description": "Generate a dense top skin at the top of the support on which the model is printed.", "type": "bool", "default_value": false, + "global_inherits_stack": "support_extruder_nr", "enabled": "support_enable", "settable_per_mesh": true }, @@ -2350,6 +2374,7 @@ "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 @@ -2407,6 +2432,7 @@ "description": "Use specialized towers to support tiny overhang areas. These towers have a larger diameter than the region they support. Near the overhang the towers' diameter decreases, forming a roof.", "type": "bool", "default_value": true, + "global_inherits_stack": "support_extruder_nr", "enabled": "support_enable", "settable_per_mesh": true }, @@ -2417,6 +2443,7 @@ "unit": "mm", "type": "float", "default_value": 3.0, + "global_inherits_stack": "support_extruder_nr", "minimum_value": "0", "maximum_value_warning": "10", "enabled": "support_enable and support_use_towers", @@ -2429,6 +2456,7 @@ "unit": "mm", "type": "float", "default_value": 3.0, + "global_inherits_stack": "support_extruder_nr", "minimum_value": "0", "maximum_value_warning": "10", "maximum_value": "support_tower_diameter", @@ -2444,6 +2472,7 @@ "minimum_value": "0", "maximum_value": "90", "default_value": 65, + "global_inherits_stack": "support_extruder_nr", "enabled": "support_enable and support_use_towers", "settable_per_mesh": true } diff --git a/resources/qml/Settings/SettingItem.qml b/resources/qml/Settings/SettingItem.qml index a7bdabb3c5..1609e30080 100644 --- a/resources/qml/Settings/SettingItem.qml +++ b/resources/qml/Settings/SettingItem.qml @@ -21,10 +21,12 @@ Item { property var showRevertButton: true property var showInheritButton: true + property var showLinkedSettingIcon: true property var doDepthIndentation: true // Create properties to put property provider stuff in (bindings break in qt 5.5.1 otherwise) property var state: propertyProvider.properties.state + property var settablePerExtruder: propertyProvider.properties.settable_per_extruder property var stackLevels: propertyProvider.stackLevels property var stackLevel: stackLevels[0] @@ -131,6 +133,26 @@ Item { verticalCenter: parent.verticalCenter } + UM.SimpleButton + { + id: linkedSettingIcon; + + visible: base.settablePerExtruder != "True" && base.showLinkedSettingIcon + + height: parent.height; + width: height; + + backgroundColor: UM.Theme.getColor("setting_control"); + hoverBackgroundColor: UM.Theme.getColor("setting_control") + color: UM.Theme.getColor("setting_control_button") + hoverColor: UM.Theme.getColor("setting_control_button") + + iconSource: UM.Theme.getIcon("link") + + onEntered: { hoverTimer.stop(); base.showTooltip(catalog.i18nc("@label", "This setting is always shared between all extruders. Changing it here will change the value for all extruders")) } + onExited: base.showTooltip(base.tooltipText); + } + UM.SimpleButton { id: revertButton; @@ -231,7 +253,6 @@ Item { onEntered: { hoverTimer.stop(); base.showTooltip(catalog.i18nc("@label", "This setting is normally calculated, but it currently has an absolute value set.\n\nClick to restore the calculated value.")) } onExited: base.showTooltip(base.tooltipText); } - } Item diff --git a/resources/qml/Settings/SettingView.qml b/resources/qml/Settings/SettingView.qml index 39f0f833b8..957a68b94c 100644 --- a/resources/qml/Settings/SettingView.qml +++ b/resources/qml/Settings/SettingView.qml @@ -34,14 +34,7 @@ ScrollView expanded: Printer.expandedCategories onExpandedChanged: Printer.setExpandedCategories(expanded) - filter: - { - if(ExtruderManager.activeExtruderStackId) - { - return { "settable_per_extruder": true } - } - return { } - } + filter: {} } delegate: Loader @@ -53,7 +46,15 @@ ScrollView Behavior on height { NumberAnimation { duration: 100 } } opacity: provider.properties.enabled == "True" ? 1 : 0 Behavior on opacity { NumberAnimation { duration: 100 } } - enabled: provider.properties.enabled == "True" + enabled: + { + if(!ExtruderManager.activeExtruderStackId && ExtruderManager.extruderCount > 0) + { + // disable all controls on the global tab, except categories + return model.type == "category" + } + return provider.properties.enabled == "True" + } property var definition: model property var settingDefinitionsModel: definitionsModel @@ -88,20 +89,59 @@ ScrollView } } + // Binding to ensure that the right containerstack ID is set for the provider. + // This ensures that if a setting has a global_inherits_stack id (for instance; Support speed points to the + // extruder that actually prints the support, as that is the setting we need to use to calculate the value) + Binding + { + target: provider + property: "containerStackId" + value: + { + if(inheritStackProvider.properties.global_inherits_stack == -1 || inheritStackProvider.properties.global_inherits_stack == null) + { + if( ExtruderManager.activeExtruderStackId) + { + return ExtruderManager.activeExtruderStackId + } + else + { + return Cura.MachineManager.activeMachineId + } + } + return ExtruderManager.extruderIds[String(inheritStackProvider.properties.global_inherits_stack)] + } + } + + // Specialty provider that only watches global_inherits (we cant filter on what property changed we get events + // so we bypass that to make a dedicated provider. + UM.SettingPropertyProvider + { + id: inheritStackProvider + containerStackId: Cura.MachineManager.activeMachineId + key: model.key + watchedProperties: [ "global_inherits_stack"] + } + UM.SettingPropertyProvider { id: provider - containerStackId: ExtruderManager.activeExtruderStackId ? ExtruderManager.activeExtruderStackId : Cura.MachineManager.activeMachineId + containerStackId: delegate.stackId key: model.key ? model.key : "" - watchedProperties: [ "value", "enabled", "state", "validationState" ] + watchedProperties: [ "value", "enabled", "state", "validationState", "settable_per_extruder" ] storeIndex: 0 } Connections { target: item - onContextMenuRequested: { contextMenu.key = model.key; contextMenu.popup() } + onContextMenuRequested: + { + contextMenu.key = model.key; + contextMenu.provider = provider + contextMenu.popup(); + } onShowTooltip: base.showTooltip(delegate, { x: 0, y: delegate.height / 2 }, text) onHideTooltip: base.hideTooltip() } @@ -133,9 +173,24 @@ ScrollView Menu { - id: contextMenu; + id: contextMenu - property string key; + property string key + property var provider + + MenuItem + { + //: Settings context menu action + text: catalog.i18nc("@action:menu", "Copy value to all extruders") + visible: machineExtruderCount.properties.value > 1 + enabled: contextMenu.provider.properties.settable_per_extruder != "False" + onTriggered: Cura.MachineManager.copyValueToExtruders(contextMenu.key) + } + + MenuSeparator + { + visible: machineExtruderCount.properties.value > 1 + } MenuItem { @@ -151,5 +206,15 @@ ScrollView onTriggered: Cura.Actions.configureSettingVisibility.trigger(contextMenu); } } + + UM.SettingPropertyProvider + { + id: machineExtruderCount + + containerStackId: Cura.MachineManager.activeMachineId + key: "machine_extruder_count" + watchedProperties: [ "value" ] + storeIndex: 0 + } } } diff --git a/resources/qml/SidebarHeader.qml b/resources/qml/SidebarHeader.qml index aa6f2c0067..1f7fa00b54 100644 --- a/resources/qml/SidebarHeader.qml +++ b/resources/qml/SidebarHeader.qml @@ -84,15 +84,15 @@ Column orientation: ListView.Horizontal - model: Cura.ExtrudersModel { id: extrudersModel; addGlobal: true } + model: Cura.ExtrudersModel { id: extrudersModel; addGlobal: false } Connections { target: Cura.MachineManager onGlobalContainerChanged: { - base.currentExtruderIndex = -1; - forceActiveFocus() + forceActiveFocus() // Changing focus applies the currently-being-typed values so it can change the displayed setting values. + base.currentExtruderIndex = (machineExtruderCount.properties.value == 1) ? -1 : 0; ExtruderManager.setActiveExtruderIndex(base.currentExtruderIndex); } } @@ -110,7 +110,7 @@ Column onClicked: { - forceActiveFocus() //Changing focus applies the currently-being-typed values so it can change the displayed setting values. + forceActiveFocus() // Changing focus applies the currently-being-typed values so it can change the displayed setting values. base.currentExtruderIndex = index; ExtruderManager.setActiveExtruderIndex(index); } @@ -258,6 +258,8 @@ Column { id: globalProfileSelection text: Cura.MachineManager.activeQualityName + enabled: !extrudersList.visible || base.currentExtruderIndex > -1 + width: parent.width * 0.55 + UM.Theme.getSize("default_margin").width height: UM.Theme.getSize("setting_control").height tooltip: Cura.MachineManager.activeQualityName diff --git a/resources/qml/SidebarSimple.qml b/resources/qml/SidebarSimple.qml index 04b93e7d2a..0e1b04cdeb 100644 --- a/resources/qml/SidebarSimple.qml +++ b/resources/qml/SidebarSimple.qml @@ -19,6 +19,7 @@ Item property Action configureSettings; property variant minimumPrintTime: PrintInformation.minimumPrintTime; property variant maximumPrintTime: PrintInformation.maximumPrintTime; + property bool settingsEnabled: ExtruderManager.activeExtruderStackId || ExtruderManager.extruderCount == 0 Component.onCompleted: PrintInformation.enabled = true Component.onDestruction: PrintInformation.enabled = false @@ -81,7 +82,11 @@ Item height: width border.color: { - if(infillListView.activeIndex == index) + if(!base.settingsEnabled) + { + return UM.Theme.getColor("setting_control_disabled_border") + } + else if(infillListView.activeIndex == index) { return UM.Theme.getColor("setting_control_selected") } @@ -92,7 +97,17 @@ Item return UM.Theme.getColor("setting_control_border") } border.width: UM.Theme.getSize("default_lining").width - color: infillListView.activeIndex == index ? UM.Theme.getColor("setting_control_selected") : "transparent" + color: { + if(infillListView.activeIndex == index) + { + if(!base.settingsEnabled) + { + return UM.Theme.getColor("setting_control_disabled_text") + } + return UM.Theme.getColor("setting_control_selected") + } + return "transparent" + } UM.RecolorImage { id: infillIcon @@ -102,13 +117,24 @@ Item sourceSize.width: width sourceSize.height: width source: UM.Theme.getIcon(model.icon); - color: (infillListView.activeIndex == index) ? UM.Theme.getColor("text_white") : UM.Theme.getColor("text") + color: { + if(infillListView.activeIndex == index) + { + return UM.Theme.getColor("text_reversed") + } + if(!base.settingsEnabled) + { + return UM.Theme.getColor("setting_control_disabled_text") + } + return UM.Theme.getColor("text") + } } MouseArea { id: infillMouseArea anchors.fill: parent hoverEnabled: true + enabled: base.settingsEnabled onClicked: { if (infillListView.activeIndex != index) { @@ -206,6 +232,7 @@ Item //: Setting enable skirt adhesion checkbox text: catalog.i18nc("@option:check", "Print Brim"); style: UM.Theme.styles.checkbox; + enabled: base.settingsEnabled checked: platformAdhesionType.properties.value == "brim" @@ -213,6 +240,7 @@ Item id: brimMouseArea anchors.fill: parent hoverEnabled: true + enabled: base.settingsEnabled onClicked: { platformAdhesionType.setPropertyValue("value", !parent.checked ? "brim" : "skirt") @@ -254,12 +282,14 @@ Item //: Setting enable support checkbox text: catalog.i18nc("@option:check", "Print Support Structure"); style: UM.Theme.styles.checkbox; + enabled: base.settingsEnabled checked: supportEnabled.properties.value == "True" MouseArea { id: supportMouseArea anchors.fill: parent hoverEnabled: true + enabled: base.settingsEnabled onClicked: { supportEnabled.setPropertyValue("value", !parent.checked) @@ -288,6 +318,7 @@ Item width: parent.width / 100 * 45 style: UM.Theme.styles.combobox + enabled: base.settingsEnabled property alias _hovered: supportExtruderMouseArea.containsMouse currentIndex: supportEnabled.properties.value == "True" ? parseFloat(supportExtruderNr.properties.value) + 1 : 0 @@ -303,6 +334,7 @@ Item id: supportExtruderMouseArea anchors.fill: parent hoverEnabled: true + enabled: base.settingsEnabled acceptedButtons: Qt.NoButton onEntered: { @@ -382,7 +414,7 @@ Item { id: platformAdhesionType - containerStackId: Cura.MachineManager.activeMachineId + containerStackId: Cura.MachineManager.activeStackId key: "adhesion_type" watchedProperties: [ "value" ] storeIndex: 0 @@ -392,7 +424,7 @@ Item { id: supportEnabled - containerStackId: Cura.MachineManager.activeMachineId + containerStackId: Cura.MachineManager.activeStackId key: "support_enable" watchedProperties: [ "value" ] storeIndex: 0 @@ -412,7 +444,7 @@ Item { id: supportExtruderNr - containerStackId: Cura.MachineManager.activeMachineId + containerStackId: Cura.MachineManager.activeStackId key: "support_extruder_nr" watchedProperties: [ "value" ] storeIndex: 0 diff --git a/resources/themes/cura/icons/link.svg b/resources/themes/cura/icons/link.svg new file mode 100644 index 0000000000..7cc2778846 --- /dev/null +++ b/resources/themes/cura/icons/link.svg @@ -0,0 +1,43 @@ + +image/svg+xml \ No newline at end of file diff --git a/resources/themes/cura/icons/reset.svg b/resources/themes/cura/icons/reset.svg index fae303d2a1..4772d446d7 100644 --- a/resources/themes/cura/icons/reset.svg +++ b/resources/themes/cura/icons/reset.svg @@ -27,10369 +27,4 @@ c-1.128,0.65-2.448,0.967-3.679,1.439C-0.113,107.552-0.113,69.744-0.113,31.935z"/> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/resources/themes/cura/theme.json b/resources/themes/cura/theme.json index 053e5e3d84..69fc2c2c71 100644 --- a/resources/themes/cura/theme.json +++ b/resources/themes/cura/theme.json @@ -56,7 +56,7 @@ "text_inactive": [174, 174, 174, 255], "text_hover": [70, 84, 113, 255], "text_pressed": [12, 169, 227, 255], - "text_white": [255, 255, 255, 255], + "text_reversed": [255, 255, 255, 255], "text_subtext": [70, 84, 113, 255], "error": [255, 140, 0, 255],