From 5873f1d4d09206261f27bb12c6527a7fa9aeb123 Mon Sep 17 00:00:00 2001 From: Arjen Hiemstra Date: Thu, 2 Jun 2016 11:22:39 +0200 Subject: [PATCH 01/42] Limit layer processing to 99% to indicate more stuff needs to happen Fixes CURA-1644 --- plugins/CuraEngineBackend/ProcessSlicedLayersJob.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py b/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py index d3053f9175..77a42f6b3e 100644 --- a/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py +++ b/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py @@ -96,7 +96,7 @@ class ProcessSlicedLayersJob(Job): Job.yieldThread() Job.yieldThread() current_layer += 1 - progress = (current_layer / layer_count) * 100 + progress = (current_layer / layer_count) * 99 # TODO: Rebuild the layer data mesh once the layer has been processed. # This needs some work in LayerData so we can add the new layers instead of recreating the entire mesh. From 070e791b94dcc9197e7a865d4e055b0dd26b1635 Mon Sep 17 00:00:00 2001 From: Arjen Hiemstra Date: Thu, 2 Jun 2016 11:23:18 +0200 Subject: [PATCH 02/42] Add a preference to change LayerView top layers between 1 and 5 Fixes CURA-1643 --- plugins/LayerView/LayerView.py | 16 +++++++++++++++- resources/qml/ViewPage.qml | 27 +++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/plugins/LayerView/LayerView.py b/plugins/LayerView/LayerView.py index 27bb7f022c..b5f152e825 100644 --- a/plugins/LayerView/LayerView.py +++ b/plugins/LayerView/LayerView.py @@ -12,6 +12,7 @@ from UM.Math.Color import Color from UM.Mesh.MeshData import MeshData from UM.Job import Job from UM.Message import Message +from UM.Preferences import Preferences from UM.View.RenderBatch import RenderBatch from UM.View.GL.OpenGL import OpenGL @@ -44,7 +45,10 @@ class LayerView(View): self._top_layers_job = None self._activity = False - self._solid_layers = 1 + Preferences.getInstance().addPreference("view/top_layer_count", 1) + Preferences.getInstance().preferenceChanged.connect(self._onPreferencesChanged) + + self._solid_layers = int(Preferences.getInstance().getValue("view/top_layer_count")) self._top_layer_timer = QTimer() self._top_layer_timer.setInterval(50) @@ -212,6 +216,16 @@ class LayerView(View): self._top_layers_job = None + def _onPreferencesChanged(self, preference): + if preference != "view/top_layer_count": + return + + self._solid_layers = int(Preferences.getInstance().getValue("view/top_layer_count")) + + self._current_layer_mesh = None + self._current_layer_jumps = None + self._top_layer_timer.start() + class _CreateTopLayersJob(Job): def __init__(self, scene, layer_number, solid_layers): super().__init__() diff --git a/resources/qml/ViewPage.qml b/resources/qml/ViewPage.qml index ee0c74904a..3860f8f304 100644 --- a/resources/qml/ViewPage.qml +++ b/resources/qml/ViewPage.qml @@ -19,6 +19,7 @@ UM.PreferencesPage { UM.Preferences.resetPreference("view/show_overhang"); UM.Preferences.resetPreference("view/center_on_select"); + UM.Preferences.resetPreference("view/top_layer_count"); } Column @@ -57,12 +58,38 @@ UM.PreferencesPage } } + UM.TooltipArea { + width: childrenRect.width; + height: childrenRect.height; + text: catalog.i18nc("@info:tooltip","Displays") + + CheckBox + { + id: topLayerCheckbox + text: catalog.i18nc("@action:button","Display five top layers in layer view."); + checked: UM.Preferences.getValue("view/top_layer_count") == 5 + onClicked: + { + if(UM.Preferences.getValue("view/top_layer_count") == 5) + { + UM.Preferences.setValue("view/top_layer_count", 1) + } + else + { + UM.Preferences.setValue("view/top_layer_count", 5) + } + } + } + } + Connections { target: UM.Preferences onPreferenceChanged: { overhangCheckbox.checked = boolCheck(UM.Preferences.getValue("view/show_overhang")) centerCheckbox.checked = boolCheck(UM.Preferences.getValue("view/center_on_select")) + topLayerCheckbox = UM.Preferences.getValue("view/top_layer_count") == 5 + } } } From 02b8fa90437d5aac8875ce52145344affa8d7dec Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Thu, 2 Jun 2016 12:46:01 +0200 Subject: [PATCH 03/42] Add missing tooltip CURA-1643 --- resources/qml/ViewPage.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/qml/ViewPage.qml b/resources/qml/ViewPage.qml index 3860f8f304..1763325e18 100644 --- a/resources/qml/ViewPage.qml +++ b/resources/qml/ViewPage.qml @@ -61,7 +61,7 @@ UM.PreferencesPage UM.TooltipArea { width: childrenRect.width; height: childrenRect.height; - text: catalog.i18nc("@info:tooltip","Displays") + text: catalog.i18nc("@info:tooltip","Display 5 top layers in layer view or only the top-most layer. Rendering 5 layers takes longer, but may show more information.") CheckBox { From 6257fe41d531d46476c207689b2a1375bf5fb192 Mon Sep 17 00:00:00 2001 From: Aldo Hoeben Date: Thu, 2 Jun 2016 14:50:02 +0200 Subject: [PATCH 04/42] Remove unsanctioned PLA profile --- .../ultimaker2+/pla_0.4_ulti.curaprofile | 23 ------------------- 1 file changed, 23 deletions(-) delete mode 100644 resources/profiles/ultimaker2+/pla_0.4_ulti.curaprofile diff --git a/resources/profiles/ultimaker2+/pla_0.4_ulti.curaprofile b/resources/profiles/ultimaker2+/pla_0.4_ulti.curaprofile deleted file mode 100644 index 5cb807de01..0000000000 --- a/resources/profiles/ultimaker2+/pla_0.4_ulti.curaprofile +++ /dev/null @@ -1,23 +0,0 @@ -[general] -version = 1 -name = Ulti Quality -machine_type = ultimaker2plus -machine_variant = 0.4 mm -material = PLA -weight = -4 - -[settings] -line_width = 0.35 -layer_height = 0.04 -layer_height_0 = 0.26 -wall_thickness = 1.4 -top_bottom_thickness = 1.12 -infill_sparse_density = 25 -retraction_amount = 5.5 -retraction_extrusion_window = 6 -speed_print = 30 -speed_infill = 50 -speed_wall_x = 40 -speed_topbottom = 20 -speed_layer_0 = 25 -cool_min_layer_time_fan_speed_max = 15 From 889844e34bfd5733aa23e58a392ca9f2f031cfd3 Mon Sep 17 00:00:00 2001 From: Tim Kuipers Date: Tue, 7 Jun 2016 11:39:23 +0200 Subject: [PATCH 05/42] profiles: speed changes (extra overrides) (CURA-1662) --- resources/profiles/ultimaker2+/abs_0.4_fast.curaprofile | 2 ++ resources/profiles/ultimaker2+/abs_0.4_high.curaprofile | 1 + resources/profiles/ultimaker2+/abs_0.4_normal.curaprofile | 1 + resources/profiles/ultimaker2+/abs_0.6_normal.curaprofile | 1 + resources/profiles/ultimaker2+/cpe_0.4_fast.curaprofile | 1 + resources/profiles/ultimaker2+/cpe_0.4_high.curaprofile | 1 + resources/profiles/ultimaker2+/cpe_0.4_normal.curaprofile | 1 + resources/profiles/ultimaker2+/pla_0.4_fast.curaprofile | 2 ++ resources/profiles/ultimaker2+/pla_0.4_high.curaprofile | 1 + resources/profiles/ultimaker2+/pla_0.4_normal.curaprofile | 1 + resources/profiles/ultimaker2+/pla_0.6_normal.curaprofile | 3 +++ resources/profiles/ultimaker2+/pla_0.8_normal.curaprofile | 1 + 12 files changed, 16 insertions(+) diff --git a/resources/profiles/ultimaker2+/abs_0.4_fast.curaprofile b/resources/profiles/ultimaker2+/abs_0.4_fast.curaprofile index 50018372b5..96e99f8a3d 100644 --- a/resources/profiles/ultimaker2+/abs_0.4_fast.curaprofile +++ b/resources/profiles/ultimaker2+/abs_0.4_fast.curaprofile @@ -12,6 +12,8 @@ wall_thickness = 0.7 top_bottom_thickness = 0.75 infill_sparse_density = 18 speed_print = 55 +speed_wall = 40 +speed_topbottom = 30 speed_travel = 150 speed_layer_0 = 30 cool_min_layer_time = 3 diff --git a/resources/profiles/ultimaker2+/abs_0.4_high.curaprofile b/resources/profiles/ultimaker2+/abs_0.4_high.curaprofile index 341c9cc34f..66a72e17bf 100644 --- a/resources/profiles/ultimaker2+/abs_0.4_high.curaprofile +++ b/resources/profiles/ultimaker2+/abs_0.4_high.curaprofile @@ -12,6 +12,7 @@ wall_thickness = 1.05 top_bottom_thickness = 0.72 infill_sparse_density = 22 speed_print = 45 +speed_wall = 30 cool_min_layer_time = 3 cool_fan_speed_min = 20 cool_min_speed = 10 diff --git a/resources/profiles/ultimaker2+/abs_0.4_normal.curaprofile b/resources/profiles/ultimaker2+/abs_0.4_normal.curaprofile index d8fce8a4dd..c6baaf448e 100644 --- a/resources/profiles/ultimaker2+/abs_0.4_normal.curaprofile +++ b/resources/profiles/ultimaker2+/abs_0.4_normal.curaprofile @@ -12,6 +12,7 @@ wall_thickness = 1.05 top_bottom_thickness = 0.8 infill_sparse_density = 20 speed_print = 45 +speed_wall = 30 cool_min_layer_time = 3 cool_fan_speed_min = 20 cool_min_speed = 10 diff --git a/resources/profiles/ultimaker2+/abs_0.6_normal.curaprofile b/resources/profiles/ultimaker2+/abs_0.6_normal.curaprofile index 5512450471..9699b4e0c9 100644 --- a/resources/profiles/ultimaker2+/abs_0.6_normal.curaprofile +++ b/resources/profiles/ultimaker2+/abs_0.6_normal.curaprofile @@ -12,6 +12,7 @@ wall_thickness = 1.59 top_bottom_thickness = 1.2 infill_sparse_density = 20 speed_print = 40 +speed_infill = 55 cool_min_layer_time = 3 cool_fan_speed_min = 50 cool_min_speed = 20 diff --git a/resources/profiles/ultimaker2+/cpe_0.4_fast.curaprofile b/resources/profiles/ultimaker2+/cpe_0.4_fast.curaprofile index f9050e5ce5..550b8f46e3 100644 --- a/resources/profiles/ultimaker2+/cpe_0.4_fast.curaprofile +++ b/resources/profiles/ultimaker2+/cpe_0.4_fast.curaprofile @@ -12,6 +12,7 @@ wall_thickness = 0.7 top_bottom_thickness = 0.75 infill_sparse_density = 18 speed_print = 45 +speed_wall = 40 speed_travel = 150 speed_layer_0 = 30 cool_min_layer_time = 3 diff --git a/resources/profiles/ultimaker2+/cpe_0.4_high.curaprofile b/resources/profiles/ultimaker2+/cpe_0.4_high.curaprofile index 377ab5b257..88db3c4bec 100644 --- a/resources/profiles/ultimaker2+/cpe_0.4_high.curaprofile +++ b/resources/profiles/ultimaker2+/cpe_0.4_high.curaprofile @@ -12,6 +12,7 @@ wall_thickness = 1.05 top_bottom_thickness = 0.72 infill_sparse_density = 22 speed_print = 45 +speed_wall = 30 cool_min_layer_time = 2 cool_fan_speed_min = 80 cool_min_speed = 15 diff --git a/resources/profiles/ultimaker2+/cpe_0.4_normal.curaprofile b/resources/profiles/ultimaker2+/cpe_0.4_normal.curaprofile index e8142405ff..91a82753ac 100644 --- a/resources/profiles/ultimaker2+/cpe_0.4_normal.curaprofile +++ b/resources/profiles/ultimaker2+/cpe_0.4_normal.curaprofile @@ -12,6 +12,7 @@ wall_thickness = 1.05 top_bottom_thickness = 0.8 infill_sparse_density = 20 speed_print = 45 +speed_wall = 30 cool_min_layer_time = 3 cool_fan_speed_min = 80 cool_min_speed = 10 diff --git a/resources/profiles/ultimaker2+/pla_0.4_fast.curaprofile b/resources/profiles/ultimaker2+/pla_0.4_fast.curaprofile index 06e401c139..c03c8ce621 100644 --- a/resources/profiles/ultimaker2+/pla_0.4_fast.curaprofile +++ b/resources/profiles/ultimaker2+/pla_0.4_fast.curaprofile @@ -12,6 +12,8 @@ wall_thickness = 0.7 top_bottom_thickness = 0.75 infill_sparse_density = 18 speed_print = 60 +speed_wall = 50 +speed_topbottom = 30 speed_travel = 150 speed_layer_0 = 30 cool_min_layer_time = 5 diff --git a/resources/profiles/ultimaker2+/pla_0.4_high.curaprofile b/resources/profiles/ultimaker2+/pla_0.4_high.curaprofile index 5e2f762354..7cba49b71e 100644 --- a/resources/profiles/ultimaker2+/pla_0.4_high.curaprofile +++ b/resources/profiles/ultimaker2+/pla_0.4_high.curaprofile @@ -12,5 +12,6 @@ wall_thickness = 1.05 top_bottom_thickness = 0.72 infill_sparse_density = 22 speed_print = 50 +speed_topbottom = 20 cool_min_layer_time = 5 cool_min_speed = 10 diff --git a/resources/profiles/ultimaker2+/pla_0.4_normal.curaprofile b/resources/profiles/ultimaker2+/pla_0.4_normal.curaprofile index 689a3251b2..4989b0e780 100644 --- a/resources/profiles/ultimaker2+/pla_0.4_normal.curaprofile +++ b/resources/profiles/ultimaker2+/pla_0.4_normal.curaprofile @@ -12,5 +12,6 @@ wall_thickness = 1.05 top_bottom_thickness = 0.8 infill_sparse_density = 20 speed_print = 50 +speed_topbottom = 20 cool_min_layer_time = 5 cool_min_speed = 10 diff --git a/resources/profiles/ultimaker2+/pla_0.6_normal.curaprofile b/resources/profiles/ultimaker2+/pla_0.6_normal.curaprofile index 188ed42a95..767a3d5ef5 100644 --- a/resources/profiles/ultimaker2+/pla_0.6_normal.curaprofile +++ b/resources/profiles/ultimaker2+/pla_0.6_normal.curaprofile @@ -12,5 +12,8 @@ wall_thickness = 1.59 top_bottom_thickness = 1.2 infill_sparse_density = 20 speed_print = 55 +speed_wall = 40 +speed_wall_0 = 25 +speed_topbottom = 20 cool_min_layer_time = 5 cool_min_speed = 10 diff --git a/resources/profiles/ultimaker2+/pla_0.8_normal.curaprofile b/resources/profiles/ultimaker2+/pla_0.8_normal.curaprofile index 92cb4a6054..a8d50c78df 100644 --- a/resources/profiles/ultimaker2+/pla_0.8_normal.curaprofile +++ b/resources/profiles/ultimaker2+/pla_0.8_normal.curaprofile @@ -12,5 +12,6 @@ wall_thickness = 2.1 top_bottom_thickness = 1.2 infill_sparse_density = 20 speed_print = 40 +speed_wall_0 = 25 cool_min_layer_time = 5 cool_min_speed = 10 From b14b05d6fb5615b5c8fc30f228d430b4017a4fcc Mon Sep 17 00:00:00 2001 From: Tim Kuipers Date: Tue, 7 Jun 2016 12:12:14 +0200 Subject: [PATCH 06/42] JSON: upped the retraction_count_max further up to 90 (CURA-1662) --- resources/machines/fdmprinter.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/machines/fdmprinter.json b/resources/machines/fdmprinter.json index 2b172d1720..a523627b7d 100644 --- a/resources/machines/fdmprinter.json +++ b/resources/machines/fdmprinter.json @@ -760,7 +760,7 @@ "retraction_count_max": { "label": "Maximum Retraction Count", "description": "This setting limits the number of retractions occurring within the minimum extrusion distance window. Further retractions within this window will be ignored. This avoids retracting repeatedly on the same piece of filament, as that can flatten the filament and cause grinding issues.", - "default": 45, + "default": 90, "min_value": "0", "max_value_warning": "100", "type": "int", From ec2657947345c7b76f59bbec4ab0898b658c26cc Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Tue, 7 Jun 2016 14:59:32 +0200 Subject: [PATCH 07/42] Remove unused _repopulate function It is replaced by the addMachineExtruders function. Contributes to issues CURA-340 and CURA-1278. --- cura/ExtruderManager.py | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/cura/ExtruderManager.py b/cura/ExtruderManager.py index df31cbacdf..23a72b2c3b 100644 --- a/cura/ExtruderManager.py +++ b/cura/ExtruderManager.py @@ -80,23 +80,6 @@ class ExtruderManager(QObject): if extruder_trains: self.extrudersChanged.emit() - ## (Re)populates the collections of extruders by machine. - def _repopulate(self): - self._extruder_trains = { } - if not UM.Application.getInstance().getGlobalContainerStack(): #No machine has been added yet. - self.extrudersChanged.emit() #Yes, we just cleared the _extruders list! - return #Then leave them empty! - - extruder_trains = UM.Settings.ContainerRegistry.getInstance().findContainerStacks(type = "extruder_train") - for extruder_train in extruder_trains: - machine_id = extruder_train.getMetaDataEntry("machine") - if not machine_id: - continue - if machine_id not in self._extruder_trains: - self._extruder_trains[machine_id] = { } - self._extruder_trains[machine_id][extruder_train.getMetaDataEntry("position")] = extruder_train.getId() - self.extrudersChanged.emit() - def createExtruderTrain(self, extruder_definition, machine_definition, extruder_train_id, position): container_registry = UM.Settings.ContainerRegistry.getInstance() From f461ed0f5f62f2cbf556c32037298bb5c7052514 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Tue, 7 Jun 2016 15:26:51 +0200 Subject: [PATCH 08/42] Document singleton Contributes to issues CURA-340 and CURA-1278. --- cura/ExtruderManager.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/cura/ExtruderManager.py b/cura/ExtruderManager.py index 23a72b2c3b..b40bb0f664 100644 --- a/cura/ExtruderManager.py +++ b/cura/ExtruderManager.py @@ -39,7 +39,18 @@ 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 + ## The instance of the singleton pattern. + # + # It's None if the extruder manager hasn't been created yet. __instance = None + + ## Gets an instance of the extruder manager, or creates one if no instance + # exists yet. + # + # This is an implementation of singleton. If an extruder manager already + # exists, it is re-used. + # + # \return The extruder manager. @classmethod def getInstance(cls): if not cls.__instance: From 98a0f90dae4764bfb77ca6feaf92412e7716aaf3 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Tue, 7 Jun 2016 16:56:55 +0200 Subject: [PATCH 09/42] Remove unused variable _active_extruder_index This index is managed by ExtruderManager. Contributes to issues CURA-340 and CURA-1278. --- cura/MachineManagerModel.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/cura/MachineManagerModel.py b/cura/MachineManagerModel.py index 02d8db8290..e7034412f5 100644 --- a/cura/MachineManagerModel.py +++ b/cura/MachineManagerModel.py @@ -36,8 +36,6 @@ class MachineManagerModel(QObject): active_machine_id = Preferences.getInstance().getValue("cura/active_machine") - self._active_extruder_index = 0 - if active_machine_id != "": # An active machine was saved, so restore it. self.setActiveMachine(active_machine_id) From 8b1c36393261608ade3257386d613cb72d5e32cd Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Tue, 7 Jun 2016 17:37:25 +0200 Subject: [PATCH 10/42] Load current machine's extruders upon creation, start and switch of machines This requires some trickery of initialising the extruder manager before the machine manager is initialised, so that it properly listens to global container stack changes. Contributes to issues CURA-340 and CURA-1278. --- cura/CuraApplication.py | 1 + cura/ExtruderManager.py | 29 ++++++++++++++++++++++++----- cura/ExtrudersModel.py | 11 ++++++++--- 3 files changed, 33 insertions(+), 8 deletions(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 7edb0bf8bd..37ba6cf7ad 100644 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -351,6 +351,7 @@ class CuraApplication(QtApplication): self.showSplashMessage(self._i18n_catalog.i18nc("@info:progress", "Loading interface...")) + ExtruderManager.ExtruderManager.getInstance() #Initialise extruder so as to listen to global container stack changes before the first global container stack is set. qmlRegisterSingletonType(MachineManagerModel.MachineManagerModel, "Cura", 1, 0, "MachineManager", MachineManagerModel.createMachineManagerModel) diff --git a/cura/ExtruderManager.py b/cura/ExtruderManager.py index b40bb0f664..c71dd27414 100644 --- a/cura/ExtruderManager.py +++ b/cura/ExtruderManager.py @@ -1,7 +1,7 @@ # Copyright (c) 2016 Ultimaker B.V. # Cura is released under the terms of the AGPLv3 or higher. -from PyQt5.QtCore import pyqtSignal, pyqtProperty, pyqtSlot, QObject #For communicating data and events to Qt. +from PyQt5.QtCore import pyqtSignal, pyqtProperty, pyqtSlot, QObject, QVariant #For communicating data and events to Qt. import UM.Application #To get the global container stack to find the current machine. import UM.Logger @@ -13,7 +13,7 @@ import UM.Settings.ContainerRegistry #Finding containers by ID. # This keeps a list of extruder stacks for each machine. class ExtruderManager(QObject): ## Signal to notify other components when the list of extruders changes. - extrudersChanged = pyqtSignal() + extrudersChanged = pyqtSignal(QVariant) ## Notify when the user switches the currently active extruder. activeExtruderChanged = pyqtSignal() @@ -21,8 +21,9 @@ class ExtruderManager(QObject): ## Registers listeners and such to listen to changes to the extruders. def __init__(self, parent = None): super().__init__(parent) - self._extruder_trains = { } #Extruders for the current machine. + self._extruder_trains = { } #Per machine, a dictionary of extruder container stack IDs. self._active_extruder_index = 0 + UM.Application.getInstance().globalContainerStackChanged.connect(self._addCurrentMachineExtruders) ## Gets the unique identifier of the currently active extruder stack. # @@ -79,7 +80,7 @@ class ExtruderManager(QObject): for extruder_definition in container_registry.findDefinitionContainers(machine = machine_definition.getId()): position = extruder_definition.getMetaDataEntry("position", None) if not position: - UM.Logger.Log("w", "Extruder definition %s specifies no position metadata entry.", extruder_definition.getId()) + UM.Logger.log("w", "Extruder definition %s specifies no position metadata entry.", extruder_definition.getId()) if not container_registry.findContainerStacks(machine = machine_id, position = position): #Doesn't exist yet. name = container_registry.uniqueName(extruder_definition.getId()) #Make a name based on the ID of the definition. self.createExtruderTrain(extruder_definition, machine_definition, name, position) @@ -89,7 +90,7 @@ class ExtruderManager(QObject): for extruder_train in extruder_trains: self._extruder_trains[machine_id][extruder_train.getMetaDataEntry("position")] = extruder_train.getId() if extruder_trains: - self.extrudersChanged.emit() + self.extrudersChanged.emit(machine_definition) def createExtruderTrain(self, extruder_definition, machine_definition, extruder_train_id, position): container_registry = UM.Settings.ContainerRegistry.getInstance() @@ -156,3 +157,21 @@ class ExtruderManager(QObject): container_stack.setNextStack(UM.Application.getInstance().getGlobalContainerStack()) container_registry.addContainer(container_stack) + + ## Generates extruders for a specific machine. + def getMachineExtruders(self, machine_definition): + container_registry = UM.Settings.ContainerRegistry.getInstance() + machine_id = machine_definition.getId() + if not machine_id in self._extruder_trains: + UM.Logger.log("w", "Tried to get the extruder trains for machine %s, which doesn't exist.", machine_id) + return + for extruder_train_id in self._extruder_trains[machine_id]: + extruder_train = container_registry.findContainerStacks(id = extruder_train_id) + if extruder_train: + yield extruder_train[0] + + ## Adds the extruders of the currently active machine. + def _addCurrentMachineExtruders(self): + global_stack = UM.Application.getInstance().getGlobalContainerStack() + if global_stack and global_stack.getBottom(): + self.addMachineExtruders(global_stack.getBottom()) \ No newline at end of file diff --git a/cura/ExtrudersModel.py b/cura/ExtrudersModel.py index 7e00611742..691a5c7690 100644 --- a/cura/ExtrudersModel.py +++ b/cura/ExtrudersModel.py @@ -9,7 +9,8 @@ import UM.Qt.ListModel ## Model that holds extruders. # # This model is designed for use by any list of extruders, but specifically -# intended for drop-down lists of extruders in place of settings. +# intended for drop-down lists of the current machine's extruders in place of +# settings. class ExtrudersModel(UM.Qt.ListModel.ListModel): ## Human-readable name of the extruder. NameRole = Qt.UserRole + 1 @@ -37,7 +38,8 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel): #Listen to changes. manager = cura.ExtruderManager.ExtruderManager.getInstance() - manager.extrudersChanged.connect(self._updateExtruders) + manager.extrudersChanged.connect(self._updateExtruders) #When the list of extruders changes in general. + UM.Application.globalContainerStackChanged.connect(self._updateExtruders) #When the current machine changes. self._updateExtruders() ## Update the list of extruders. @@ -46,7 +48,10 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel): def _updateExtruders(self): self.clear() manager = cura.ExtruderManager.ExtruderManager.getInstance() - for index, extruder in enumerate(manager._extruder_trains): + global_container_stack = UM.Application.getInstance().getGlobalContainerStack() + if not global_container_stack: + return #There is no machine to get the extruders of. + for index, extruder in manager.getMachineExtruders(global_container_stack.getBottom()): item = { #Construct an item with only the relevant information. "name": extruder.name, "colour": extruder.material.getMetaDataEntry("color_code", default = "#FFFF00"), From 1a8fe6aa1fb7dd22034f02d61338d1e8d1faab04 Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Wed, 8 Jun 2016 10:55:48 +0200 Subject: [PATCH 11/42] Fix customised settings indicator CURA-1585 --- resources/qml/ProfileSetup.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/qml/ProfileSetup.qml b/resources/qml/ProfileSetup.qml index c6291c8c85..48d52c539a 100644 --- a/resources/qml/ProfileSetup.qml +++ b/resources/qml/ProfileSetup.qml @@ -143,7 +143,7 @@ Item{ UM.SimpleButton { id: customisedSettings - visible: UM.ActiveProfile.hasCustomisedValues + visible: Cura.MachineManager.hasUserSettings height: parent.height * 0.6 width: parent.height * 0.6 From 77431b01a3ddb88952c6d2283e420386cb92d19e Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Wed, 8 Jun 2016 11:02:04 +0200 Subject: [PATCH 12/42] Inherit button now has the same behaviour as 2.1 again CURA-1278 --- resources/qml/Settings/SettingItem.qml | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/resources/qml/Settings/SettingItem.qml b/resources/qml/Settings/SettingItem.qml index e4edc267ef..eb8fabec28 100644 --- a/resources/qml/Settings/SettingItem.qml +++ b/resources/qml/Settings/SettingItem.qml @@ -24,7 +24,7 @@ Item { // Create properties to put property provider stuff in (bindings break in qt 5.5.1 otherwise) property var state: propertyProvider.properties.state - property var stackLevel: propertyProvider.stackLevel + property var stackLevel: propertyProvider.stackLevels[0] signal contextMenuRequested() signal showTooltip(string text); @@ -166,7 +166,15 @@ Item { onClicked: { focus = true; - propertyProvider.removeFromContainer(base.stackLevel) + // Get the deepest entry of this setting that we can find. TODO: This is a bit naive, in some cases + // there might be multiple profiles saying something about the same setting. There is no strategy + // how to handle this as of yet. + var last_entry = propertyProvider.stackLevels.slice(-1)[0] + // Put that entry into the "top" instance container. + // This ensures that the value in any of the deeper containers need not be removed, which is + // needed for the reset button (which deletes the top value) to correctly go back to profile + // defaults. + propertyProvider.setPropertyValue("value", propertyProvider.getPropertyValue("value", last_entry)) } backgroundColor: UM.Theme.getColor("setting_control"); From af484b03d80a5379c5eebd38b1a26f3e89a66cfd Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Wed, 8 Jun 2016 10:45:32 +0200 Subject: [PATCH 13/42] Fix typo in variable name --- plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml | 2 +- resources/qml/Settings/SettingItem.qml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml b/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml index 9565b0e345..667f842469 100644 --- a/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml +++ b/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml @@ -61,7 +61,7 @@ Item { onLoaded: { settingLoader.item.showRevertButton = false settingLoader.item.showInheritButton = false - settingLoader.item.doDepthIdentation = false + settingLoader.item.doDepthIndentation = false } sourceComponent: diff --git a/resources/qml/Settings/SettingItem.qml b/resources/qml/Settings/SettingItem.qml index eb8fabec28..4fa615134b 100644 --- a/resources/qml/Settings/SettingItem.qml +++ b/resources/qml/Settings/SettingItem.qml @@ -20,7 +20,7 @@ Item { property var showRevertButton: true property var showInheritButton: true - property var doDepthIdentation: 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 @@ -101,7 +101,7 @@ Item { id: label; anchors.left: parent.left; - anchors.leftMargin: doDepthIdentation ? (UM.Theme.getSize("section_icon_column").width + 5) + ((definition.depth - 1) * UM.Theme.getSize("setting_control_depth_margin").width) : 0 + anchors.leftMargin: doDepthIndentation ? (UM.Theme.getSize("section_icon_column").width + 5) + ((definition.depth - 1) * UM.Theme.getSize("setting_control_depth_margin").width) : 0 anchors.right: settingControls.left; anchors.verticalCenter: parent.verticalCenter From 4aa495f9efa8dba6120c129f193186502c6d802b Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Wed, 8 Jun 2016 10:56:51 +0200 Subject: [PATCH 14/42] Fix getting name and colour from extruder There used to be an extruder object from which we could ask these properties. But now we have a container stack in its place, so we need to get the properties in a slightly different way. Contributes to issues CURA-1278 and CURA-340. --- cura/ExtrudersModel.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cura/ExtrudersModel.py b/cura/ExtrudersModel.py index 691a5c7690..cd85181787 100644 --- a/cura/ExtrudersModel.py +++ b/cura/ExtrudersModel.py @@ -53,8 +53,8 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel): return #There is no machine to get the extruders of. for index, extruder in manager.getMachineExtruders(global_container_stack.getBottom()): item = { #Construct an item with only the relevant information. - "name": extruder.name, - "colour": extruder.material.getMetaDataEntry("color_code", default = "#FFFF00"), + "name": extruder.getName(), + "colour": extruder.findContainer(type = "material").getMetaDataEntry("color_code", default = "#FFFF00"), "index": index } self.appendItem(item) From 675a8c140e1bf22ed9c396298ff150d66f9d7e69 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Wed, 8 Jun 2016 11:00:50 +0200 Subject: [PATCH 15/42] Give default colour if there is no material Otherwise it would try to call getMetaDataEntry on None. Contributes to issues CURA-340 and CURA-1278. --- cura/ExtrudersModel.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cura/ExtrudersModel.py b/cura/ExtrudersModel.py index cd85181787..a915a21506 100644 --- a/cura/ExtrudersModel.py +++ b/cura/ExtrudersModel.py @@ -52,9 +52,11 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel): if not global_container_stack: return #There is no machine to get the extruders of. for index, extruder in manager.getMachineExtruders(global_container_stack.getBottom()): + material = extruder.findContainer(type = "material") + colour = material.getMetaDataEntry("color_code", default = "#FFFF00") if material else "#FFFF00" item = { #Construct an item with only the relevant information. "name": extruder.getName(), - "colour": extruder.findContainer(type = "material").getMetaDataEntry("color_code", default = "#FFFF00"), + "colour": colour, "index": index } self.appendItem(item) From 91797c3944c24e41b16883bb55f48d4294c046c1 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Wed, 8 Jun 2016 11:09:08 +0200 Subject: [PATCH 16/42] Log error if the machine refers to invalid extruder train ID This helped mostly for debugging but it should be a genuine warning. Contributes to issues CURA-1278 and CURA-340. --- cura/ExtruderManager.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cura/ExtruderManager.py b/cura/ExtruderManager.py index c71dd27414..3be0694440 100644 --- a/cura/ExtruderManager.py +++ b/cura/ExtruderManager.py @@ -169,6 +169,8 @@ class ExtruderManager(QObject): extruder_train = container_registry.findContainerStacks(id = extruder_train_id) if extruder_train: yield extruder_train[0] + else: + UM.Logger.log("w", "Machine %s refers to an extruder train with ID %s, which doesn't exist.", machine_id, extruder_train_id) ## Adds the extruders of the currently active machine. def _addCurrentMachineExtruders(self): From 21545af5c8eb425faee88caf1ca703ea8ea9ef1a Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Wed, 8 Jun 2016 11:10:41 +0200 Subject: [PATCH 17/42] Get only values from extruder trains dictionary Instead of getting the keys, which are labeled '0' and '1', we'd like to get the values, which are the extruder train IDs themselves. Contributes to issues CURA-340 and CURA-1278. --- cura/ExtruderManager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cura/ExtruderManager.py b/cura/ExtruderManager.py index 3be0694440..8219066eca 100644 --- a/cura/ExtruderManager.py +++ b/cura/ExtruderManager.py @@ -165,7 +165,7 @@ class ExtruderManager(QObject): if not machine_id in self._extruder_trains: UM.Logger.log("w", "Tried to get the extruder trains for machine %s, which doesn't exist.", machine_id) return - for extruder_train_id in self._extruder_trains[machine_id]: + for _,extruder_train_id in self._extruder_trains[machine_id].items(): extruder_train = container_registry.findContainerStacks(id = extruder_train_id) if extruder_train: yield extruder_train[0] From 8c7b3a05b654e2eea12cf6a2a6525e6e97950bfc Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Wed, 8 Jun 2016 11:22:03 +0200 Subject: [PATCH 18/42] Enumerate again over the machine's extruders We needed to get the index, after all. Contributes to issues CURA-340 and CURA-1278. --- cura/ExtrudersModel.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cura/ExtrudersModel.py b/cura/ExtrudersModel.py index a915a21506..a95f9f8a99 100644 --- a/cura/ExtrudersModel.py +++ b/cura/ExtrudersModel.py @@ -51,7 +51,7 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel): global_container_stack = UM.Application.getInstance().getGlobalContainerStack() if not global_container_stack: return #There is no machine to get the extruders of. - for index, extruder in manager.getMachineExtruders(global_container_stack.getBottom()): + for index, extruder in enumerate(manager.getMachineExtruders(global_container_stack.getBottom())): material = extruder.findContainer(type = "material") colour = material.getMetaDataEntry("color_code", default = "#FFFF00") if material else "#FFFF00" item = { #Construct an item with only the relevant information. From 8b75a230a0adad455787278683863bd70c63df41 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Wed, 8 Jun 2016 11:24:41 +0200 Subject: [PATCH 19/42] Fix findContainer call without kwargs It has no kwargs. This needs to be provided as dictionary. Contributes to issues CURA-340 and CURA-1278. --- cura/ExtrudersModel.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cura/ExtrudersModel.py b/cura/ExtrudersModel.py index a95f9f8a99..60bd60abab 100644 --- a/cura/ExtrudersModel.py +++ b/cura/ExtrudersModel.py @@ -52,7 +52,7 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel): if not global_container_stack: return #There is no machine to get the extruders of. for index, extruder in enumerate(manager.getMachineExtruders(global_container_stack.getBottom())): - material = extruder.findContainer(type = "material") + material = extruder.findContainer({ "type": "material" }) colour = material.getMetaDataEntry("color_code", default = "#FFFF00") if material else "#FFFF00" item = { #Construct an item with only the relevant information. "name": extruder.getName(), From b53926b9de53abc85b2bd8a6345a34563c1acc9f Mon Sep 17 00:00:00 2001 From: Arjen Hiemstra Date: Wed, 8 Jun 2016 13:29:36 +0200 Subject: [PATCH 20/42] Exclude machine_settings from the settings visible in the sidebar Contrivbutes to CURA-1645 --- resources/qml/Settings/SettingView.qml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/resources/qml/Settings/SettingView.qml b/resources/qml/Settings/SettingView.qml index 6261496c84..a6bb60f865 100644 --- a/resources/qml/Settings/SettingView.qml +++ b/resources/qml/Settings/SettingView.qml @@ -29,7 +29,8 @@ ScrollView model: UM.SettingDefinitionsModel { id: definitionsModel; containerId: Cura.MachineManager.activeDefinitionId - visibilityHandler: UM.SettingPreferenceVisibilityHandler {} + exclude: ["machine_settings"] + visibilityHandler: UM.SettingPreferenceVisibilityHandler { } } delegate: Loader From 2cedc69ed19c309f9c348a6ca597ba5b1761d22b Mon Sep 17 00:00:00 2001 From: Arjen Hiemstra Date: Wed, 8 Jun 2016 13:46:30 +0200 Subject: [PATCH 21/42] Remove all special floating point handling code from SettingTextField Since we now always send setting values as string and the conversion from float to string already does the rounding, there is no need to also do it here. Contributes to CURA-1278 Contributes to CURA-389 --- resources/qml/Settings/SettingTextField.qml | 36 +-------------------- 1 file changed, 1 insertion(+), 35 deletions(-) diff --git a/resources/qml/Settings/SettingTextField.qml b/resources/qml/Settings/SettingTextField.qml index 2a1fb96330..bf6fc34c93 100644 --- a/resources/qml/Settings/SettingTextField.qml +++ b/resources/qml/Settings/SettingTextField.qml @@ -90,21 +90,11 @@ SettingItem Keys.onReleased: { -// text = text.replace(",", ".") // User convenience. We use dots for decimal values -// if(parseFloat(text) != base.parentValue) -// { -// base.valueChanged(parseFloat(text)); -// } - propertyProvider.setPropertyValue("value", text) } onEditingFinished: { -// if(parseFloat(text) != base.parentValue) -// { -// base.valueChanged(parseFloat(text)); -// } propertyProvider.setPropertyValue("value", text) } @@ -121,33 +111,9 @@ SettingItem { target: input property: "text" - value: control.format(propertyProvider.properties.value) + value: propertyProvider.properties.value when: !input.activeFocus } } - - //Rounds a floating point number to 4 decimals. This prevents floating - //point rounding errors. - // - //input: The number to round. - //decimals: The number of decimals (digits after the radix) to round to. - //return: The rounded number. - function roundFloat(input, decimals) - { - //First convert to fixed-point notation to round the number to 4 decimals and not introduce new floating point errors. - //Then convert to a string (is implicit). The fixed-point notation will be something like "3.200". - //Then remove any trailing zeroes and the radix. - return input.toFixed(decimals).replace(/\.?0*$/, ""); //Match on periods, if any ( \.? ), followed by any number of zeros ( 0* ), then the end of string ( $ ). - } - - //Formats a value for display in the text field. - // - //This correctly handles formatting of float values. - // - //input: The string value to format. - //return: The formatted string. - function format(inputValue) { - return parseFloat(inputValue) ? roundFloat(parseFloat(inputValue), 4) : inputValue //If it's a float, round to four decimals. - } } } From e53a961ba72e5090467689d9e95722f7d393d24d Mon Sep 17 00:00:00 2001 From: Tim Kuipers Date: Wed, 8 Jun 2016 13:49:27 +0200 Subject: [PATCH 22/42] JSON fix: topbottom thickness had max value for no apparent reason (CURA-1352) --- resources/definitions/fdmprinter.def.json | 1 - 1 file changed, 1 deletion(-) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index ec27abd9f5..2443e08b47 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -461,7 +461,6 @@ "unit": "mm", "default_value": 0.8, "minimum_value": "0", - "maximum_value": "5", "minimum_value_warning": "0.6", "type": "float", "children": From 163642f9ada9585f8582826b89c6f77c171b1a83 Mon Sep 17 00:00:00 2001 From: Arjen Hiemstra Date: Wed, 8 Jun 2016 14:05:16 +0200 Subject: [PATCH 23/42] Also remove the "current_settings" container when removing a machine Contributes to CURA-1628 --- cura/MachineManagerModel.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/cura/MachineManagerModel.py b/cura/MachineManagerModel.py index e7034412f5..2738bfd764 100644 --- a/cura/MachineManagerModel.py +++ b/cura/MachineManagerModel.py @@ -427,7 +427,13 @@ class MachineManagerModel(QObject): def removeMachine(self, machine_id): # 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) + + current_settings_id = machine_id + "_current_settings" + containers = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(id = current_settings_id) + for container in containers: + UM.Settings.ContainerRegistry.getInstance().removeContainer(container.getId()) UM.Settings.ContainerRegistry.getInstance().removeContainer(machine_id) + if activate_new_machine: stacks = UM.Settings.ContainerRegistry.getInstance().findContainerStacks(type = "machine") if stacks: From f6ece126c31f62e0984f6a5b31f35e827c3f2dc8 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Wed, 8 Jun 2016 12:22:45 +0200 Subject: [PATCH 24/42] Don't re-create user profile if one is loaded from files The user profiles are also saved because they are added to the container registry. So if one exists for this extruder, don't create a new blank name, but use the pre-loaded one which contained the user settings the user had before he closed down Cura previously. Contributes to issues CURA-340 and CURA-1278. --- cura/ExtruderManager.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/cura/ExtruderManager.py b/cura/ExtruderManager.py index 8219066eca..a5960be552 100644 --- a/cura/ExtruderManager.py +++ b/cura/ExtruderManager.py @@ -147,12 +147,15 @@ class ExtruderManager(QObject): self._container_stack.addContainer(self._quality) """ - #Add an empty user profile. - user_profile = UM.Settings.InstanceContainer(extruder_train_id + "_current_settings") - user_profile.addMetaDataEntry("type", "user") - user_profile.setDefinition(machine_definition) + user_profile = container_registry.findInstanceContainers(id = extruder_train_id + "_current_settings") + if user_profile: #There was already a user profile, loaded from settings. + user_profile = user_profile[0] + else: + user_profile = UM.Settings.InstanceContainer(extruder_train_id + "_current_settings") #Add an empty user profile. + user_profile.addMetaDataEntry("type", "user") + user_profile.setDefinition(machine_definition) + container_registry.addContainer(user_profile) container_stack.addContainer(user_profile) - container_registry.addContainer(user_profile) container_stack.setNextStack(UM.Application.getInstance().getGlobalContainerStack()) From 32f90ad8676d69e536f5775fa912d35e5ec44586 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Wed, 8 Jun 2016 13:19:46 +0200 Subject: [PATCH 25/42] Re-add per-extruder nozzles, materials, qualities Slightly more efficient and correct implementation.Contributes to issue CURA-340. --- cura/ExtruderManager.py | 77 +++++++++++++++++++++++------------------ 1 file changed, 44 insertions(+), 33 deletions(-) diff --git a/cura/ExtruderManager.py b/cura/ExtruderManager.py index a5960be552..e03bcfd3b3 100644 --- a/cura/ExtruderManager.py +++ b/cura/ExtruderManager.py @@ -93,7 +93,9 @@ class ExtruderManager(QObject): self.extrudersChanged.emit(machine_definition) def createExtruderTrain(self, extruder_definition, machine_definition, extruder_train_id, position): + #Cache some things. container_registry = UM.Settings.ContainerRegistry.getInstance() + machine_id = machine_definition.getId() #Create a container stack for this extruder. container_stack = UM.Settings.ContainerStack(extruder_train_id) @@ -102,50 +104,59 @@ class ExtruderManager(QObject): container_stack.addMetaDataEntry("position", position) container_stack.addContainer(extruder_definition) - """ - Yes, I'm committing this code which needs to be transformed to work later. #Find the nozzle to use for this extruder. nozzle = container_registry.getEmptyInstanceContainer() - if definition.getMetaDataEntry("has_nozzles", default = "False") == "True": - if len(self._nozzles) >= 1: #First add any extruder. Later, overwrite with preference if the preference is valid. - self._nozzle = self._nozzles[0] - preferred_nozzle_id = definition.getMetaDataEntry("preferred_nozzle") + if machine_definition.getMetaDataEntry("has_nozzles", default = "False") == "True": + #First add any nozzle. Later, overwrite with preference if the preference is valid. + nozzles = container_registry.findInstanceContainers(machine = machine_id, type = "nozzle") + if len(nozzles) >= 1: + nozzle = nozzles[0] + preferred_nozzle_id = machine_definition.getMetaDataEntry("preferred_nozzle") if preferred_nozzle_id: - for nozzle in self._nozzles: - if nozzle.getId() == preferred_nozzle_id: - self._nozzle = nozzle - break - self._container_stack.addContainer(self._nozzle) + preferred_nozzles = container_registry.findInstanceContainers(id = preferred_nozzle_id, type = "nozzle") + if len(preferred_nozzles) >= 1: + nozzle = preferred_nozzles[0] + else: + UM.Logger.log("w", "The preferred nozzle \"%s\" of machine %s doesn't exist or is not a nozzle profile.", preferred_nozzle_id, machine_id) + #And leave it at the default nozzle. + container_stack.addContainer(nozzle) #Find a material to use for this nozzle. - self._material = container_registry.getEmptyInstanceContainer() - if self._definition.getMetaDataEntry("has_materials", default = "False") == "True": - if self._definition.getMetaDataEntry("has_nozzle_materials", default = "False") == "True": - all_materials = container_registry.findInstanceContainers(type = "material", nozzle = self._nozzle.getId()) + material = container_registry.getEmptyInstanceContainer() + if machine_definition.getMetaDataEntry("has_materials", default = "False") == "True": + #First add any material. Later, overwrite with preference if the preference is valid. + if machine_definition.getMetaDataEntry("has_nozzle_materials", default = "False") == "True": + materials = container_registry.findInstanceContainers(type = "material", machine = machine_id, nozzle = nozzle.getId()) else: - all_materials = container_registry.findInstanceContainers(type = "material") - if len(all_materials) >= 1: - self._material = all_materials[0] - preferred_material_id = self._definition.getMetaDataEntry("preferred_material") + materials = container_registry.findInstanceContainers(type = "material", machine = machine_id) + if len(materials) >= 1: + material = materials[0] + preferred_material_id = machine_definition.getMetaDataEntry("preferred_material") if preferred_material_id: - preferred_material = container_registry.findInstanceContainers(type = "material", id = preferred_material_id.lower()) - if len(preferred_material) >= 1: - self._material = preferred_material[0] - self._container_stack.addContainer(self._material) + preferred_materials = container_registry.findInstanceContainers(id = preferred_material_id, type = "material") + if len(preferred_materials) >= 1: + material = preferred_materials[0] + else: + UM.Logger.log("w", "The preferred material \"%s\" of machine %s doesn't exist or is not a material profile.", preferred_material_id, machine_id) + #And leave it at the default material. + container_stack.addContainer(material) #Find a quality to use for this extruder. - self._quality = container_registry.getEmptyInstanceContainer() - if self._definition.getMetaDataEntry("has_machine_quality"): - all_qualities = container_registry.findInstanceContainers(type = "quality") - if len(all_qualities) >= 1: - self._quality = all_qualities[0] - preferred_quality_id = self._definition.getMetaDataEntry("preferred_quality") + quality = container_registry.getEmptyInstanceContainer() + if machine_definition.getMetaDataEntry("has_machine_quality"): + #First add any quality. Later, overwrite with preference if the preference is valid. + qualities = container_registry.findInstanceContainers(type = "quality") + if len(qualities) >= 1: + quality = qualities[0] + preferred_quality_id = machine_definition.getMetaDataEntry("preferred_quality") if preferred_quality_id: - preferred_quality = container_registry.findInstanceContainers(type = "quality", id = preferred_quality_id.lower()) + preferred_quality = container_registry.findInstanceContainers(id = preferred_quality_id.lower(), type = "quality") if len(preferred_quality) >= 1: - self._quality = preferred_quality[0] - self._container_stack.addContainer(self._quality) - """ + quality = preferred_quality[0] + else: + UM.Logger.log("w", "The preferred quality \"%s\" of machine %s doesn't exist or is not a quality profile.", preferred_quality_id, machine_id) + #And leave it at the default quality. + container_stack.addContainer(quality) user_profile = container_registry.findInstanceContainers(id = extruder_train_id + "_current_settings") if user_profile: #There was already a user profile, loaded from settings. From fffe9b3a943afa39621f803c21273f5c6c57b101 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Wed, 8 Jun 2016 13:56:42 +0200 Subject: [PATCH 26/42] Better naming for extruder slot The name of the extruder stack is now the same as the name for the extruder definition. The IDs are different though! Contributes to issues CURA-1278 and CURA-340. --- cura/ExtruderManager.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/cura/ExtruderManager.py b/cura/ExtruderManager.py index e03bcfd3b3..b67a7f1542 100644 --- a/cura/ExtruderManager.py +++ b/cura/ExtruderManager.py @@ -82,8 +82,7 @@ class ExtruderManager(QObject): if not position: UM.Logger.log("w", "Extruder definition %s specifies no position metadata entry.", extruder_definition.getId()) if not container_registry.findContainerStacks(machine = machine_id, position = position): #Doesn't exist yet. - name = container_registry.uniqueName(extruder_definition.getId()) #Make a name based on the ID of the definition. - self.createExtruderTrain(extruder_definition, machine_definition, name, position) + self.createExtruderTrain(extruder_definition, machine_definition, position) #Gets the extruder trains that we just created as well as any that still existed. extruder_trains = container_registry.findContainerStacks(type = "extruder_train", machine = machine_definition.getId()) @@ -92,13 +91,15 @@ class ExtruderManager(QObject): if extruder_trains: self.extrudersChanged.emit(machine_definition) - def createExtruderTrain(self, extruder_definition, machine_definition, extruder_train_id, position): + def createExtruderTrain(self, extruder_definition, machine_definition, position): #Cache some things. container_registry = UM.Settings.ContainerRegistry.getInstance() machine_id = machine_definition.getId() #Create a container stack for this extruder. - container_stack = UM.Settings.ContainerStack(extruder_train_id) + extruder_stack_id = container_registry.uniqueName(extruder_definition.getId()) + container_stack = UM.Settings.ContainerStack(extruder_stack_id) + container_stack.setName(extruder_definition.getName()) #Take over the display name to display the stack with. container_stack.addMetaDataEntry("type", "extruder_train") container_stack.addMetaDataEntry("machine", machine_definition.getId()) container_stack.addMetaDataEntry("position", position) @@ -158,11 +159,11 @@ class ExtruderManager(QObject): #And leave it at the default quality. container_stack.addContainer(quality) - user_profile = container_registry.findInstanceContainers(id = extruder_train_id + "_current_settings") + user_profile = container_registry.findInstanceContainers(id = extruder_stack_id + "_current_settings") if user_profile: #There was already a user profile, loaded from settings. user_profile = user_profile[0] else: - user_profile = UM.Settings.InstanceContainer(extruder_train_id + "_current_settings") #Add an empty user profile. + user_profile = UM.Settings.InstanceContainer(extruder_stack_id + "_current_settings") #Add an empty user profile. user_profile.addMetaDataEntry("type", "user") user_profile.setDefinition(machine_definition) container_registry.addContainer(user_profile) From 0a34577fdb898cc24e4cea1305bc53b24669c8f4 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Wed, 8 Jun 2016 13:59:26 +0200 Subject: [PATCH 27/42] Add documentation for createExtruderTrain Contributes to issues CURA-340 and CURA-1278. --- cura/ExtruderManager.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/cura/ExtruderManager.py b/cura/ExtruderManager.py index b67a7f1542..b4d05d7e6c 100644 --- a/cura/ExtruderManager.py +++ b/cura/ExtruderManager.py @@ -91,6 +91,20 @@ class ExtruderManager(QObject): if extruder_trains: self.extrudersChanged.emit(machine_definition) + ## Creates a container stack for an extruder train. + # + # The container stack has an extruder definition at the bottom, which is + # linked to a machine definition. Then it has a nozzle profile, a material + # profile, a quality profile and a user profile, in that order. + # + # The resulting container stack is added to the registry. + # + # \param extruder_definition The extruder to create the extruder train + # for. + # \param machine_definition The machine that the extruder train belongs + # to. + # \param position The position of this extruder train in the extruder + # slots of the machine. def createExtruderTrain(self, extruder_definition, machine_definition, position): #Cache some things. container_registry = UM.Settings.ContainerRegistry.getInstance() From 59c8a4e66d5c0b8f5a2cc1b5fbb2a3e9af9c4629 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Wed, 8 Jun 2016 14:16:13 +0200 Subject: [PATCH 28/42] Fix validation of extruder-type settings Based on how ints are validated, since the data is the same. Contributes to issues CURA-1278 and CURA-340. --- cura/CuraApplication.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 37ba6cf7ad..8acd3eda2a 100644 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -47,6 +47,7 @@ from PyQt5.QtCore import pyqtSlot, QUrl, pyqtSignal, pyqtProperty, QEvent, Q_ENU from PyQt5.QtGui import QColor, QIcon from PyQt5.QtQml import qmlRegisterUncreatableType, qmlRegisterSingletonType, qmlRegisterType +import ast #For literal eval of extruder setting types. import platform import sys import os.path @@ -92,7 +93,7 @@ class CuraApplication(QtApplication): # Need to do this before ContainerRegistry tries to load the machines SettingDefinition.addSupportedProperty("global_only", DefinitionPropertyType.Function, default = False) - SettingDefinition.addSettingType("extruder", int, str, UM.Settings.Validator) + SettingDefinition.addSettingType("extruder", str, ast.literal_eval, UM.Settings.Validator) super().__init__(name = "cura", version = CuraVersion, buildtype = CuraBuildType) From 061cbfe46bc4c9f8e32290484402a2b62a51b419 Mon Sep 17 00:00:00 2001 From: Tim Kuipers Date: Wed, 8 Jun 2016 14:20:06 +0200 Subject: [PATCH 29/42] JSON fix: make base of raft with thicker lines than nozzle size (CURA-695) --- resources/definitions/fdmprinter.def.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index da99c36d51..29db032aa1 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -1860,7 +1860,7 @@ "unit": "mm", "type": "float", "default_value": 1, - "value": "line_width", + "value": "line_width * 2", "minimum_value": "0.0001", "maximum_value_warning": "machine_nozzle_size * 2", "enabled": "adhesion_type == \"raft\"", @@ -1898,7 +1898,7 @@ "type": "float", "default_value": 1, "minimum_value": "0.0001", - "value": "line_width", + "value": "line_width * 2", "maximum_value_warning": "machine_nozzle_size * 2", "enabled": "adhesion_type == \"raft\"", "global_only": "True" From 3881ed8a61f40249b96c5e6f2103b73f588e95fb Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Wed, 8 Jun 2016 14:58:05 +0200 Subject: [PATCH 30/42] Fixed behaviour of inheritance button CURA-1278 --- resources/qml/Settings/SettingItem.qml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/resources/qml/Settings/SettingItem.qml b/resources/qml/Settings/SettingItem.qml index 4fa615134b..2f1a74dba6 100644 --- a/resources/qml/Settings/SettingItem.qml +++ b/resources/qml/Settings/SettingItem.qml @@ -24,7 +24,8 @@ Item { // Create properties to put property provider stuff in (bindings break in qt 5.5.1 otherwise) property var state: propertyProvider.properties.state - property var stackLevel: propertyProvider.stackLevels[0] + property var stackLevels: propertyProvider.stackLevels + property var stackLevel: stackLevels[0] signal contextMenuRequested() signal showTooltip(string text); @@ -159,7 +160,7 @@ Item { id: inheritButton; //visible: has_profile_value && base.has_inherit_function && base.is_enabled - visible: base.state == "InstanceState.User" && base.stackLevel > 0 && base.showInheritButton + visible: base.state == "InstanceState.User" && base.showInheritButton height: parent.height; width: height; @@ -175,6 +176,7 @@ Item { // needed for the reset button (which deletes the top value) to correctly go back to profile // defaults. propertyProvider.setPropertyValue("value", propertyProvider.getPropertyValue("value", last_entry)) + propertyProvider.setPropertyValue("state", "InstanceState.Calculated") } backgroundColor: UM.Theme.getColor("setting_control"); From cf15f9e2a11a593648bd4217408f6b64934858f6 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Wed, 8 Jun 2016 15:31:28 +0200 Subject: [PATCH 31/42] Added handling of special case when only user & definition were set CURA-1278 --- resources/qml/Settings/SettingItem.qml | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/resources/qml/Settings/SettingItem.qml b/resources/qml/Settings/SettingItem.qml index 2f1a74dba6..9ed75bdecf 100644 --- a/resources/qml/Settings/SettingItem.qml +++ b/resources/qml/Settings/SettingItem.qml @@ -175,8 +175,17 @@ Item { // This ensures that the value in any of the deeper containers need not be removed, which is // needed for the reset button (which deletes the top value) to correctly go back to profile // defaults. - propertyProvider.setPropertyValue("value", propertyProvider.getPropertyValue("value", last_entry)) - propertyProvider.setPropertyValue("state", "InstanceState.Calculated") + if(last_entry == 4 && base.stackLevel == 0) + { + // Special case of the inherit reset. If only the definition (4th container) and the first + // entry (user container) are set, we can simply remove the container. + propertyProvider.removeFromContainer(0) + } + else + { + propertyProvider.setPropertyValue("value", propertyProvider.getPropertyValue("value", last_entry)) + propertyProvider.setPropertyValue("state", "InstanceState.Calculated") + } } backgroundColor: UM.Theme.getColor("setting_control"); From 8a7e549a27c6b6f9fe28c7d944097f093fdf1224 Mon Sep 17 00:00:00 2001 From: Tim Kuipers Date: Wed, 8 Jun 2016 15:40:15 +0200 Subject: [PATCH 32/42] Merge fix of 2.1 Max Retraction count 45 ==> 90 wasn't taken along --- resources/definitions/fdmprinter.def.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index 29db032aa1..8be258c79e 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -890,7 +890,7 @@ "retraction_count_max": { "label": "Maximum Retraction Count", "description": "This setting limits the number of retractions occurring within the minimum extrusion distance window. Further retractions within this window will be ignored. This avoids retracting repeatedly on the same piece of filament, as that can flatten the filament and cause grinding issues.", - "default_value": 45, + "default_value": 90, "minimum_value": "0", "maximum_value_warning": "100", "type": "int", From cc7369c59476aa49bb7c515dc6dca2d4ce75db83 Mon Sep 17 00:00:00 2001 From: Tim Kuipers Date: Wed, 8 Jun 2016 15:43:22 +0200 Subject: [PATCH 33/42] profiles fix: duplicated UM2+ profile changes from 2.1 to the UM2E+ profiles (CURA-1662) --- .../ultimaker2_extended_plus/um2ep_abs_0.4_fast.inst.cfg | 2 ++ .../ultimaker2_extended_plus/um2ep_abs_0.4_high.inst.cfg | 1 + .../ultimaker2_extended_plus/um2ep_abs_0.4_normal.inst.cfg | 1 + .../ultimaker2_extended_plus/um2ep_abs_0.6_normal.inst.cfg | 1 + .../ultimaker2_extended_plus/um2ep_cpe_0.4_fast.inst.cfg | 1 + .../ultimaker2_extended_plus/um2ep_cpe_0.4_high.inst.cfg | 1 + .../ultimaker2_extended_plus/um2ep_cpe_0.4_normal.inst.cfg | 1 + 7 files changed, 8 insertions(+) diff --git a/resources/quality/ultimaker2_extended_plus/um2ep_abs_0.4_fast.inst.cfg b/resources/quality/ultimaker2_extended_plus/um2ep_abs_0.4_fast.inst.cfg index f554c7f058..139c8cb976 100644 --- a/resources/quality/ultimaker2_extended_plus/um2ep_abs_0.4_fast.inst.cfg +++ b/resources/quality/ultimaker2_extended_plus/um2ep_abs_0.4_fast.inst.cfg @@ -15,6 +15,8 @@ wall_thickness = 0.7 top_bottom_thickness = 0.75 infill_sparse_density = 18 speed_print = 55 +speed_wall = 40 +speed_topbottom = 30 speed_travel = 150 speed_layer_0 = 30 cool_min_layer_time = 3 diff --git a/resources/quality/ultimaker2_extended_plus/um2ep_abs_0.4_high.inst.cfg b/resources/quality/ultimaker2_extended_plus/um2ep_abs_0.4_high.inst.cfg index c1a8136cf5..8d021f4d91 100644 --- a/resources/quality/ultimaker2_extended_plus/um2ep_abs_0.4_high.inst.cfg +++ b/resources/quality/ultimaker2_extended_plus/um2ep_abs_0.4_high.inst.cfg @@ -15,6 +15,7 @@ wall_thickness = 1.05 top_bottom_thickness = 0.72 infill_sparse_density = 22 speed_print = 45 +speed_wall = 30 cool_min_layer_time = 3 cool_fan_speed_min = 20 cool_min_speed = 10 diff --git a/resources/quality/ultimaker2_extended_plus/um2ep_abs_0.4_normal.inst.cfg b/resources/quality/ultimaker2_extended_plus/um2ep_abs_0.4_normal.inst.cfg index eabc9827a1..3f89bdeee6 100644 --- a/resources/quality/ultimaker2_extended_plus/um2ep_abs_0.4_normal.inst.cfg +++ b/resources/quality/ultimaker2_extended_plus/um2ep_abs_0.4_normal.inst.cfg @@ -15,6 +15,7 @@ wall_thickness = 1.05 top_bottom_thickness = 0.8 infill_sparse_density = 20 speed_print = 45 +speed_wall = 30 cool_min_layer_time = 3 cool_fan_speed_min = 20 cool_min_speed = 10 diff --git a/resources/quality/ultimaker2_extended_plus/um2ep_abs_0.6_normal.inst.cfg b/resources/quality/ultimaker2_extended_plus/um2ep_abs_0.6_normal.inst.cfg index 64e0ec72fb..ea67bcc0b2 100644 --- a/resources/quality/ultimaker2_extended_plus/um2ep_abs_0.6_normal.inst.cfg +++ b/resources/quality/ultimaker2_extended_plus/um2ep_abs_0.6_normal.inst.cfg @@ -15,6 +15,7 @@ wall_thickness = 1.59 top_bottom_thickness = 1.2 infill_sparse_density = 20 speed_print = 40 +speed_infill = 55 cool_min_layer_time = 3 cool_fan_speed_min = 50 cool_min_speed = 20 diff --git a/resources/quality/ultimaker2_extended_plus/um2ep_cpe_0.4_fast.inst.cfg b/resources/quality/ultimaker2_extended_plus/um2ep_cpe_0.4_fast.inst.cfg index ae9b437010..5f402d50aa 100644 --- a/resources/quality/ultimaker2_extended_plus/um2ep_cpe_0.4_fast.inst.cfg +++ b/resources/quality/ultimaker2_extended_plus/um2ep_cpe_0.4_fast.inst.cfg @@ -15,6 +15,7 @@ wall_thickness = 0.7 top_bottom_thickness = 0.75 infill_sparse_density = 18 speed_print = 45 +speed_wall = 40 speed_travel = 150 speed_layer_0 = 30 cool_min_layer_time = 3 diff --git a/resources/quality/ultimaker2_extended_plus/um2ep_cpe_0.4_high.inst.cfg b/resources/quality/ultimaker2_extended_plus/um2ep_cpe_0.4_high.inst.cfg index e3fa254a74..2b35097f66 100644 --- a/resources/quality/ultimaker2_extended_plus/um2ep_cpe_0.4_high.inst.cfg +++ b/resources/quality/ultimaker2_extended_plus/um2ep_cpe_0.4_high.inst.cfg @@ -15,6 +15,7 @@ wall_thickness = 1.05 top_bottom_thickness = 0.72 infill_sparse_density = 22 speed_print = 45 +speed_wall = 30 cool_min_layer_time = 2 cool_fan_speed_min = 80 cool_min_speed = 15 diff --git a/resources/quality/ultimaker2_extended_plus/um2ep_cpe_0.4_normal.inst.cfg b/resources/quality/ultimaker2_extended_plus/um2ep_cpe_0.4_normal.inst.cfg index 48e767e1cb..41e9fab6d3 100644 --- a/resources/quality/ultimaker2_extended_plus/um2ep_cpe_0.4_normal.inst.cfg +++ b/resources/quality/ultimaker2_extended_plus/um2ep_cpe_0.4_normal.inst.cfg @@ -15,6 +15,7 @@ wall_thickness = 1.05 top_bottom_thickness = 0.8 infill_sparse_density = 20 speed_print = 45 +speed_wall = 30 cool_min_layer_time = 3 cool_fan_speed_min = 80 cool_min_speed = 10 From 860846880212c89f2b0aca718b23b15acba4a3e8 Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Wed, 8 Jun 2016 16:32:39 +0200 Subject: [PATCH 34/42] Add a method to get the id of the current user profile CURA-1668 --- cura/MachineManagerModel.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/cura/MachineManagerModel.py b/cura/MachineManagerModel.py index 2738bfd764..e719c05743 100644 --- a/cura/MachineManagerModel.py +++ b/cura/MachineManagerModel.py @@ -105,7 +105,7 @@ class MachineManagerModel(QObject): @pyqtSlot(str, str) def addMachine(self, name, definition_id): - definitions = UM.Settings.ContainerRegistry.getInstance().findDefinitionContainers(id=definition_id) + definitions = UM.Settings.ContainerRegistry.getInstance().findDefinitionContainers(id = definition_id) if definitions: definition = definitions[0] name = self._createUniqueName("machine", "", name, definition.getName()) @@ -205,6 +205,13 @@ class MachineManagerModel(QObject): def isGlobalStackValid(self): return self._global_stack_valid + @pyqtProperty(str, notify = globalContainerChanged) + def activeUserProfileId(self): + if self._global_container_stack: + return self._global_container_stack.getTop().getId() + + return "" + @pyqtProperty(str, notify = globalContainerChanged) def activeMachineName(self): if self._global_container_stack: From 1131623278227f9e7ab4db9b5fd42ff54a27f961 Mon Sep 17 00:00:00 2001 From: Arjen Hiemstra Date: Wed, 8 Jun 2016 16:33:58 +0200 Subject: [PATCH 35/42] Disable the property editor when the value of the setting is not used Contributes to CURA-1278 --- resources/qml/Settings/SettingItem.qml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/resources/qml/Settings/SettingItem.qml b/resources/qml/Settings/SettingItem.qml index 9ed75bdecf..8160489b01 100644 --- a/resources/qml/Settings/SettingItem.qml +++ b/resources/qml/Settings/SettingItem.qml @@ -205,6 +205,8 @@ Item { { id: controlContainer; + enabled: provider.isValueUsed + anchors.right: parent.right; anchors.rightMargin: UM.Theme.getSize("default_margin").width anchors.verticalCenter: parent.verticalCenter; From 485ae53660d5c234084403ab7d13125470ca7bcf Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Wed, 8 Jun 2016 16:35:10 +0200 Subject: [PATCH 36/42] Show quality profile and user profile settings side-by-side on Profiles manager Introduces ContainerSettingsModel, which can combine the settings of instances from multiple containers into one model. Towards CURA-1668 --- cura/ContainerSettingsModel.py | 104 +++++++++++++++++++++ cura/CuraApplication.py | 3 + resources/qml/Preferences/ProfilesPage.qml | 11 ++- 3 files changed, 115 insertions(+), 3 deletions(-) create mode 100644 cura/ContainerSettingsModel.py diff --git a/cura/ContainerSettingsModel.py b/cura/ContainerSettingsModel.py new file mode 100644 index 0000000000..23d20cd6e2 --- /dev/null +++ b/cura/ContainerSettingsModel.py @@ -0,0 +1,104 @@ +from UM.Application import Application +from UM.Qt.ListModel import ListModel + +from PyQt5.QtCore import pyqtProperty, Qt, pyqtSignal, pyqtSlot, QUrl + +from UM.Settings.ContainerRegistry import ContainerRegistry +from UM.Settings.InstanceContainer import InstanceContainer + +class ContainerSettingsModel(ListModel): + LabelRole = Qt.UserRole + 1 + CategoryRole = Qt.UserRole + 2 + UnitRole = Qt.UserRole + 3 + ValuesRole = Qt.UserRole + 4 + + def __init__(self, parent = None): + super().__init__(parent) + self.addRoleName(self.LabelRole, "label") + self.addRoleName(self.CategoryRole, "category") + self.addRoleName(self.UnitRole, "unit") + self.addRoleName(self.ValuesRole, "values") + + self._container_ids = [] + self._container = None + + self._global_container_stack = None + Application.getInstance().globalContainerStackChanged.connect(self._onGlobalContainerChanged) + self._update() + + def _onGlobalContainerChanged(self): + if self._global_container_stack: + self._global_container_stack.containersChanged.disconnect(self._onInstanceContainersChanged) + self._global_container_stack.propertyChanged.disconnect(self._onGlobalPropertyChanged) + + self._global_container_stack = Application.getInstance().getGlobalContainerStack() + + if self._global_container_stack: + Preferences.getInstance().setValue("cura/active_machine", self._global_container_stack.getId()) + self._global_container_stack.containersChanged.connect(self._onInstanceContainersChanged) + self._global_container_stack.propertyChanged.connect(self._onGlobalPropertyChanged) + + self._update() + + def _onGlobalPropertyChanged(self, key, property_name): + if property_name == "value": + self._update() + + def _onInstanceContainersChanged(self, container): + self._update() + + def _update(self): + self.clear() + + if len(self._container_ids) == 0: + return + + keys = [] + containers = [] + for container_id in self._container_ids: + container = ContainerRegistry.getInstance().findContainers(id = container_id) + if not container: + return + + keys = keys + list(container[0].getAllKeys()) + containers.append(container[0]) + + keys = list(set(keys)) + keys.sort() + + for key in keys: + definition = None + category = None + values = [] + for container in containers: + + instance = container.getInstance(key) + if instance: + definition = instance.definition + + # Traverse up to find the category + category = definition + while category.type != "category": + category = category.parent + + values.append(container.getProperty(key, "value")) + else: + values.append("") + + self.appendItem({ + "key": key, + "values": values, + "label": definition.label, + "unit": definition.unit, + "category": category.label + }) + + ## Set the id of the container which has the settings this model should list. + def setContainers(self, container_ids): + self._container_ids = container_ids + self._update() + + containersChanged = pyqtSignal() + @pyqtProperty("QVariantList", fset = setContainers, notify = containersChanged) + def containers(self): + return self.container_ids \ No newline at end of file diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 8acd3eda2a..9abfabc7b2 100644 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -42,6 +42,7 @@ from . import MultiMaterialDecorator from . import ZOffsetDecorator from . import CuraSplashScreen from . import MachineManagerModel +from . import ContainerSettingsModel from PyQt5.QtCore import pyqtSlot, QUrl, pyqtSignal, pyqtProperty, QEvent, Q_ENUMS from PyQt5.QtGui import QColor, QIcon @@ -400,6 +401,8 @@ class CuraApplication(QtApplication): qmlRegisterType(ExtrudersModel.ExtrudersModel, "Cura", 1, 0, "ExtrudersModel") + qmlRegisterType(ContainerSettingsModel.ContainerSettingsModel, "Cura", 1, 0, "ContainerSettingsModel") + qmlRegisterSingletonType(QUrl.fromLocalFile(Resources.getPath(CuraApplication.ResourceTypes.QmlFiles, "Actions.qml")), "Cura", 1, 0, "Actions") engine.rootContext().setContextProperty("ExtruderManager", ExtruderManager.ExtruderManager.getInstance()) diff --git a/resources/qml/Preferences/ProfilesPage.qml b/resources/qml/Preferences/ProfilesPage.qml index ed9c20f65f..ee7653f96e 100644 --- a/resources/qml/Preferences/ProfilesPage.qml +++ b/resources/qml/Preferences/ProfilesPage.qml @@ -128,16 +128,21 @@ UM.ManagementPage anchors.bottom: parent.bottom ListView { - model: base.currentItem ? base.currentItem.settings: null + model: Cura.ContainerSettingsModel{ containers: [base.currentItem.id, Cura.MachineManager.activeUserProfileId] } delegate: Row { + property variant setting: model spacing: UM.Theme.getSize("default_margin").width Label { text: model.label elide: Text.ElideMiddle width: scrollView.width / 100 * 40 } - Label { - text: model.value.toString() + Repeater { + model: setting.values.length + Label { + text: setting.values[index].toString() + width: scrollView.width / 100 * 10 + } } Label { text: model.unit From 7dbafa06d1ae2b53e77726dee45662d721470ccb Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Wed, 8 Jun 2016 16:00:52 +0200 Subject: [PATCH 37/42] Make SidebarHeader use ExtrudersModel This model is also used by the extruder selection drop-downs, and it's automatically filled already so that was double logic. Contributes to issues CURA-340 and CURA-1278. --- resources/qml/SidebarHeader.qml | 29 ++++------------------------- 1 file changed, 4 insertions(+), 25 deletions(-) diff --git a/resources/qml/SidebarHeader.qml b/resources/qml/SidebarHeader.qml index 237746ac0d..75f5393d57 100644 --- a/resources/qml/SidebarHeader.qml +++ b/resources/qml/SidebarHeader.qml @@ -104,7 +104,7 @@ Item anchors.leftMargin: model.index * (extruderSelection.width / machineExtruderCount.properties.value) anchors.verticalCenter: parent.verticalCenter width: parent.width / machineExtruderCount.properties.value - text: model.text + text: model.name exclusiveGroup: extruderMenuGroup; checkable: true; checked: base.currentExtruderIndex == index @@ -138,10 +138,11 @@ Item } } ExclusiveGroup { id: extruderMenuGroup; } - ListView{ + ListView + { id: extrudersList property var index: 0 - model: extrudersListModel + model: Cura.ExtrudersModel {} delegate: wizardDelegate anchors.top: parent.top anchors.left: parent.left @@ -149,28 +150,6 @@ Item } } - ListModel - { - id: extrudersListModel - Component.onCompleted: populateExtruderModel() - } - Connections - { - id: machineChange - target: Cura.MachineManager - onGlobalContainerChanged: populateExtruderModel() - } - - function populateExtruderModel() - { - extrudersListModel.clear(); - for(var extruder = 0; extruder < machineExtruderCount.properties.value ; extruder++) { - extrudersListModel.append({ - text: catalog.i18nc("@label", "Extruder %1").arg(extruder + 1) - }) - } - } - Rectangle { id: variantRow anchors.top: extruderSelection.visible ? extruderSelection.bottom : machineSelectionRow.bottom From 4d418a7c1a94ddfe11a3f3e6b252821b9e077d73 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Wed, 8 Jun 2016 16:26:57 +0200 Subject: [PATCH 38/42] When switching active extruder, get the extruder train from definition id Not from extruder container stack ID. Contributes to issues CURA-340 and CURA-1278. --- cura/ExtruderManager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cura/ExtruderManager.py b/cura/ExtruderManager.py index b4d05d7e6c..c8a07a4000 100644 --- a/cura/ExtruderManager.py +++ b/cura/ExtruderManager.py @@ -36,7 +36,7 @@ class ExtruderManager(QObject): if not UM.Application.getInstance().getGlobalContainerStack(): return None #No active machine, so no active extruder. try: - return self._extruder_trains[UM.Application.getInstance().getGlobalContainerStack().getId()][str(self._active_extruder_index)] + return self._extruder_trains[UM.Application.getInstance().getGlobalContainerStack().getBottom().getId()][str(self._active_extruder_index)] 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 From da467b9b2806af69fb55f51f2b8a73b095c69cd6 Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Wed, 8 Jun 2016 16:45:20 +0200 Subject: [PATCH 39/42] Only shown the current settings column when the currently active quality profile is selected CURA-1668 --- resources/qml/Preferences/ProfilesPage.qml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/qml/Preferences/ProfilesPage.qml b/resources/qml/Preferences/ProfilesPage.qml index ee7653f96e..3307c1e2a5 100644 --- a/resources/qml/Preferences/ProfilesPage.qml +++ b/resources/qml/Preferences/ProfilesPage.qml @@ -93,7 +93,7 @@ UM.ManagementPage Row { id: currentSettingsActions - visible: base.currentItem.id == -1 || currentItem.id == Cura.MachineManager.activeQualityId + visible: currentItem.id == Cura.MachineManager.activeQualityId anchors.left: parent.left anchors.top: profileName.bottom @@ -128,7 +128,7 @@ UM.ManagementPage anchors.bottom: parent.bottom ListView { - model: Cura.ContainerSettingsModel{ containers: [base.currentItem.id, Cura.MachineManager.activeUserProfileId] } + model: Cura.ContainerSettingsModel{ containers: (currentItem.id == Cura.MachineManager.activeQualityId) ? [base.currentItem.id, Cura.MachineManager.activeUserProfileId] : [base.currentItem.id] } delegate: Row { property variant setting: model spacing: UM.Theme.getSize("default_margin").width From 07b51d0ca8813f95a76e252651113bf398c68010 Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Wed, 8 Jun 2016 17:04:04 +0200 Subject: [PATCH 40/42] Strike out profile value if it is overridden by the current setting CURA-1668 --- resources/qml/Preferences/ProfilesPage.qml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/resources/qml/Preferences/ProfilesPage.qml b/resources/qml/Preferences/ProfilesPage.qml index 3307c1e2a5..14569464d6 100644 --- a/resources/qml/Preferences/ProfilesPage.qml +++ b/resources/qml/Preferences/ProfilesPage.qml @@ -142,6 +142,8 @@ UM.ManagementPage Label { text: setting.values[index].toString() width: scrollView.width / 100 * 10 + font.strikeout: index < setting.values.length - 1 && setting.values[index + 1] != "" + opacity: font.strikeout ? 0.5 : 1 } } Label { From fcd6f0959f0b15281074af4ab717eb8536e0660c Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Wed, 8 Jun 2016 17:47:23 +0200 Subject: [PATCH 41/42] Inheritance button now only shows if there is a function in the container stack at some point CURA-1278 --- resources/qml/Settings/SettingItem.qml | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/resources/qml/Settings/SettingItem.qml b/resources/qml/Settings/SettingItem.qml index 9ed75bdecf..1b80cb68f5 100644 --- a/resources/qml/Settings/SettingItem.qml +++ b/resources/qml/Settings/SettingItem.qml @@ -158,9 +158,24 @@ Item { { // This button shows when the setting has an inherited function, but is overriden by profile. id: inheritButton; - - //visible: has_profile_value && base.has_inherit_function && base.is_enabled - visible: base.state == "InstanceState.User" && base.showInheritButton + // Inherit button needs to be visible if; + // - User made changes that override any loaded settings + // - This setting item uses inherit button at all + // - The type of the value of any deeper container is an "object" (eg; is a function) + visible: + { + var state = base.state == "InstanceState.User"; + var has_setting_function = false; + for (var i = 1; i < base.stackLevels.length; i++) + { + has_setting_function = typeof(propertyProvider.getPropertyValue("value", base.stackLevels[i])) == "object"; + if(has_setting_function) + { + break; + } + } + return state && base.showInheritButton && has_setting_function + } height: parent.height; width: height; From ca308c5b05f37d0205b5392e31de927eae0a5b31 Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Wed, 8 Jun 2016 17:50:54 +0200 Subject: [PATCH 42/42] Add notice if a profile has no settings, and if the current settings are "empty" CURA-1668, CURA-696 --- resources/qml/Preferences/ProfilesPage.qml | 26 +++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/resources/qml/Preferences/ProfilesPage.qml b/resources/qml/Preferences/ProfilesPage.qml index 14569464d6..97dd2c5d77 100644 --- a/resources/qml/Preferences/ProfilesPage.qml +++ b/resources/qml/Preferences/ProfilesPage.qml @@ -118,11 +118,35 @@ UM.ManagementPage } } + Column { + id: profileNotices + anchors.top: currentSettingsActions.visible ? currentSettingsActions.bottom : currentSettingsActions.anchors.top + anchors.topMargin: UM.Theme.getSize("default_margin").height + anchors.left: parent.left + anchors.right: parent.right + spacing: UM.Theme.getSize("default_margin").height + + Label { + id: defaultsMessage + visible: !currentItem.hasSettings + text: catalog.i18nc("@action:label", "This profile has no settings and uses the defaults specified by the printer.") + wrapMode: Text.WordWrap + width: parent.width + } + Label { + id: noCurrentSettingsMessage + visible: currentItem.id == Cura.MachineManager.activeQualityId && !Cura.MachineManager.hasUserSettings + text: catalog.i18nc("@action:label", "Your current settings match the selected profile.") + wrapMode: Text.WordWrap + width: parent.width + } + } + ScrollView { id: scrollView anchors.left: parent.left - anchors.top: currentSettingsActions.visible ? currentSettingsActions.bottom : profileName.bottom + anchors.top: profileNotices.visible ? profileNotices.bottom : profileNotices.anchors.top anchors.topMargin: UM.Theme.getSize("default_margin").height anchors.right: parent.right anchors.bottom: parent.bottom