From cf94c8d37d0fa431d587d166165d86154fa86dea Mon Sep 17 00:00:00 2001 From: Diego Prado Gesto Date: Fri, 22 Sep 2017 14:47:20 +0200 Subject: [PATCH 1/6] Working on fixing several issues with profiles - CURA-4327 --- cura/QualityManager.py | 25 ++++++++++++ cura/Settings/ProfilesModel.py | 62 +++++++++++++++++++---------- cura/Settings/UserProfilesModel.py | 29 ++++++++++---- resources/qml/Menus/ProfileMenu.qml | 2 +- 4 files changed, 88 insertions(+), 30 deletions(-) diff --git a/cura/QualityManager.py b/cura/QualityManager.py index c0b5afb71e..763599ac73 100644 --- a/cura/QualityManager.py +++ b/cura/QualityManager.py @@ -64,6 +64,19 @@ class QualityManager: result = [quality_change for quality_change in result if quality_change.getName() == quality_changes_name] return result + ## Fetch the list of available quality types for this machine definition. + # + # \param machine_definition \type{DefinitionContainer} + # \param material_containers \type{List[InstanceContainer]} + # \return \type{List[str]} + def findAllQualityTypesForMachine(self, machine_definition: "DefinitionContainerInterface") -> List[str]: + # Determine the common set of quality types which can be + # applied to all of the materials for this machine. + quality_type_dict = self.__fetchQualityTypeDict(machine_definition) + common_quality_types = set(quality_type_dict.keys()) + + return list(common_quality_types) + ## Fetch the list of available quality types for this combination of machine definition and materials. # # \param machine_definition \type{DefinitionContainer} @@ -91,6 +104,18 @@ class QualityManager: return list(qualities) + ## Fetches a dict of quality types names to quality profiles for a combination of machine and material. + # + # \param machine_definition \type{DefinitionContainer} the machine definition. + # \param material \type{InstanceContainer} the material. + # \return \type{Dict[str, InstanceContainer]} the dict of suitable quality type names mapping to qualities. + def __fetchQualityTypeDict(self, machine_definition: "DefinitionContainerInterface") -> Dict[str, InstanceContainer]: + qualities = self.findAllQualitiesForMachineMaterial(machine_definition, None) + quality_type_dict = {} + for quality in qualities: + quality_type_dict[quality.getMetaDataEntry("quality_type")] = quality + return quality_type_dict + ## Fetches a dict of quality types names to quality profiles for a combination of machine and material. # # \param machine_definition \type{DefinitionContainer} the machine definition. diff --git a/cura/Settings/ProfilesModel.py b/cura/Settings/ProfilesModel.py index c7348ea920..9fcffc9f57 100644 --- a/cura/Settings/ProfilesModel.py +++ b/cura/Settings/ProfilesModel.py @@ -54,7 +54,7 @@ class ProfilesModel(InstanceContainersModel): global_container_stack = Application.getInstance().getGlobalContainerStack() if global_container_stack is None: return [] - global_stack_definition = global_container_stack.getBottom() + # global_stack_definition = global_container_stack.getBottom() # Get the list of extruders and place the selected extruder at the front of the list. extruder_manager = ExtruderManager.getInstance() @@ -64,23 +64,26 @@ class ProfilesModel(InstanceContainersModel): extruder_stacks.remove(active_extruder) extruder_stacks = [active_extruder] + extruder_stacks - if ExtruderManager.getInstance().getActiveExtruderStacks(): - # Multi-extruder machine detected. - materials = [extruder.material for extruder in extruder_stacks] - else: - # Machine with one extruder. - materials = [global_container_stack.material] + # if ExtruderManager.getInstance().getActiveExtruderStacks(): + # # Multi-extruder machine detected. + # materials = [extruder.material for extruder in extruder_stacks] + # else: + # # Machine with one extruder. + # materials = [global_container_stack.material] + # + # # Fetch the list of usable qualities across all extruders. + # # The actual list of quality profiles come from the first extruder in the extruder list. + # result = QualityManager.getInstance().findAllQualitiesForMachineAndMaterials(global_stack_definition, + # materials) + # + # for quality in QualityManager.getInstance().findAllUsableQualitiesForMachineAndExtruders( + # global_container_stack, extruder_stacks): + # if quality not in result: + # result.append(quality) + quality_list = QualityManager.getInstance().findAllUsableQualitiesForMachineAndExtruders(global_container_stack, + extruder_stacks) - # Fetch the list of usable qualities across all extruders. - # The actual list of quality profiles come from the first extruder in the extruder list. - result = QualityManager.getInstance().findAllQualitiesForMachineAndMaterials(global_stack_definition, - materials) - - for quality in QualityManager.getInstance().findAllUsableQualitiesForMachineAndExtruders( - global_container_stack, extruder_stacks): - if quality not in result: - result.append(quality) - return result + return quality_list ## Re-computes the items in this model, and adds the layer height role. def _recomputeItems(self): @@ -93,12 +96,18 @@ class ProfilesModel(InstanceContainersModel): extruder_manager = ExtruderManager.getInstance() active_extruder = extruder_manager.getActiveExtruderStack() extruder_stacks = extruder_manager.getActiveExtruderStacks() + material = global_container_stack.material if active_extruder in extruder_stacks: extruder_stacks.remove(active_extruder) extruder_stacks = [active_extruder] + extruder_stacks + material = active_extruder.material + # Get a list of available qualities for this machine and material qualities = QualityManager.getInstance().findAllUsableQualitiesForMachineAndExtruders(global_container_stack, extruder_stacks) + + all_qualities = QualityManager.getInstance().findAllQualitiesForMachineMaterial(global_container_stack.getBottom(), material) + container_registry = ContainerRegistry.getInstance() machine_manager = Application.getInstance().getMachineManager() @@ -125,12 +134,23 @@ class ProfilesModel(InstanceContainersModel): for key in reversed(tmp_all_quality_items.keys()): all_quality_items[key] = tmp_all_quality_items[key] + # First the suitable containers are set in the model + containers = [] for data_item in all_quality_items.values(): - item = data_item["suitable_container"] - if item is None: - item = data_item["all_containers"][0] + suitable_item = data_item["suitable_container"] + if suitable_item is None: + suitable_item = data_item["all_containers"][0] + containers.append(suitable_item) - profile = container_registry.findContainers(id = item["id"]) + # Once the suitable containers are collected, the rest of the containers are appended + for data_item in all_quality_items.values(): + for item in data_item["all_containers"]: + if item not in containers: + containers.append(item) + + # Now all the containers are set + for item in containers: + profile = container_registry.findContainers(id=item["id"]) if not profile: item["layer_height"] = "" # Can't update a profile that is unknown. item["available"] = False diff --git a/cura/Settings/UserProfilesModel.py b/cura/Settings/UserProfilesModel.py index 07669422d2..fdb44ce313 100644 --- a/cura/Settings/UserProfilesModel.py +++ b/cura/Settings/UserProfilesModel.py @@ -25,17 +25,30 @@ class UserProfilesModel(ProfilesModel): machine_definition = quality_manager.getParentMachineDefinition(global_container_stack.getBottom()) quality_changes_list = quality_manager.findAllQualityChangesForMachine(machine_definition) - # Fetch the list of qualities - quality_list = QualityManager.getInstance().findAllUsableQualitiesForMachineAndExtruders(global_container_stack, - ExtruderManager.getInstance().getActiveExtruderStacks()) + # Detecting if the machine has multiple extrusion + multiple_extrusion = False + # Get the list of extruders and place the selected extruder at the front of the list. + extruder_manager = ExtruderManager.getInstance() + active_extruder = extruder_manager.getActiveExtruderStack() + extruder_stacks = extruder_manager.getActiveExtruderStacks() + if active_extruder in extruder_stacks: + multiple_extrusion = True + extruder_stacks.remove(active_extruder) + extruder_stacks = [active_extruder] + extruder_stacks + + # Fetch the list of useable qualities across all extruders. + # The actual list of quality profiles come from the first extruder in the extruder list. + quality_list = quality_manager.findAllUsableQualitiesForMachineAndExtruders(global_container_stack, + extruder_stacks) # Filter the quality_change by the list of available quality_types quality_type_set = set([x.getMetaDataEntry("quality_type") for x in quality_list]) - filtered_quality_changes = [qc for qc in quality_changes_list if qc.getMetaDataEntry("quality_type") in quality_type_set] - #Only display the global quality changes. - #Otherwise you get multiple copies of every quality changes profile. - #The actual profile switching goes by profile name (not ID), and as long as the names are consistent, switching to any of the profiles will cause all stacks to switch. - filtered_quality_changes = list(filter(lambda quality_changes: quality_changes.getMetaDataEntry("extruder") is None, filtered_quality_changes)) + if multiple_extrusion: + # If the printer has multiple extruders then quality changes related to the current extruder are kept + filtered_quality_changes = [qc for qc in quality_changes_list if qc.getMetaDataEntry("quality_type") in quality_type_set and qc.getMetaDataEntry("extruder") == active_extruder.definition.getId()] + else: + # If not, the quality changes of the global stack are selected + filtered_quality_changes = [qc for qc in quality_changes_list if qc.getMetaDataEntry("quality_type") in quality_type_set] return filtered_quality_changes diff --git a/resources/qml/Menus/ProfileMenu.qml b/resources/qml/Menus/ProfileMenu.qml index d6412c50be..0ed4448d1b 100644 --- a/resources/qml/Menus/ProfileMenu.qml +++ b/resources/qml/Menus/ProfileMenu.qml @@ -43,7 +43,7 @@ Menu { text: model.name + " - " + model.layer_height checkable: true - checked: Cura.MachineManager.globalQualityId == model.id + checked: Cura.MachineManager.activeQualityChangesId == model.id exclusiveGroup: group onTriggered: Cura.MachineManager.setActiveQuality(model.id) } From c22928f5d1bdc2a53f7360eaf36d85e73dc44798 Mon Sep 17 00:00:00 2001 From: Diego Prado Gesto Date: Mon, 25 Sep 2017 08:43:57 +0200 Subject: [PATCH 2/6] Change behavior when there is no suitable item - CURA-4327 --- cura/Settings/ProfilesModel.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/cura/Settings/ProfilesModel.py b/cura/Settings/ProfilesModel.py index 9fcffc9f57..715f290352 100644 --- a/cura/Settings/ProfilesModel.py +++ b/cura/Settings/ProfilesModel.py @@ -106,7 +106,10 @@ class ProfilesModel(InstanceContainersModel): qualities = QualityManager.getInstance().findAllUsableQualitiesForMachineAndExtruders(global_container_stack, extruder_stacks) - all_qualities = QualityManager.getInstance().findAllQualitiesForMachineMaterial(global_container_stack.getBottom(), material) + all_qualities = [] + for extruder in extruder_stacks: + all_qualities.append(QualityManager.getInstance().findAllQualitiesForMachineMaterial(global_container_stack.getBottom(), extruder.material)) + all_qualities2 = QualityManager.getInstance().findAllUsableQualitiesForMachineAndExtruders(global_container_stack, []) container_registry = ContainerRegistry.getInstance() machine_manager = Application.getInstance().getMachineManager() @@ -138,9 +141,8 @@ class ProfilesModel(InstanceContainersModel): containers = [] for data_item in all_quality_items.values(): suitable_item = data_item["suitable_container"] - if suitable_item is None: - suitable_item = data_item["all_containers"][0] - containers.append(suitable_item) + if suitable_item is not None: + containers.append(suitable_item) # Once the suitable containers are collected, the rest of the containers are appended for data_item in all_quality_items.values(): From d7ed8244ae002bcedef19d92701c3dfe30c0ecfd Mon Sep 17 00:00:00 2001 From: alekseisasin Date: Mon, 25 Sep 2017 14:32:02 +0200 Subject: [PATCH 3/6] In project loading dialog the CANCLE button did not work CURA-4345 --- plugins/3MFReader/WorkspaceDialog.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/plugins/3MFReader/WorkspaceDialog.py b/plugins/3MFReader/WorkspaceDialog.py index 75ee5c30f0..b77e687885 100644 --- a/plugins/3MFReader/WorkspaceDialog.py +++ b/plugins/3MFReader/WorkspaceDialog.py @@ -235,7 +235,7 @@ class WorkspaceDialog(QObject): self._result["definition_changes"] = None # If the machine needs to be re-created, the definition_changes should also be re-created. - if self._result["machine"] == "new" and self._result["definition_changes"] is None: + if "machine" in self._result and self._result["machine"] == "new" and self._result["definition_changes"] is None: self._result["definition_changes"] = "new" if "material" in self._result and not self._has_material_conflict: @@ -267,7 +267,7 @@ class WorkspaceDialog(QObject): @pyqtSlot() ## Used to notify the dialog so the lock can be released. def notifyClosed(self): - self._result = {} + self._result = {} # The result should be cleared before hide, because after it is released the main thread lock self._visible = False self._lock.release() @@ -283,9 +283,10 @@ class WorkspaceDialog(QObject): @pyqtSlot() def onCancelButtonClicked(self): + self._result = {} self._view.hide() self.hide() - self._result = {} + ## Block thread until the dialog is closed. def waitForClose(self): From 2ae1700a156eebbd6a930245fd5d0f81cf78ee75 Mon Sep 17 00:00:00 2001 From: Diego Prado Gesto Date: Mon, 25 Sep 2017 14:43:29 +0200 Subject: [PATCH 4/6] Solved the issue with the slider that was no showing in gray the unavailable profiles - CURA-4327 --- cura/QualityManager.py | 25 ---------------- cura/Settings/ProfilesModel.py | 53 +++++++++++++++------------------- 2 files changed, 23 insertions(+), 55 deletions(-) diff --git a/cura/QualityManager.py b/cura/QualityManager.py index 763599ac73..c0b5afb71e 100644 --- a/cura/QualityManager.py +++ b/cura/QualityManager.py @@ -64,19 +64,6 @@ class QualityManager: result = [quality_change for quality_change in result if quality_change.getName() == quality_changes_name] return result - ## Fetch the list of available quality types for this machine definition. - # - # \param machine_definition \type{DefinitionContainer} - # \param material_containers \type{List[InstanceContainer]} - # \return \type{List[str]} - def findAllQualityTypesForMachine(self, machine_definition: "DefinitionContainerInterface") -> List[str]: - # Determine the common set of quality types which can be - # applied to all of the materials for this machine. - quality_type_dict = self.__fetchQualityTypeDict(machine_definition) - common_quality_types = set(quality_type_dict.keys()) - - return list(common_quality_types) - ## Fetch the list of available quality types for this combination of machine definition and materials. # # \param machine_definition \type{DefinitionContainer} @@ -104,18 +91,6 @@ class QualityManager: return list(qualities) - ## Fetches a dict of quality types names to quality profiles for a combination of machine and material. - # - # \param machine_definition \type{DefinitionContainer} the machine definition. - # \param material \type{InstanceContainer} the material. - # \return \type{Dict[str, InstanceContainer]} the dict of suitable quality type names mapping to qualities. - def __fetchQualityTypeDict(self, machine_definition: "DefinitionContainerInterface") -> Dict[str, InstanceContainer]: - qualities = self.findAllQualitiesForMachineMaterial(machine_definition, None) - quality_type_dict = {} - for quality in qualities: - quality_type_dict[quality.getMetaDataEntry("quality_type")] = quality - return quality_type_dict - ## Fetches a dict of quality types names to quality profiles for a combination of machine and material. # # \param machine_definition \type{DefinitionContainer} the machine definition. diff --git a/cura/Settings/ProfilesModel.py b/cura/Settings/ProfilesModel.py index 715f290352..c5de9b9136 100644 --- a/cura/Settings/ProfilesModel.py +++ b/cura/Settings/ProfilesModel.py @@ -54,36 +54,36 @@ class ProfilesModel(InstanceContainersModel): global_container_stack = Application.getInstance().getGlobalContainerStack() if global_container_stack is None: return [] - # global_stack_definition = global_container_stack.getBottom() + global_stack_definition = global_container_stack.getBottom() # Get the list of extruders and place the selected extruder at the front of the list. extruder_manager = ExtruderManager.getInstance() active_extruder = extruder_manager.getActiveExtruderStack() extruder_stacks = extruder_manager.getActiveExtruderStacks() + materials = [global_container_stack.material] if active_extruder in extruder_stacks: extruder_stacks.remove(active_extruder) extruder_stacks = [active_extruder] + extruder_stacks + materials = [extruder.material for extruder in extruder_stacks] - # if ExtruderManager.getInstance().getActiveExtruderStacks(): - # # Multi-extruder machine detected. - # materials = [extruder.material for extruder in extruder_stacks] - # else: - # # Machine with one extruder. - # materials = [global_container_stack.material] - # - # # Fetch the list of usable qualities across all extruders. - # # The actual list of quality profiles come from the first extruder in the extruder list. - # result = QualityManager.getInstance().findAllQualitiesForMachineAndMaterials(global_stack_definition, - # materials) - # - # for quality in QualityManager.getInstance().findAllUsableQualitiesForMachineAndExtruders( - # global_container_stack, extruder_stacks): - # if quality not in result: - # result.append(quality) - quality_list = QualityManager.getInstance().findAllUsableQualitiesForMachineAndExtruders(global_container_stack, - extruder_stacks) + # Fetch the list of usable qualities across all extruders. + # The actual list of quality profiles come from the first extruder in the extruder list. + result = QualityManager.getInstance().findAllUsableQualitiesForMachineAndExtruders(global_container_stack, extruder_stacks) - return quality_list + # The usable quality types are set + quality_type_set = set([x.getMetaDataEntry("quality_type") for x in result]) + + # Fetch all qualities available for this machine and the materials selected in extruders + all_qualities = QualityManager.getInstance().findAllQualitiesForMachineAndMaterials(global_stack_definition, materials) + + # If in the all qualities there is some of them that are not available due to incompatibility with materials + # we also add it so that they will appear in the slide quality bar. However in recomputeItems will be marked as + # not available so they will be shown in gray + for quality in all_qualities: + if quality.getMetaDataEntry("quality_type") not in quality_type_set: + result.append(quality) + + return result ## Re-computes the items in this model, and adds the layer height role. def _recomputeItems(self): @@ -96,21 +96,14 @@ class ProfilesModel(InstanceContainersModel): extruder_manager = ExtruderManager.getInstance() active_extruder = extruder_manager.getActiveExtruderStack() extruder_stacks = extruder_manager.getActiveExtruderStacks() - material = global_container_stack.material if active_extruder in extruder_stacks: extruder_stacks.remove(active_extruder) extruder_stacks = [active_extruder] + extruder_stacks - material = active_extruder.material - # Get a list of available qualities for this machine and material + # Get a list of usable/available qualities for this machine and material qualities = QualityManager.getInstance().findAllUsableQualitiesForMachineAndExtruders(global_container_stack, extruder_stacks) - all_qualities = [] - for extruder in extruder_stacks: - all_qualities.append(QualityManager.getInstance().findAllQualitiesForMachineMaterial(global_container_stack.getBottom(), extruder.material)) - all_qualities2 = QualityManager.getInstance().findAllUsableQualitiesForMachineAndExtruders(global_container_stack, []) - container_registry = ContainerRegistry.getInstance() machine_manager = Application.getInstance().getMachineManager() @@ -129,7 +122,7 @@ class ProfilesModel(InstanceContainersModel): tmp_all_quality_items[quality_type] = {"suitable_container": None, "all_containers": []} tmp_all_quality_items[quality_type]["all_containers"].append(item) - if tmp_all_quality_items[quality_type]["suitable_container"] is None and profile[0] in qualities: + if tmp_all_quality_items[quality_type]["suitable_container"] is None: tmp_all_quality_items[quality_type]["suitable_container"] = item # reverse the ordering (finest first, coarsest last) @@ -154,7 +147,7 @@ class ProfilesModel(InstanceContainersModel): for item in containers: profile = container_registry.findContainers(id=item["id"]) if not profile: - item["layer_height"] = "" # Can't update a profile that is unknown. + self._setItemLayerHeight(item, "", unit) item["available"] = False yield item continue From c33bd80818a72995755bb3c3eeb9b43cc15c26ce Mon Sep 17 00:00:00 2001 From: alekseisasin Date: Mon, 25 Sep 2017 15:38:47 +0200 Subject: [PATCH 5/6] Added NOT SUPPORTED profile for UM2++ and quality slider validation if value:-1 CURA-4182 --- resources/qml/SidebarSimple.qml | 11 ++++++++--- .../ultimaker2_plus/um2p_tpu_0.8_normal.inst.cfg | 15 +++++++++++++++ 2 files changed, 23 insertions(+), 3 deletions(-) create mode 100644 resources/quality/ultimaker2_plus/um2p_tpu_0.8_normal.inst.cfg diff --git a/resources/qml/SidebarSimple.qml b/resources/qml/SidebarSimple.qml index e53d07ae69..d93dd67550 100644 --- a/resources/qml/SidebarSimple.qml +++ b/resources/qml/SidebarSimple.qml @@ -138,8 +138,13 @@ Item function reset () { qualityModel.clear() - qualityModel.totalTicks = Cura.ProfilesModel.rowCount() - 1 // minus one, because slider starts from 0 qualityModel.availableTotalTicks = -1 + + // check, the ticks count cannot be less than zero + if(Cura.ProfilesModel.rowCount() != 0) + qualityModel.totalTicks = Cura.ProfilesModel.rowCount() - 1 // minus one, because slider starts from 0 + else + qualityModel.totalTicks = 0 } } @@ -240,8 +245,8 @@ Item enabled: qualityModel.availableTotalTicks > 0 updateValueWhileDragging : false - minimumValue: qualityModel.qualitySliderAvailableMin - maximumValue: qualityModel.qualitySliderAvailableMax + minimumValue: qualityModel.qualitySliderAvailableMin >= 0 ? qualityModel.qualitySliderAvailableMin : 0 + maximumValue: qualityModel.qualitySliderAvailableMax >= 0 ? qualityModel.qualitySliderAvailableMax : 0 stepSize: 1 value: qualityModel.activeQualityId diff --git a/resources/quality/ultimaker2_plus/um2p_tpu_0.8_normal.inst.cfg b/resources/quality/ultimaker2_plus/um2p_tpu_0.8_normal.inst.cfg new file mode 100644 index 0000000000..65f9ba383e --- /dev/null +++ b/resources/quality/ultimaker2_plus/um2p_tpu_0.8_normal.inst.cfg @@ -0,0 +1,15 @@ +[general] +version = 2 +name = Not Supported +definition = ultimaker2_plus + +[metadata] +weight = 0 +type = quality +quality_type = normal +material = generic_tpu_ultimaker2_plus_0.8_mm +supported = False +setting_version = 3 + +[values] + From 355aa36bb4b09377991ec915a48959e9758782af Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Tue, 26 Sep 2017 09:06:38 +0200 Subject: [PATCH 6/6] Ignore SolidWorksPlugin Please. --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 03ae94a87f..616d325ffb 100644 --- a/.gitignore +++ b/.gitignore @@ -33,6 +33,7 @@ cura.desktop .settings #Externally located plug-ins. +plugins/CuraSolidWorksPlugin plugins/Doodle3D-cura-plugin plugins/GodMode plugins/PostProcessingPlugin